public async Task <IActionResult> Authorize(OpenIdConnectRequest request) { // Retrieve the claims stored in the authentication cookie. // If they can't be extracted, redirect the user to the login page. var result = await HttpContext.AuthenticateAsync(); if (result == null || !result.Succeeded || request.HasPrompt(OpenIddictConstants.Prompts.Login)) { return(RedirectToLoginPage(request)); } // If a max_age parameter was provided, ensure that the cookie is not too old. // If it's too old, automatically redirect the user agent to the login page. if (request.MaxAge != null && result.Properties.IssuedUtc != null && DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value)) { return(RedirectToLoginPage(request)); } var application = await _applicationManager.FindByClientIdAsync(request.ClientId); if (application == null) { return(View("Error", new ErrorViewModel { Error = OpenIddictConstants.Errors.InvalidClient, ErrorDescription = T["The specified 'client_id' parameter is invalid."] })); } var authorizations = await _authorizationManager.FindAsync( subject : _userManager.GetUserId(result.Principal), client : await _applicationManager.GetIdAsync(application), status : OpenIddictConstants.Statuses.Valid, type : OpenIddictConstants.AuthorizationTypes.Permanent, scopes : ImmutableArray.CreateRange(request.GetScopes())); switch (await _applicationManager.GetConsentTypeAsync(application)) { case OpenIddictConstants.ConsentTypes.External when authorizations.IsEmpty: return(RedirectToClient(new OpenIdConnectResponse { Error = OpenIddictConstants.Errors.ConsentRequired, ErrorDescription = T["The logged in user is not allowed to access this client application."] })); case OpenIddictConstants.ConsentTypes.Implicit: case OpenIddictConstants.ConsentTypes.External when authorizations.Any(): case OpenIddictConstants.ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(OpenIddictConstants.Prompts.Consent): return(await IssueTokensAsync(result.Principal, request, application, authorizations.LastOrDefault())); case OpenIddictConstants.ConsentTypes.Explicit when request.HasPrompt(OpenIddictConstants.Prompts.None): return(RedirectToClient(new OpenIdConnectResponse { Error = OpenIddictConstants.Errors.ConsentRequired, ErrorDescription = T["Interactive user consent is required."] })); default: return(View(new AuthorizeViewModel { ApplicationName = await _applicationManager.GetDisplayNameAsync(application), RequestId = request.RequestId, Scope = request.Scope })); } }
public async Task <IActionResult> Authorize() { var response = HttpContext.GetOpenIddictServerResponse(); if (response != null) { return(View("Error", new ErrorViewModel { Error = response.Error, ErrorDescription = response.ErrorDescription })); } var request = HttpContext.GetOpenIddictServerRequest(); if (request == null) { return(NotFound()); } // Retrieve the claims stored in the authentication cookie. // If they can't be extracted, redirect the user to the login page. var result = await HttpContext.AuthenticateAsync(); if (result == null || !result.Succeeded || request.HasPrompt(Prompts.Login)) { return(RedirectToLoginPage(request)); } // If a max_age parameter was provided, ensure that the cookie is not too old. // If it's too old, automatically redirect the user agent to the login page. if (request.MaxAge != null && result.Properties.IssuedUtc != null && DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value)) { return(RedirectToLoginPage(request)); } var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? throw new InvalidOperationException("The application details cannot be found."); var authorizations = await _authorizationManager.FindAsync( subject : result.Principal.GetUserIdentifier(), client : await _applicationManager.GetIdAsync(application), status : Statuses.Valid, type : AuthorizationTypes.Permanent, scopes : request.GetScopes()).ToListAsync(); switch (await _applicationManager.GetConsentTypeAsync(application)) { case ConsentTypes.External when !authorizations.Any(): return(Forbid(new AuthenticationProperties(new Dictionary <string, string> { [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = S["The logged in user is not allowed to access this client application."] }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)); case ConsentTypes.Implicit: case ConsentTypes.External when authorizations.Any(): case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent): var identity = new ClaimsIdentity(result.Principal.Claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); identity.AddClaim(OpenIdConstants.Claims.EntityType, OpenIdConstants.EntityTypes.User, Destinations.AccessToken, Destinations.IdentityToken); // Note: while ASP.NET Core Identity uses the legacy WS-Federation claims (exposed by the ClaimTypes class), // OpenIddict uses the newer JWT claims defined by the OpenID Connect specification. To ensure the mandatory // subject claim is correctly populated (and avoid an InvalidOperationException), it's manually added here. if (string.IsNullOrEmpty(result.Principal.FindFirst(Claims.Subject)?.Value)) { identity.AddClaim(new Claim(Claims.Subject, result.Principal.GetUserIdentifier())); } principal.SetScopes(request.GetScopes()); principal.SetResources(await GetResourcesAsync(request.GetScopes())); // Automatically create a permanent authorization to avoid requiring explicit consent // for future authorization or token requests containing the same scopes. var authorization = authorizations.LastOrDefault(); if (authorization == null) { authorization = await _authorizationManager.CreateAsync( principal : principal, subject : principal.GetUserIdentifier(), client : await _applicationManager.GetIdAsync(application), type : AuthorizationTypes.Permanent, scopes : principal.GetScopes()); } principal.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization)); foreach (var claim in principal.Claims) { claim.SetDestinations(GetDestinations(claim, principal)); } return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)); case ConsentTypes.Explicit when request.HasPrompt(Prompts.None): return(Forbid(new AuthenticationProperties(new Dictionary <string, string> { [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = S["Interactive user consent is required."] }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)); default: return(View(new AuthorizeViewModel { ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application), RequestId = request.RequestId, Scope = request.Scope })); } IActionResult RedirectToLoginPage(OpenIddictRequest request) { // If the client application requested promptless authentication, // return an error indicating that the user is not logged in. if (request.HasPrompt(Prompts.None)) { return(Forbid(new AuthenticationProperties(new Dictionary <string, string> { [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired, [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = S["The user is not logged in."] }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)); } string GetRedirectUrl() { // Override the prompt parameter to prevent infinite authentication/authorization loops. var parameters = Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); parameters[Parameters.Prompt] = "continue"; return(Request.PathBase + Request.Path + QueryString.Create(parameters)); } return(Challenge(new AuthenticationProperties { RedirectUri = GetRedirectUrl() })); } }
public async Task <IActionResult> Edit(EditOpenIdApplicationViewModel model, string returnUrl = null) { if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageApplications)) { return(Unauthorized()); } var application = await _applicationManager.FindByPhysicalIdAsync(model.Id); if (application == null) { return(NotFound()); } // If the application was a public client and is now a confidential client, ensure a client secret was provided. if (string.IsNullOrEmpty(model.ClientSecret) && !string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase) && await _applicationManager.IsPublicAsync(application)) { ModelState.AddModelError(nameof(model.ClientSecret), T["Setting a new client secret is required."]); } if (!string.IsNullOrEmpty(model.ClientSecret) && string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { ModelState.AddModelError(nameof(model.ClientSecret), T["No client secret can be set for public applications."]); } if (ModelState.IsValid) { var other = await _applicationManager.FindByClientIdAsync(model.ClientId); if (other != null && !string.Equals( await _applicationManager.GetIdAsync(other), await _applicationManager.GetIdAsync(application), StringComparison.Ordinal)) { ModelState.AddModelError(nameof(model.ClientId), T["The client identifier is already taken by another application."]); } } if (!ModelState.IsValid) { ViewData[nameof(OpenIdServerSettings)] = await GetServerSettingsAsync(); ViewData["ReturnUrl"] = returnUrl; return(View(model)); } var descriptor = new OpenIdApplicationDescriptor(); await _applicationManager.PopulateAsync(descriptor, application); descriptor.ClientId = model.ClientId; descriptor.ConsentType = model.ConsentType; descriptor.DisplayName = model.DisplayName; descriptor.Type = model.Type; if (!string.IsNullOrEmpty(model.ClientSecret)) { descriptor.ClientSecret = model.ClientSecret; } if (string.Equals(descriptor.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { descriptor.ClientSecret = null; } if (model.AllowLogoutEndpoint) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.Endpoints.Logout); } if (model.AllowAuthorizationCodeFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); } if (model.AllowClientCredentialsFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); } if (model.AllowImplicitFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.GrantTypes.Implicit); } if (model.AllowPasswordFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.GrantTypes.Password); } if (model.AllowRefreshTokenFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); } if (model.AllowAuthorizationCodeFlow || model.AllowImplicitFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.Endpoints.Authorization); } if (model.AllowAuthorizationCodeFlow || model.AllowClientCredentialsFlow || model.AllowPasswordFlow || model.AllowRefreshTokenFlow) { descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); } else { descriptor.Permissions.Remove(OpenIddictConstants.Permissions.Endpoints.Token); } descriptor.Roles.Clear(); foreach (string selectedRole in (model.RoleEntries .Where(role => role.Selected) .Select(role => role.Name))) { descriptor.Roles.Add(selectedRole); } descriptor.PostLogoutRedirectUris.Clear(); foreach (Uri uri in (from uri in model.PostLogoutRedirectUris?.Split(new[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>() select new Uri(uri, UriKind.Absolute))) { descriptor.PostLogoutRedirectUris.Add(uri); } descriptor.RedirectUris.Clear(); foreach (Uri uri in (from uri in model.RedirectUris?.Split(new[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>() select new Uri(uri, UriKind.Absolute))) { descriptor.RedirectUris.Add(uri); } await _applicationManager.UpdateAsync(application, descriptor); if (string.IsNullOrEmpty(returnUrl)) { return(RedirectToAction("Index")); } return(LocalRedirect(returnUrl)); }
public async Task <IActionResult> Edit(EditOpenIdApplicationViewModel model, string returnUrl = null) { if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageApplications)) { return(Forbid()); } var application = await _applicationManager.FindByPhysicalIdAsync(model.Id); if (application == null) { return(NotFound()); } // If the application was a public client and is now a confidential client, ensure a client secret was provided. if (string.IsNullOrEmpty(model.ClientSecret) && !string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase) && await _applicationManager.HasClientTypeAsync(application, OpenIddictConstants.ClientTypes.Public)) { ModelState.AddModelError(nameof(model.ClientSecret), S["Setting a new client secret is required."]); } if (!string.IsNullOrEmpty(model.ClientSecret) && string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { ModelState.AddModelError(nameof(model.ClientSecret), S["No client secret can be set for public applications."]); } if (ModelState.IsValid) { var other = await _applicationManager.FindByClientIdAsync(model.ClientId); if (other != null && !string.Equals( await _applicationManager.GetIdAsync(other), await _applicationManager.GetIdAsync(application), StringComparison.Ordinal)) { ModelState.AddModelError(nameof(model.ClientId), S["The client identifier is already taken by another application."]); } } if (!ModelState.IsValid) { ViewData[nameof(OpenIdServerSettings)] = await GetServerSettingsAsync(); ViewData["ReturnUrl"] = returnUrl; return(View(model)); } var settings = new OpenIdApplicationSettings() { AllowAuthorizationCodeFlow = model.AllowAuthorizationCodeFlow, AllowClientCredentialsFlow = model.AllowClientCredentialsFlow, AllowHybridFlow = model.AllowHybridFlow, AllowImplicitFlow = model.AllowImplicitFlow, AllowLogoutEndpoint = model.AllowLogoutEndpoint, AllowPasswordFlow = model.AllowPasswordFlow, AllowRefreshTokenFlow = model.AllowRefreshTokenFlow, ClientId = model.ClientId, ClientSecret = model.ClientSecret, ConsentType = model.ConsentType, DisplayName = model.DisplayName, PostLogoutRedirectUris = model.PostLogoutRedirectUris, RedirectUris = model.RedirectUris, Roles = model.RoleEntries.Where(x => x.Selected).Select(x => x.Name).ToArray(), Scopes = model.ScopeEntries.Where(x => x.Selected).Select(x => x.Name).ToArray(), Type = model.Type }; await _applicationManager.UpdateDescriptorFromSettings(settings, application); if (string.IsNullOrEmpty(returnUrl)) { return(RedirectToAction(nameof(Index))); } return(this.LocalRedirect(returnUrl, true)); }