Перенаправление не происходит в открытом идентификаторе "OnAuthorizatioCodeReceived" - PullRequest
0 голосов
/ 24 декабря 2018

Я использую Azure ADB2C для аутентификации и авторизации и использую поток Open Id Connect.Мне нужно перенаправить пользователя на домашнюю страницу приложения с полученным токеном доступа, прикрепленным к URL-адресу домашней страницы в качестве параметра запроса из «OnAuthorizationCodeReceived».Но это не работает.Ниже приведен мой код.

Делая это, я намерен поймать токен доступа и токен идентификатора из URL перенаправления.И это одностраничное приложение.Я пробовал MSAL.js, но у него есть проблемы с совместимостью браузера и даже несколько раз у разных провайдеров идентификации.Поэтому я решил открыть идентификатор пользователя из c # backend

  public static class AzureAdB2CAuthenticationBuilderExtensions
{
    public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder)
        => builder.AddAzureAdB2C(_ =>
        {
        });

    public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action<AzureAdB2COptions> configureOptions)
    {
        builder.Services.Configure(configureOptions);
        builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsSetup>();
        builder.AddOpenIdConnect();
        return builder;
    }

    public class OpenIdConnectOptionsSetup : IConfigureNamedOptions<OpenIdConnectOptions>
    {

        public OpenIdConnectOptionsSetup(IOptions<AzureAdB2COptions> b2cOptions)
        {
            AzureAdB2COptions = b2cOptions.Value;
        }

        public AzureAdB2COptions AzureAdB2COptions { get; set; }

        public void Configure(string name, OpenIdConnectOptions options)
        {
            options.ClientId = AzureAdB2COptions.ClientId;
            options.Authority = AzureAdB2COptions.Authority;
            options.UseTokenLifetime = true;
            //options.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/console/home");
            options.TokenValidationParameters = new TokenValidationParameters() { SaveSigninToken=true, NameClaimType = "name" };
            options.SaveTokens = true;
            options.Events = new OpenIdConnectEvents()
            {
                OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
                OnRemoteFailure = OnRemoteFailure,
                OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
                OnTokenValidated= OnTokenValidated,
                OnTokenResponseReceived= OnTokenResponseReceived
            };
        }

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

        public Task OnRedirectToIdentityProvider(RedirectContext context)
        {
            var defaultPolicy = AzureAdB2COptions.DefaultPolicy;
            if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) &&
                !policy.Equals(defaultPolicy))
            {
                context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile;
                context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
                context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower().Replace(defaultPolicy.ToLower(), policy.ToLower());
                context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty);
            }
            else if (!string.IsNullOrEmpty(AzureAdB2COptions.ApiUrl))
            {
                context.ProtocolMessage.Scope += $" offline_access {AzureAdB2COptions.ApiScopes}";
                context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken;
            }
            return Task.FromResult(0);
        }

        public Task OnRemoteFailure(RemoteFailureContext context)
        {
            context.HandleResponse();
            // Handle the error code that Azure AD B2C throws when trying to reset a password from the login page 
            // because password reset is not supported by a "sign-up or sign-in policy"
            if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118"))
            {
                // If the user clicked the reset password link, redirect to the reset password route
                context.Response.Redirect("/Session/ResetPassword");
            }
            else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied"))
            {
                context.Response.Redirect("/");
            }
            else
            {
                context.Response.Redirect("/Home/Error?message=" + context.Failure.Message);
            }
            return Task.FromResult(0);
        }

        public Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
        {

            // Use MSAL to swap the code for an access token
            // Extract the code from the response notification
            var code = context.ProtocolMessage.Code;

            string signedInUserID = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
            TokenCache userTokenCache = new MSALSessionCache(signedInUserID, context.HttpContext).GetMsalCacheInstance();
            ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
            try
            {
                List<string> apiScopes = new List<string>();

                AuthenticationResult result =  cca.AcquireTokenByAuthorizationCodeAsync(code, AzureAdB2COptions.ApiScopes.Split(' ')).Result;

                //context.HandleResponse();
                context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                context.Response.Redirect("http://localhost:8836/console/home?id_token="+result.IdToken+"&access_token="+result.AccessToken);
                return Task.FromResult(0);
                //context.HandleCodeRedemption(result.AccessToken, result.IdToken);

            }
            catch (Exception ex)
            {
                //TODO: Handle
                throw;
            }
        }

        public Task OnTokenValidated(TokenValidatedContext context)
        {
            try
            {
                return Task.FromResult(0);
            }
            catch (Exception ex)
            {

                throw;
            }
        }

        public Task OnTokenResponseReceived(TokenResponseReceivedContext context)
        {
            try
            {
                var cntxt = context;
                context.ProtocolMessage.RedirectUri = "/console/home";
                context.Response.Redirect("/Home/Error?message=test");
                return Task.FromResult(0);
            }
            catch (Exception ex)
            {

                throw;
            }
        }
    }
}

И это мой класс запуска

 public void ConfigureServices(IServiceCollection services)
    {

        services.Configure<AzureAdB2COptions>(Configuration.GetSection("Authentication:AzureAdB2C"));
        services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsSetup>();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
        .AddCookie();

        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });

        services.AddMvc();

        // Adds a default in-memory implementation of IDistributedCache.
        services.AddDistributedMemoryCache();
        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromHours(1);
            options.CookieHttpOnly = true;
        });
    }

1 Ответ

0 голосов
/ 28 декабря 2018

Вы должны позвонить

context.HandleResponse();

Этот метод обрабатывает ответ от сервера аутентификации и захватывает JWT.

В Microsoft Doc вы можете найти дополнительную информацию об OpenId Connect.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...