3

これに関する質問を探してみましたが、何も見つかりませんでした。

認証に Azure AD B2C を使用する ASP.NET Core 1.0 アプリがあります。署名と登録、およびサインアウトは問題なく機能します。問題は、ユーザーのプロファイルを編集しようとしたときに発生します。私の Startup.cs は次のようになります。

namespace AspNetCoreBtoC
{
    public class Startup
    {
        private IConfigurationRoot Configuration { get; }

        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                            .SetBasePath(env.ContentRootPath)
                            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                            .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IConfiguration>(Configuration);
            services.AddMvc();
            services.AddAuthentication(
                opts => opts.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                loggerFactory.AddDebug(LogLevel.Debug);
                app.UseDeveloperExceptionPage();
            }

            app.UseStaticFiles();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AutomaticChallenge = false
            });

            string signUpPolicyId = Configuration["AzureAd:SignUpPolicyId"];
            string signUpCallbackPath = Configuration["AzureAd:SignUpCallbackPath"];
            app.UseOpenIdConnectAuthentication(CreateOidConnectOptionsForPolicy(signUpPolicyId, false, signUpCallbackPath));

            string userProfilePolicyId = Configuration["AzureAd:UserProfilePolicyId"];
            string profileCallbackPath = Configuration["AzureAd:ProfileCallbackPath"];
            app.UseOpenIdConnectAuthentication(CreateOidConnectOptionsForPolicy(userProfilePolicyId, false, profileCallbackPath));

            string signInPolicyId = Configuration["AzureAd:SignInPolicyId"];
            string signInCallbackPath = Configuration["AzureAd:SignInCallbackPath"];
            app.UseOpenIdConnectAuthentication(CreateOidConnectOptionsForPolicy(signInPolicyId, true, signInCallbackPath));

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "Default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

        private OpenIdConnectOptions CreateOidConnectOptionsForPolicy(string policyId, bool autoChallenge, string callbackPath)
        {
            string aadInstance = Configuration["AzureAd:AadInstance"];
            string tenant = Configuration["AzureAd:Tenant"];
            string clientId = Configuration["AzureAd:ClientId"];
            string redirectUri = Configuration["AzureAd:RedirectUri"];

            var opts = new OpenIdConnectOptions
            {
                AuthenticationScheme = policyId,
                MetadataAddress = string.Format(aadInstance, tenant, policyId),
                ClientId = clientId,
                PostLogoutRedirectUri = redirectUri,
                ResponseType = "id_token",
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name"
                },
                CallbackPath = callbackPath,
                AutomaticChallenge = autoChallenge
            };

            opts.Scope.Add("openid");

            return opts;
        }
    }
}

これが私の AccountController で、ここからミドルウェアにチャレンジを発行します。

namespace AspNetCoreBtoC.Controllers
{
    public class AccountController : Controller
    {
        private readonly IConfiguration config;

        public AccountController(IConfiguration config)
        {
            this.config = config;
        }

        public IActionResult SignIn()
        {
            return Challenge(new AuthenticationProperties
            {
                RedirectUri = "/"
            },
            config["AzureAd:SignInPolicyId"]);
        }

        public IActionResult SignUp()
        {
            return Challenge(new AuthenticationProperties
            {
                RedirectUri = "/"
            },
            config["AzureAd:SignUpPolicyId"]);
        }

        public IActionResult EditProfile()
        {
            return Challenge(new AuthenticationProperties
            {
                RedirectUri = "/"
            },
            config["AzureAd:UserProfilePolicyId"]);
        }

        public IActionResult SignOut()
        {
            string returnUrl = Url.Action(
                action: nameof(SignedOut),
                controller: "Account",
                values: null,
                protocol: Request.Scheme);
            return SignOut(new AuthenticationProperties
            {
                RedirectUri = returnUrl
            },
            config["AzureAd:UserProfilePolicyId"],
            config["AzureAd:SignUpPolicyId"],
            config["AzureAd:SignInPolicyId"],
            CookieAuthenticationDefaults.AuthenticationScheme);
        }

        public IActionResult SignedOut()
        {
            return View();
        }
    }
}

OWINの例から適応させようとしました。私が抱えている問題は、プロファイルを編集するために、それを担当する OpenIdConnect ミドルウェアにチャレンジを発行する必要があることです。問題は、デフォルトのサインイン ミドルウェア (Cookie) を呼び出すことです。これは、ユーザーが認証されていることを認識するため、アクションは不正なものである必要があり、/Account/AccessDenied にリダイレクトしようとします (必要に応じてプロファイルを編集するために Azure AD に移動するのではなく、そのルートに何かがある)。

ASP.NET Core でユーザー プロファイル編集を正常に実装した人はいますか?

4

1 に答える 1

1

さて、私はついにそれを解決しました。ソリューションを含むセットアップに関するブログ記事を書きました: https://joonasw.net/view/azure-ad-b2c-with-aspnet-core。問題は ChallengeBehavior で、デフォルト値の Automatic ではなく、Unauthorized に設定する必要があります。現時点では、フレームワーク ChallengeResult で定義することはできなかったので、独自に作成しました。

public class MyChallengeResult : IActionResult
{
    private readonly AuthenticationProperties authenticationProperties;
    private readonly string[] authenticationSchemes;
    private readonly ChallengeBehavior challengeBehavior;

    public MyChallengeResult(
        AuthenticationProperties authenticationProperties,
        ChallengeBehavior challengeBehavior,
        string[] authenticationSchemes)
    {
        this.authenticationProperties = authenticationProperties;
        this.challengeBehavior = challengeBehavior;
        this.authenticationSchemes = authenticationSchemes;
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        AuthenticationManager authenticationManager =
            context.HttpContext.Authentication;

        foreach (string scheme in authenticationSchemes)
        {
            await authenticationManager.ChallengeAsync(
                scheme,
                authenticationProperties,
                challengeBehavior);
        }
    }
}

名前で申し訳ありません...しかし、これはコントローラーアクションから返される可能性があり、ChallengeBehavior.Unauthorizedを指定することで、すべてが正常に機能するようになりました。

于 2016-08-27T19:30:11.460 に答える