public static AuthenticationBuilder AddOpenIdConnectB2CAuthentication(this AuthenticationBuilder authenticationBuilder, B2CAuthenticationOptions authOptions, B2CPolicies b2cPolicies, IDistributedCache distributedCache) { authenticationBuilder.AddOpenIdConnect(B2CAuthConstants.OpenIdConnectB2CAuthenticationScheme, options => { options.CallbackPath = new PathString(B2CAuthConstants.B2CCallbackPath); options.Authority = authOptions.Authority; options.ClientId = authOptions.ClientId; options.ClientSecret = authOptions.ClientSecret; options.SignedOutRedirectUri = authOptions.PostLogoutRedirectUri; options.ConfigurationManager = new PolicyConfigurationManager(authOptions.Authority, new[] { b2cPolicies.SignInOrSignUpPolicy, b2cPolicies.EditProfilePolicy, b2cPolicies.ResetPasswordPolicy }); options.Events = CreateOpenIdConnectEventHandlers(authOptions, b2cPolicies, distributedCache); options.ResponseType = OpenIdConnectResponseType.CodeIdToken; options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }; // it will fall back on using DefaultSignInScheme if not set //options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.Scope.Add("offline_access"); options.Scope.Add($"{authOptions.ApiIdentifier}/read_booking"); options.Scope.Add($"{authOptions.ApiIdentifier}/update_booking"); }); return(authenticationBuilder); }
public static void UseOpenIdConnectB2CAuthentication(this IApplicationBuilder app, B2CAuthenticationOptions authOptions, B2CPolicies b2cPolicies, IDistributedCache distributedCache, bool automaticChallenge = false) { var openIdConnectOptions = new OpenIdConnectOptions { AuthenticationScheme = B2CAuthConstants.OpenIdConnectB2CAuthenticationScheme, AutomaticChallenge = automaticChallenge, CallbackPath = new PathString(B2CAuthConstants.B2CCallbackPath), Authority = authOptions.Authority, ClientId = authOptions.ClientId, ClientSecret = authOptions.ClientSecret, PostLogoutRedirectUri = authOptions.PostLogoutRedirectUri, ConfigurationManager = new PolicyConfigurationManager(authOptions.Authority, new[] { b2cPolicies.SignInOrSignUpPolicy, b2cPolicies.EditProfilePolicy }), Events = CreateOpenIdConnectEventHandlers(authOptions, b2cPolicies, distributedCache), ResponseType = OpenIdConnectResponseType.CodeIdToken, TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }, SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme }; openIdConnectOptions.Scope.Add("offline_access"); app.UseOpenIdConnectAuthentication(openIdConnectOptions); }
private static IOpenIdConnectEvents CreateOpenIdConnectEventHandlers(B2CAuthenticationOptions authOptions, B2CPolicies policies, IDistributedCache distributedCache) { return(new OpenIdConnectEvents { OnRedirectToIdentityProvider = context => SetIssuerAddressAsync(context, policies.SignInOrSignUpPolicy), OnRedirectToIdentityProviderForSignOut = context => SetIssuerAddressForSignOutAsync(context, policies.SignInOrSignUpPolicy), OnAuthorizationCodeReceived = async context => { try { var userId = context.Ticket.Principal.FindFirst(B2CAuthConstants.ObjectId).Value; var credential = new ClientCredential(authOptions.ClientId, authOptions.ClientSecret); var authenticationContext = new AuthenticationContext(authOptions.Authority, new DistributedTokenCache(distributedCache, userId)); var result = await authenticationContext.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code, new Uri(context.TokenEndpointRequest.RedirectUri, UriKind.RelativeOrAbsolute), credential, new[] { authOptions.ClientId }, context.Ticket.Principal.FindFirst(B2CAuthConstants.AcrClaimType).Value); context.HandleCodeRedemption(); } catch { context.HandleResponse(); } }, OnTokenValidated = context => { var claimsIdentity = (ClaimsIdentity)context.Ticket.Principal.Identity; claimsIdentity.AddClaim(new Claim(BookFastClaimTypes.InteractorRole, InteractorRole.Customer.ToString())); return Task.FromResult(0); }, OnAuthenticationFailed = context => { context.SkipToNextMiddleware(); return Task.FromResult(0); }, OnMessageReceived = context => { if (!string.IsNullOrEmpty(context.ProtocolMessage.Error) && !string.IsNullOrEmpty(context.ProtocolMessage.ErrorDescription) && context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90091") && context.Properties.Items[B2CAuthConstants.B2CPolicy] == policies.EditProfilePolicy) { context.Ticket = new Microsoft.AspNetCore.Authentication.AuthenticationTicket(context.HttpContext.User, context.Properties, B2CAuthConstants.OpenIdConnectB2CAuthenticationScheme); context.HandleResponse(); } return Task.FromResult(0); } }); }
private static OpenIdConnectEvents CreateOpenIdConnectEventHandlers(B2CAuthenticationOptions authOptions, B2CPolicies policies, IDistributedCache distributedCache) { return(new OpenIdConnectEvents { OnRedirectToIdentityProvider = context => SetIssuerAddressAsync(context, policies.SignInOrSignUpPolicy), OnRedirectToIdentityProviderForSignOut = context => SetIssuerAddressForSignOutAsync(context, policies.SignInOrSignUpPolicy), OnAuthorizationCodeReceived = async context => { try { var principal = context.Principal; var userTokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(B2CAuthConstants.ObjectIdClaimType).Value).GetMSALCache(); var client = new ConfidentialClientApplication(authOptions.ClientId, authOptions.GetAuthority(principal.FindFirst(B2CAuthConstants.AcrClaimType).Value), "https://app", // it's not really needed new ClientCredential(authOptions.ClientSecret), userTokenCache, null); var result = await client.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code, new[] { $"{authOptions.ApiIdentifier}/read_booking", $"{authOptions.ApiIdentifier}/update_booking" }); context.HandleCodeRedemption(result.AccessToken, result.IdToken); } catch (Exception ex) { context.Fail(ex); } }, OnTokenValidated = context => { var claimsIdentity = (ClaimsIdentity)context.Principal.Identity; claimsIdentity.AddClaim(new Claim(BookFastClaimTypes.InteractorRole, InteractorRole.Customer.ToString())); return Task.FromResult(0); }, OnAuthenticationFailed = context => { context.Fail(context.Exception); return Task.FromResult(0); }, OnMessageReceived = context => { if (!string.IsNullOrEmpty(context.ProtocolMessage.Error) && !string.IsNullOrEmpty(context.ProtocolMessage.ErrorDescription)) { if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90091")) // cancel profile editing { context.HandleResponse(); context.Response.Redirect("/"); } else if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90118")) // forgot password { context.HandleResponse(); context.Response.Redirect("/Account/ResetPassword"); } } return Task.FromResult(0); } }); }
public CustomerAccessTokenProvider(IOptions <B2CAuthenticationOptions> authOptions, IHttpContextAccessor httpContextAccessor, IDistributedCache distributedCache) { this.authOptions = authOptions.Value; this.httpContextAccessor = httpContextAccessor; this.distributedCache = distributedCache; }