2016-08-25 54 views
2

我試圖尋找與此有關的問題,但找不到任何東西。Azure AD B2C與ASP.NET核心 - 無法去編輯配置文件

我有一個ASP.NET Core 1.0應用程序,它使用Azure AD B2C進行身份驗證。簽署和註冊以及退出工作就好了。當我嘗試去編輯用戶的個人資料時,問題就來了。這裏是我的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中間件提出質疑。問題在於它調用了中間件(Cookies)中的默認簽名,這實現了用戶的身份驗證,因此該操作必須是未授權的,並嘗試重定向到/ Account/AccessDenied(即使我甚至沒有在該路線上有任何東西),而不是去Azure AD編輯該配置文件,因爲它應該。

是否有人在ASP.NET Core中成功實現了用戶配置文件編輯?

回答

1

那麼,我終於解決了它。我寫了一篇博客文章,內容包括解決方案:https://joonasw.net/view/azure-ad-b2c-with-aspnet-core。問題是ChallengeBehavior,它必須設置爲Unauthorized,而不是默認值Automatic。這是不可能與此刻的框架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,我得到了一切應有的工作。