【问题标题】:OpenIdConnectEvents OnAuthorizationCodeReceived not firingOpenIdConnectEvents OnAuthorizationCodeReceived 未触发
【发布时间】:2018-10-17 00:03:02
【问题描述】:

我在我的 Dotnet 核心 Web 应用程序中使用 Azure AD 登录,它应该会触发 OnAuthorizationCodeReceived 事件,但它没有被触发。

你能解释一下吗?

 public void Configure(string name, OpenIdConnectOptions options)
            {
                JsonFileConfigurationService config = new JsonFileConfigurationService();
                options.ClientId = config.AzureAdClientId;
                options.Authority = $"{config.AzureAdInstance}{config.AzureAdTenantId}";
                options.UseTokenLifetime = true;
                options.CallbackPath = config.AzureAdCallbackPath;
                options.RequireHttpsMetadata = false;
                var allScopes = $"{_azureOptions.Scopes} {_azureOptions.GraphScopes}".Split(new[] { ' ' });
                foreach (var scope in allScopes) { options.Scope.Add(scope); }

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    // Instead of using the default validation (validating against a single issuer value, as we do in line of business apps),
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,

                    // If the app is meant to be accessed by entire organizations, add your issuer validation logic here.
                    //IssuerValidator = (issuer, securityToken, validationParameters) => {
                    //    if (myIssuerValidationLogic(issuer)) return issuer;
                    //}
                };

                options.Events = new OpenIdConnectEvents
                {
                    OnTicketReceived = context =>
                    {
                        // If your authentication logic is based on users then add your logic here
                        return Task.CompletedTask;
                    },
                    OnAuthenticationFailed = context =>
                    {
                        context.Response.Redirect("/Home/Error");
                        context.HandleResponse(); // Suppress the exception
                        return Task.CompletedTask;
                    },
                    OnAuthorizationCodeReceived = async (context) =>
                    {
                        var code = context.ProtocolMessage.Code;
                        var identifier = context.Principal.FindFirst(config.AzureAdObjectIdentifierType).Value;
                        var memoryCache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
                        var graphScopes = _azureOptions.GraphScopes.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        var cca = new ConfidentialClientApplication(
                            _azureOptions.ClientId,
                            _azureOptions.BaseUrl + _azureOptions.CallbackPath,
                            new ClientCredential(_azureOptions.ClientSecret),
                            new SessionTokenCache(identifier, memoryCache).GetCacheInstance(),
                            null);
                        var result = await cca.AcquireTokenByAuthorizationCodeAsync(code, graphScopes);

                        // Check whether the login is from the MSA tenant. 
                        // The sample uses this attribute to disable UI buttons for unsupported operations when the user is logged in with an MSA account.
                        var currentTenantId = context.Principal.FindFirst(config.AzureAdTenantId).Value;
                        if (currentTenantId == "9188040d-6c67-4c5b-b112-36a304b66dad")
                        {
                            // MSA (Microsoft Account) is used to log in
                        }

                        context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                    },
                    // If your application needs to do authenticate single users, add your user validation below.
                    //OnTokenValidated = context =>
                    //{
                    //    return myUserValidationLogic(context.Ticket.Principal);
                    //}
                };
            }

【问题讨论】:

    标签: c# .net authentication azure-active-directory openid-connect


    【解决方案1】:

    您应该使用混合模式并将响应类型设置为“code id_token”,默认为“id_token”: options.ResponseType = OpenIdConnectResponseType.CodeIdToken

    【讨论】:

    • 谢谢 - 这是事件处理程序没有命中的原因。
    • 在我的情况下,它没有触发 OnAuthorizationCodeReceived 事件,在添加上述代码后,现在它可以正常工作了。谢谢。
    【解决方案2】:

    我遇到了类似的问题,似乎没有调用事件。不幸的是没有看到更多的代码。我假设您提供的方法在实现IConfigureNamedOptions&lt;OpenIdConnectOptions&gt; 的类中。

    我猜你也已经通过断点或日志证明该方法被实际调用了。

    要尝试的另一件事是停止将新的OpenIdConnectEvents 实例分配给options.Events(即options.Events = new OpenIdConnectEvents)。 OpenIdConnectOptions 的构造函数为Events 属性分配了一个值,因此通过为该属性重新分配一个新实例,您可以丢弃其他配置代码可能添加的任何事件挂钩。我在网上找到的许多示例代码确实像您一样分配了一个新实例,但似乎它可能会给我带来问题。或者将您的事件代码添加到现有实例,例如

    options.Events.OnAuthorizationCodeReceived = async (context) =>
    {
        var code = context.ProtocolMessage.Code;
        var identifier = context.Principal.FindFirst(config.AzureAdObjectIdentifierType).Value;
        var memoryCache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
        var graphScopes = _azureOptions.GraphScopes.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    
        var cca = new ConfidentialClientApplication(
            _azureOptions.ClientId,
            _azureOptions.BaseUrl + _azureOptions.CallbackPath,
            new ClientCredential(_azureOptions.ClientSecret),
            new SessionTokenCache(identifier, memoryCache).GetCacheInstance(),
            null);
        var result = await cca.AcquireTokenByAuthorizationCodeAsync(code, graphScopes);
    
        // Check whether the login is from the MSA tenant. 
        // The sample uses this attribute to disable UI buttons for unsupported operations when the user is logged in with an MSA account.
        var currentTenantId = context.Principal.FindFirst(config.AzureAdTenantId).Value;
        if (currentTenantId == "9188040d-6c67-4c5b-b112-36a304b66dad")
        {
            // MSA (Microsoft Account) is used to log in
        }
    
        context.HandleCodeRedemption(result.AccessToken, result.IdToken);
    }
    

    当然,这仍然意味着您可能会覆盖其他一些处理程序(即options.Events.OnAuthorizationCodeReceived 可能已经有一个处理程序)。所以你可以先捕获它并等待结果,例如

    var existingHandler = options.Events.OnAuthorizationCodeReceived;
    options.Events.OnAuthorizationCodeReceived = async (context) =>
    {    
        await existingHandler(context);
    
        // Your code here...
    }
    

    最后,如果您在Startup.ConfigureServices 方法中使用AzureAdAuthenticationBuilderExtensions.AddAzureAd 方法,请检查ConfigureAzureOptions.Configure 方法是否没有按照上述讨论分配新的OpenIdConnectEvents

    【讨论】:

      猜你喜欢
      • 2022-09-29
      • 2020-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 2021-02-26
      相关资源
      最近更新 更多