2017-08-30 46 views
1

我有一個ASP.NET Core 2.0應用程序設置,我想使用AzureAd與我公司的目錄進行身份驗證。我已經設置了類和啓動方法,並使驗證塊工作,我遇到的問題是我正在嘗試設置OnAuthorizationCodeReceived事件的事件處理程序,以便我可以請求一個用戶令牌,然後用於Microsoft圖形調用。ASP.NET Core 2.0 AzureAD身份驗證不起作用

在我Startup.cs我有以下代碼

public void ConfigureServices(IServiceCollection services) 
     { 
      services.AddAuthentication(sharedOptions => 
      { 
       sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
       sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; 
       sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
      }) 
      .AddAzureAd(options => Configuration.Bind("AzureAd", options)) 
      .AddCookie(); 

      services.AddMvc(); 

      services.AddSingleton(Configuration); 
      services.AddSingleton<IGraphAuthProvider, GraphAuthProvider>(); 
      services.AddTransient<IGraphSDKHelper, GraphSDKHelper>(); 
     } 

     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
     public void Configure(IApplicationBuilder app, IHostingEnvironment env) 
     { 
      if (env.IsDevelopment()) 
      { 
       app.UseDeveloperExceptionPage(); 
       app.UseBrowserLink(); 
      } 
      else 
      { 
       app.UseExceptionHandler("/Home/Error"); 
      } 

      app.UseStaticFiles(); 

      app.UseAuthentication(); 

      app.UseMvc(routes => 
      { 
       routes.MapRoute(
        name: "default", 
        template: "{controller=Home}/{action=Index}/{id?}"); 
      }); 
     } 
在我有以下代碼AzureAdAuthenticationBuilderExtensions.cs

然後。

public static class AzureAdAuthenticationBuilderExtensions 
{   
    public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, IConfiguration configuration) 
     => builder.AddAzureAd(_ => { }, configuration); 

    public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions, 
     IConfiguration configuration) 
    { 
     builder.Services.Configure(configureOptions); 
     builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>(); 
     builder.AddOpenIdConnect(opts => 
     { 
      opts.ResponseType = "code id_token"; 

      opts.ClientId = configuration["AzureAd:ClientId"]; 
      opts.Authority = $"{configuration["AzureAd:Instance"]}{configuration["AzureAd:TenantId"]}"; 
      opts.UseTokenLifetime = true; 
      opts.CallbackPath = configuration["AzureAd:CallbackPath"]; 
      opts.ClientSecret = configuration["AzureAd:ClientSecret"]; 
      opts.RequireHttpsMetadata = false; 

      opts.Events = new OpenIdConnectEvents 
      { 
       OnAuthorizationCodeReceived = async context => 
       { 
        var credential = new ClientCredential(context.Options.ClientId, context.Options.ClientSecret); 

        var distributedCache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>(); 
        var userId = context.Principal 
         .FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier") 
         .Value; 
        var cache = new AdalDistributedTokenCache(distributedCache, userId); 
        var authContext = new AuthenticationContext(context.Options.Authority, cache); 
        await authContext.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code, 
         new Uri(context.TokenEndpointRequest.RedirectUri, UriKind.RelativeOrAbsolute), credential, context.Options.Resource); 
        context.HandleCodeRedemption(); 
       } 
      }; 
     }); 
     return builder; 
    } 

    private class ConfigureAzureOptions: IConfigureNamedOptions<OpenIdConnectOptions> 
    { 
     private readonly AzureAdOptions _azureOptions; 

     public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions) 
     { 
      if (azureOptions != null) 
      { 
       _azureOptions = azureOptions.Value; 
      } 
     } 

     public void Configure(string name, OpenIdConnectOptions options) 
     { 
      options.ClientId = _azureOptions.ClientId; 
      options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}"; 
      options.UseTokenLifetime = true; 
      options.CallbackPath = _azureOptions.CallbackPath; 
      options.RequireHttpsMetadata = false; 
      options.ClientSecret = _azureOptions.ClientSecret; 
     } 

     public void Configure(OpenIdConnectOptions options) 
     { 
      Configure(Options.DefaultName, options); 
     } 
    } 
} 

然後AddAzureAd方法被調用,我可以看到它穿行都在這個方法的代碼,但是當我把一個斷點在OnAuthorizationCodeReceived方法斷點從來沒有被擊中。我已經完成了一堆閱讀,看起來我所擁有的是正確的,所以我猜測我必須在這裏錯過簡單的東西,但找不到問題。

Editted 現在我打了OnAuthorizationCodeReceived事件,但現在,應用程序無法繼續登錄收到以下錯誤

SecurityTokenException: Unable to validate the 'id_token', no suitable ISecurityTokenValidator was found for: ''." 
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+<HandleRequestAsync>d__12.MoveNext() 

Stack Query Cookies Headers 
SecurityTokenException: Unable to validate the 'id_token', no suitable ISecurityTokenValidator was found for: ''." 
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+<HandleRequestAsync>d__12.MoveNext() 
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext() 
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext() 

回答

1

的Asp.net核心的OpenIdConnect組件2.0使用隱流量(response_type的值是id_token)。

要觸發OnAuthorizationCodeReceived事件,我們應該使用「response_type」參數包含code值的混合流(例如,id_token code)。我們需要把它通過OpenIdConnectOptions像下面的代碼:

.AddOpenIdConnect(options => 
{ 
    options.Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]); 
    options.ClientId = Configuration["AzureAd:ClientId"]; 
    options.ResponseType = "code id_token";  
}); 

options.Events = new OpenIdConnectEvents 
{ 
    OnAuthorizationCodeReceived = async context => 
    { 
     var credential = new ClientCredential(context.Options.ClientId, context.Options.ClientSecret); 

     var authContext = new AuthenticationContext(context.Options.Authority); 
     var authResult=await authContext.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code, 
      new Uri(context.TokenEndpointRequest.RedirectUri, UriKind.RelativeOrAbsolute), credential, context.Options.Resource); 
     context.HandleCodeRedemption(authResult.AccessToken, context.ProtocolMessage.IdToken); 
    }, 
}; 
+0

我更新了新的AddAzureAd方法和我現在得到的錯誤,問題是SecurityTokenException:無法驗證「id_token」,沒有合適的ISecurityTokenValidator是找到:''。「 –

+0

@PaulCavacas要調用'OnAuthorizationCodeReceived'中的'context.HandleCodeRedemption()'方法,需要id_token。或者我們都可以提供id_token和access_token。我已經更新了帖子中的代碼,請讓我幫忙。 –