public static string GetToken(HttpContext httpContext) { string response; try { // Retrieve the token with the specified scopes string[] scope = _options["Scopes"].Split(' '); string signedInUserID = httpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value; IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder.Create(_options["ClientId"]) .WithClientSecret(_options["ClientSecret"]) .WithB2CAuthority("https://emsfiiot.b2clogin.com/tfp/emsfiiot.onmicrosoft.com/B2C_1_Signin/v2.0") .Build(); ITokenCache cache = new MSALStaticCache(signedInUserID, httpContext).EnablePersistence(cca.UserTokenCache); IEnumerable <IAccount> accounts = cca.GetAccountsAsync().Result; AuthenticationResult tokenRequest = cca.AcquireTokenSilent(scope, accounts.FirstOrDefault()).ExecuteAsync().Result; if (tokenRequest.AccessToken != null) { httpContext.Response.Cookies.Append("ADB2CToken", tokenRequest.AccessToken, new CookieOptions { Expires = tokenRequest.ExpiresOn }); } response = tokenRequest.AccessToken; } catch (MsalUiRequiredException ex) { response = $"Session has expired. Please sign in again. {ex.Message}"; httpContext.Response.Redirect("/Account/SignIn"); } catch (Exception ex) { response = $"Error calling API: {ex.Message}"; } return(response); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { new EMSfIIoTApiConnector(Configuration.GetSection("AzureAdB2C")); new BoschIoTSuiteApiConnector(Configuration.GetSection("BoschIoTSuite")); new GraphApiConnector(Configuration.GetSection("AzureAdB2C")); IdentityModelEventSource.ShowPII = true; services.TryAddSingleton <CommonLocalizationService>(); services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) .AddAzureADB2C(options => { options.Instance = Configuration["AzureAdB2C:Instance"]; options.ClientId = Configuration["AzureAdB2C:ClientId"]; options.CallbackPath = Configuration["AzureAdB2C:CallbackPath"]; options.Domain = Configuration["AzureAdB2C:Domain"]; options.SignUpSignInPolicyId = Configuration["AzureAdB2C:SignUpSignInPolicyId"]; options.ResetPasswordPolicyId = Configuration["AzureAdB2C:ResetPasswordPolicyId"]; options.EditProfilePolicyId = Configuration["AzureAdB2C:EditProfilePolicyId"]; }) .AddCookie(); services.Configure <OpenIdConnectOptions>(AzureADB2CDefaults.OpenIdScheme, options => { string authority = Configuration["AzureAdB2C:Instance"] + "tfp/" + Configuration["AzureAdB2C:Domain"] + "/" + Configuration["AzureAdB2C:SignUpSignInPolicyId"] + "/v2.0"; options.ClientId = Configuration["AzureAdB2C:ClientId"]; options.Authority = authority; options.UseTokenLifetime = true; options.SaveTokens = true; options.CallbackPath = new PathString("/auth"); options.GetClaimsFromUserInfoEndpoint = true; options.ResponseMode = OpenIdConnectResponseMode.FormPost; options.TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name", }; options.Events = new OpenIdConnectEvents { OnAuthorizationCodeReceived = async ctx => { // Use MSAL to swap the code for an access token // Extract the code from the response notification var code = ctx.ProtocolMessage.Code; await GraphApiConnector.UpdateAdministrators(); string signedInUserID = ctx.Principal.FindFirst(ClaimTypes.NameIdentifier).Value; IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder.Create(Configuration["AzureAdB2C:ClientId"]) .WithB2CAuthority(authority) .WithClientSecret(Configuration["AzureAdB2C:ClientSecret"]) .Build(); var cache = new MSALStaticCache(signedInUserID, ctx.HttpContext).EnablePersistence(cca.UserTokenCache); try { AuthenticationResult result = await cca.AcquireTokenByAuthorizationCode(options.Scope, code).ExecuteAsync(); if (result.AccessToken != null) { ctx.HttpContext.Response.Cookies.Append("ADB2CToken", result.AccessToken, new CookieOptions { Expires = result.ExpiresOn }); } ctx.HandleCodeRedemption(result.AccessToken, result.IdToken); } catch (Exception ex) { throw; } }, OnRedirectToIdentityProvider = ctx => { var defaultPolicy = Configuration["AzureAdB2C:SignUpSignInPolicyId"]; if (ctx.Properties.Items.TryGetValue("Policy", out var policy) && !policy.Equals(defaultPolicy)) { ctx.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile; ctx.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken; ctx.ProtocolMessage.IssuerAddress = ctx.ProtocolMessage.IssuerAddress.ToLower().Replace(defaultPolicy.ToLower(), policy.ToLower()); ctx.Properties.Items.Remove(Configuration["AzureAdB2C:SignUpSignInPolicyId"]); } else if (!string.IsNullOrEmpty(Configuration["AzureAdB2C:Url"])) { ctx.ProtocolMessage.Scope += $" offline_access {Configuration["AzureAdB2C:Scopes"]}"; ctx.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken; } ctx.ProtocolMessage.UiLocales = ctx.HttpContext.Request.Query["culture"].ToString(); return(Task.FromResult(0)); }, OnRemoteFailure = ctx => { ctx.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 (ctx.Failure is OpenIdConnectProtocolException && ctx.Failure.Message.Contains("AADB2C90118")) { // If the user clicked the reset password link, redirect to the reset password route ctx.Response.Redirect("/Account/ResetPassword"); } else if (ctx.Failure is OpenIdConnectProtocolException && ctx.Failure.Message.Contains("access_denied")) { ctx.Response.Redirect("/"); } else { ctx.Response.Redirect("/Error?message=" + Uri.EscapeDataString(ctx.Failure.Message)); } return(Task.FromResult(0)); }, OnRemoteSignOut = ctx => { ctx.HttpContext.Response.Cookies.Delete("ADB2CToken"); return(Task.FromResult(0)); } }; });