public void Configure(string name, OpenIdConnectOptions options) { options.ClientId = azureOptions.ClientId; options.Authority = $"{azureOptions.Instance}{azureOptions.TenantId}/v2.0"; options.UseTokenLifetime = true; options.CallbackPath = azureOptions.CallbackPath; options.RequireHttpsMetadata = env.IsProduction(); options.TokenValidationParameters.NameClaimType = "preferred_username"; options.ResponseType = OpenIdConnectResponseType.CodeIdToken; options.Prompt = "select_account"; options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.Scope.Add("offline_access"); // sometimes need admin approval: options.Scope.Add("user.read"); if (azureOptions.DefaultScopes != null && azureOptions.DefaultScopes.Length > 0) { foreach (var scope in azureOptions.DefaultScopes) { options.Scope.Add(scope); } } if (azureOptions.ValidIssuers != null && azureOptions.ValidIssuers.Length > 0) { options.TokenValidationParameters.ValidIssuers = azureOptions.ValidIssuers; } options.Events = new OpenIdConnectEvents { OnUserInformationReceived = context => { return(Task.CompletedTask); }, OnTicketReceived = context => { // If your authentication logic is based on users then add your logic here return(Task.CompletedTask); }, OnAuthenticationFailed = context => { logger.LogError("OnAuthenticationFailed", context.Exception); context.Response.Redirect("/Home/Error"); context.HandleResponse(); // Suppress the exception return(Task.CompletedTask); }, OnRedirectToIdentityProviderForSignOut = context => { System.Security.Claims.ClaimsPrincipal user = context.HttpContext.User; context.ProtocolMessage.LoginHint = user.GetLoginHint(); context.ProtocolMessage.DomainHint = user.GetDomainHint(); tokenService.RemoveAccount(user); return(Task.FromResult(true)); }, OnRedirectToIdentityProvider = context => { System.Collections.Generic.IDictionary <string, object> properties = context.Properties.Parameters; if (properties.ContainsKey("scopes")) { var scopes = properties["scopes"] as string[]; if (scopes.Length > 0) { var encoded = string.Join(" ", scopes); context.ProtocolMessage.Scope = context.ProtocolMessage.Scope + " " + encoded; } } return(Task.CompletedTask); }, OnAuthorizationCodeReceived = async(context) => { // As AcquireTokenByAuthorizationCode is asynchronous we want to tell ASP.NET core // that we are handing the code even if it's not done yet, so that it does // not concurrently call the Token endpoint. context.HandleCodeRedemption(); var code = context.ProtocolMessage.Code; Microsoft.Identity.Client.AuthenticationResult result = await tokenService.GetAccessTokenByAuthorizationCodeAsync(context.Principal, code); // Do not share the access token with ASP.NET Core otherwise ASP.NET will cache it // and will not send the OAuth 2.0 request in case a further call to // AcquireTokenByAuthorizationCode in the future for incremental consent // (getting a code requesting more scopes) // Share the ID Token so that the identity of the user is known in the application (in // HttpContext.User) context.HandleCodeRedemption(null, result.IdToken); } }; }
public void Configure(string name, OpenIdConnectOptions options) { // Set the application id options.ClientId = _azureOptions.ClientId; // the authority {Instance}/{Tenant}/v2.0 // ASP.NET uses v1.0 by default options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}/v2.0"; options.UseTokenLifetime = true; // the redirect Uri: constructed from host:port/signin-oidc options.CallbackPath = _azureOptions.CallbackPath; // we are in development environment, don't do this in production options.RequireHttpsMetadata = false; // set name of user name claim options.TokenValidationParameters.NameClaimType = "preferred_username"; // We ask ASP.NET to request a Code and an Id Token options.ResponseType = OpenIdConnectResponseType.CodeIdToken; //options.Scope.Add("https://graph.microsoft.com/User.Read"); //options.Scope.Add("https://graph.microsoft.com/Mail.ReadWrite"); //options.Scope.Add("https://graph.microsoft.com/Tasks.ReadWrite.Shared"); options.Scope.Add("offline_access"); 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); }, OnRedirectToIdentityProviderForSignOut = context => { System.Security.Claims.ClaimsPrincipal user = context.HttpContext.User; context.ProtocolMessage.LoginHint = user.GetLoginHint(); context.ProtocolMessage.DomainHint = user.GetDomainHint(); _tokenService.RemoveAccount(user); return(Task.FromResult(true)); }, OnAuthorizationCodeReceived = async(context) => { // As AcquireTokenByAuthorizationCode is asynchronous we want to tell ASP.NET core // that we are handing the code even if it's not done yet, so that it does // not concurrently call the Token endpoint. context.HandleCodeRedemption(); string code = context.ProtocolMessage.Code; Microsoft.Identity.Client.AuthenticationResult result = await _tokenService.GetAccessTokenByAuthorizationCodeAsync(context.Principal, code); // Do not share the access token with ASP.NET Core otherwise ASP.NET will cache it // and will not send the OAuth 2.0 request in case a further call to // AcquireTokenByAuthorizationCode in the future for incremental consent // (getting a code requesting more scopes) // Share the ID Token so that the identity of the user is known in the application (in // HttpContext.User) context.HandleCodeRedemption(null, result.IdToken); } }; }