public async Task <string> ProcessAsync(ExtendTokenRequest extendTokenRequest) { _logger.LogDebug("Creating new JWT Token"); var handler = new JwtSecurityTokenHandler(); //Receieved JWT Token var rjwt = handler.ReadJwtToken(extendTokenRequest.JWTTokenRAW); var claims = rjwt.Claims.ToList(); //Adding the new api scope to token foreach (var aud in extendTokenRequest.AudiencesToAdd) { //If claims exist, do not add var isClaimExists = claims.Where(c => c.Type == "aud" && c.Value == aud).Any(); if (!isClaimExists) { claims.Add(new Claim("aud", aud)); } } //Getting keys var validationKey = _keys.GetValidationKeysAsync().Result.FirstOrDefault(); var credentials = new SigningCredentials(validationKey, "RS256"); JwtSecurityToken newjwt = new JwtSecurityToken(rjwt.Issuer, null, claims, rjwt.ValidFrom, rjwt.ValidTo, credentials); var signedAndEncodedToken = handler.WriteToken(newjwt); return(signedAndEncodedToken); }
/// <summary> /// Validates the JWT for Signature. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public async Task <TokenValidationResult> ValidateJWTSignature(string jwttoken) { //Validate JWT Token SecurityToken securityToken = null; var handler = new JwtSecurityTokenHandler(); handler.InboundClaimTypeMap.Clear(); var validationKey = _keys.GetValidationKeysAsync().Result.FirstOrDefault(); TokenValidationParameters validationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, ValidateIssuer = false, ValidateAudience = false, IssuerSigningKey = validationKey }; try { var id = handler.ValidateToken(jwttoken, validationParameters, out securityToken); } catch (Exception ex) { return(new TokenValidationResult { IsError = true, Error = ex.Message }); } return(new TokenValidationResult { IsError = false, Jwt = jwttoken }); }
public virtual async Task <TokenValidationResult> ValidateIdentityTokenAsync(string token, string clientId = null, bool validateLifetime = true) { _logger.LogDebug("Start identity token validation"); if (token.Length > _options.InputLengthRestrictions.Jwt) { _logger.LogError("JWT too long"); return(Invalid(OidcConstants.ProtectedResourceErrors.InvalidToken)); } if (clientId.IsMissing()) { clientId = GetClientIdFromJwt(token); if (clientId.IsMissing()) { _logger.LogError("No clientId supplied, can't find id in identity token."); return(Invalid(OidcConstants.ProtectedResourceErrors.InvalidToken)); } } _log.ClientId = clientId; _log.ValidateLifetime = validateLifetime; var client = await _clients.FindEnabledClientByIdAsync(clientId); if (client == null) { _logger.LogError("Unknown or diabled client: {clientId}.", clientId); return(Invalid(OidcConstants.ProtectedResourceErrors.InvalidToken)); } _log.ClientName = client.ClientName; _logger.LogDebug("Client found: {clientId} / {clientName}", client.ClientId, client.ClientName); var keys = await _keys.GetValidationKeysAsync(); var result = await ValidateJwtAsync(token, clientId, keys, validateLifetime); result.Client = client; if (result.IsError) { LogError("Error validating JWT"); return(result); } _log.Claims = result.Claims.ToClaimsDictionary(); _logger.LogDebug("Calling into custom token validator: {type}", _customValidator.GetType().FullName); var customResult = await _customValidator.ValidateIdentityTokenAsync(result); if (customResult.IsError) { LogError("Custom validator failed: " + (customResult.Error ?? "unknown")); return(customResult); } _log.Claims = customResult.Claims.ToClaimsDictionary(); LogSuccess(); return(customResult); }
public async Task <TokenValidationResult> ValidateIdentityTokenAsync(string token, string clientId = null, bool validateLifetime = true) { _logger.LogDebug("Start identity token validation"); if (token.Length > _options.InputLengthRestrictions.Jwt) { _logger.LogError("JWT too long"); return(Invalid(OidcConstants.ProtectedResourceErrors.InvalidToken)); } if (clientId.IsMissing()) { clientId = GetClientIdFromJwt(token); if (clientId.IsMissing()) { _logger.LogError("No clientId supplied, can't find id in identity token."); return(Invalid(OidcConstants.ProtectedResourceErrors.InvalidToken)); } } _log.ClientId = clientId; _log.ValidateLifetime = validateLifetime; var client = await _clients.FindEnabledClientByIdAsync(clientId); if (client == null) { _logger.LogError("Unknown or disabled client: {clientId}.", clientId); return(Invalid(OidcConstants.ProtectedResourceErrors.InvalidToken)); } _log.ClientName = client.ClientName; _logger.LogDebug("Client found: {clientId} / {clientName}", client.ClientId, client.ClientName); var keys = await _keys.GetValidationKeysAsync(); var result = await ValidateJwtAsync(token, clientId, keys, validateLifetime); result.Client = client; if (result.IsError) { LogError("Error validating JWT"); return(result); } _log.Claims = result.Claims.ToClaimsDictionary(); // make sure user is still active (if sub claim is present) var subClaim = result.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject); if (subClaim != null) { var principal = Principal.Create("tokenvalidator", result.Claims.ToArray()); var isActiveCtx = new IsActiveContext(principal, result.Client, IdentityServerConstants.ProfileIsActiveCallers.IdentityTokenValidation); await _profile.IsActiveAsync(isActiveCtx); if (isActiveCtx.IsActive == false) { _logger.LogError("User marked as not active: {subject}", subClaim.Value); result.IsError = true; result.Error = OidcConstants.ProtectedResourceErrors.InvalidToken; result.Claims = null; return(result); } } _logger.LogDebug("Calling into custom token validator: {type}", _customValidator.GetType().FullName); var customResult = await _customValidator.ValidateIdentityTokenAsync(result); if (customResult.IsError) { LogError("Custom validator failed: " + (customResult.Error ?? "unknown")); return(customResult); } _log.Claims = customResult.Claims.ToClaimsDictionary(); LogSuccess(); return(customResult); }
/// <summary> /// Creates the discovery document. /// </summary> /// <param name="baseUrl">The base URL.</param> /// <param name="issuerUri">The issuer URI.</param> public virtual async Task <Dictionary <string, object> > CreateDiscoveryDocumentAsync(string baseUrl, string issuerUri) { var entries = new Dictionary <string, object> { { OidcConstants.Discovery.Issuer, issuerUri } }; // jwks if (Options.Discovery.ShowKeySet) { if ((await Keys.GetValidationKeysAsync()).Any()) { entries.Add(OidcConstants.Discovery.JwksUri, baseUrl + Constants.ProtocolRoutePaths.DiscoveryWebKeys); } } // endpoints if (Options.Discovery.ShowEndpoints) { if (Options.Endpoints.EnableAuthorizeEndpoint) { entries.Add(OidcConstants.Discovery.AuthorizationEndpoint, baseUrl + Constants.ProtocolRoutePaths.Authorize); } if (Options.Endpoints.EnableTokenEndpoint) { entries.Add(OidcConstants.Discovery.TokenEndpoint, baseUrl + Constants.ProtocolRoutePaths.Token); } if (Options.Endpoints.EnableUserInfoEndpoint) { entries.Add(OidcConstants.Discovery.UserInfoEndpoint, baseUrl + Constants.ProtocolRoutePaths.UserInfo); } if (Options.Endpoints.EnableEndSessionEndpoint) { entries.Add(OidcConstants.Discovery.EndSessionEndpoint, baseUrl + Constants.ProtocolRoutePaths.EndSession); } if (Options.Endpoints.EnableCheckSessionEndpoint) { entries.Add(OidcConstants.Discovery.CheckSessionIframe, baseUrl + Constants.ProtocolRoutePaths.CheckSession); } if (Options.Endpoints.EnableTokenRevocationEndpoint) { entries.Add(OidcConstants.Discovery.RevocationEndpoint, baseUrl + Constants.ProtocolRoutePaths.Revocation); } if (Options.Endpoints.EnableIntrospectionEndpoint) { entries.Add(OidcConstants.Discovery.IntrospectionEndpoint, baseUrl + Constants.ProtocolRoutePaths.Introspection); } if (Options.Endpoints.EnableDeviceAuthorizationEndpoint) { entries.Add(OidcConstants.Discovery.DeviceAuthorizationEndpoint, baseUrl + Constants.ProtocolRoutePaths.DeviceAuthorization); } if (Options.MutualTls.Enabled) { var mtlsEndpoints = new Dictionary <string, string>(); if (Options.Endpoints.EnableTokenEndpoint) { mtlsEndpoints.Add(OidcConstants.Discovery.TokenEndpoint, ConstructMtlsEndpoint(Constants.ProtocolRoutePaths.Token)); } if (Options.Endpoints.EnableTokenRevocationEndpoint) { mtlsEndpoints.Add(OidcConstants.Discovery.RevocationEndpoint, ConstructMtlsEndpoint(Constants.ProtocolRoutePaths.Revocation)); } if (Options.Endpoints.EnableIntrospectionEndpoint) { mtlsEndpoints.Add(OidcConstants.Discovery.IntrospectionEndpoint, ConstructMtlsEndpoint(Constants.ProtocolRoutePaths.Introspection)); } if (Options.Endpoints.EnableDeviceAuthorizationEndpoint) { mtlsEndpoints.Add(OidcConstants.Discovery.DeviceAuthorizationEndpoint, ConstructMtlsEndpoint(Constants.ProtocolRoutePaths.DeviceAuthorization)); } if (mtlsEndpoints.Any()) { entries.Add(OidcConstants.Discovery.MtlsEndpointAliases, mtlsEndpoints); } string ConstructMtlsEndpoint(string endpoint) { // path based if (Options.MutualTls.DomainName.IsMissing()) { return(baseUrl + endpoint.Replace(Constants.ProtocolRoutePaths.ConnectPathPrefix, Constants.ProtocolRoutePaths.MtlsPathPrefix)); } // domain based if (Options.MutualTls.DomainName.Contains(".")) { return($"https://{Options.MutualTls.DomainName}/{endpoint}"); } // sub-domain based else { var parts = baseUrl.Split("://"); return($"https://{Options.MutualTls.DomainName}.{parts[1]}{endpoint}"); } } } } // logout if (Options.Endpoints.EnableEndSessionEndpoint) { entries.Add(OidcConstants.Discovery.FrontChannelLogoutSupported, true); entries.Add(OidcConstants.Discovery.FrontChannelLogoutSessionSupported, true); entries.Add(OidcConstants.Discovery.BackChannelLogoutSupported, true); entries.Add(OidcConstants.Discovery.BackChannelLogoutSessionSupported, true); } // scopes and claims if (Options.Discovery.ShowIdentityScopes || Options.Discovery.ShowApiScopes || Options.Discovery.ShowClaims) { var resources = await ResourceStore.GetAllEnabledResourcesAsync(); var scopes = new List <string>(); // scopes if (Options.Discovery.ShowIdentityScopes) { scopes.AddRange(resources.IdentityResources.Where(x => x.ShowInDiscoveryDocument).Select(x => x.Name)); } if (Options.Discovery.ShowApiScopes) { var apiScopes = from scope in resources.ApiScopes where scope.ShowInDiscoveryDocument select scope.Name; scopes.AddRange(apiScopes); scopes.Add(IdentityServerConstants.StandardScopes.OfflineAccess); } if (scopes.Any()) { entries.Add(OidcConstants.Discovery.ScopesSupported, scopes.ToArray()); } // claims if (Options.Discovery.ShowClaims) { var claims = new List <string>(); // add non-hidden identity scopes related claims claims.AddRange(resources.IdentityResources.Where(x => x.ShowInDiscoveryDocument).SelectMany(x => x.UserClaims)); claims.AddRange(resources.ApiResources.Where(x => x.ShowInDiscoveryDocument).SelectMany(x => x.UserClaims)); claims.AddRange(resources.ApiScopes.Where(x => x.ShowInDiscoveryDocument).SelectMany(x => x.UserClaims)); entries.Add(OidcConstants.Discovery.ClaimsSupported, claims.Distinct().ToArray()); } } // grant types if (Options.Discovery.ShowGrantTypes) { var standardGrantTypes = new List <string> { OidcConstants.GrantTypes.AuthorizationCode, OidcConstants.GrantTypes.ClientCredentials, OidcConstants.GrantTypes.RefreshToken, OidcConstants.GrantTypes.Implicit }; if (!(ResourceOwnerValidator is NotSupportedResourceOwnerPasswordValidator)) { standardGrantTypes.Add(OidcConstants.GrantTypes.Password); } if (Options.Endpoints.EnableDeviceAuthorizationEndpoint) { standardGrantTypes.Add(OidcConstants.GrantTypes.DeviceCode); } var showGrantTypes = new List <string>(standardGrantTypes); if (Options.Discovery.ShowExtensionGrantTypes) { showGrantTypes.AddRange(ExtensionGrants.GetAvailableGrantTypes()); } entries.Add(OidcConstants.Discovery.GrantTypesSupported, showGrantTypes.ToArray()); } // response types if (Options.Discovery.ShowResponseTypes) { entries.Add(OidcConstants.Discovery.ResponseTypesSupported, Constants.SupportedResponseTypes.ToArray()); } // response modes if (Options.Discovery.ShowResponseModes) { entries.Add(OidcConstants.Discovery.ResponseModesSupported, Constants.SupportedResponseModes.ToArray()); } // misc if (Options.Discovery.ShowTokenEndpointAuthenticationMethods) { var types = SecretParsers.GetAvailableAuthenticationMethods().ToList(); if (Options.MutualTls.Enabled) { types.Add(OidcConstants.EndpointAuthenticationMethods.TlsClientAuth); types.Add(OidcConstants.EndpointAuthenticationMethods.SelfSignedTlsClientAuth); } entries.Add(OidcConstants.Discovery.TokenEndpointAuthenticationMethodsSupported, types); } var signingCredentials = await Keys.GetAllSigningCredentialsAsync(); if (signingCredentials.Any()) { var signingAlgorithms = signingCredentials.Select(c => c.Algorithm).Distinct(); entries.Add(OidcConstants.Discovery.IdTokenSigningAlgorithmsSupported, signingAlgorithms); } entries.Add(OidcConstants.Discovery.SubjectTypesSupported, new[] { "public" }); entries.Add(OidcConstants.Discovery.CodeChallengeMethodsSupported, new[] { OidcConstants.CodeChallengeMethods.Plain, OidcConstants.CodeChallengeMethods.Sha256 }); if (Options.Endpoints.EnableAuthorizeEndpoint) { entries.Add(OidcConstants.Discovery.RequestParameterSupported, true); entries.Add(OidcConstants.Discovery.RequestObjectSigningAlgorithmsSupported, new[] { SecurityAlgorithms.RsaSha256, SecurityAlgorithms.RsaSha384, SecurityAlgorithms.RsaSha512, SecurityAlgorithms.RsaSsaPssSha256, SecurityAlgorithms.RsaSsaPssSha384, SecurityAlgorithms.RsaSsaPssSha512, SecurityAlgorithms.EcdsaSha256, SecurityAlgorithms.EcdsaSha384, SecurityAlgorithms.EcdsaSha512, SecurityAlgorithms.HmacSha256, SecurityAlgorithms.HmacSha384, SecurityAlgorithms.HmacSha512 }); if (Options.Endpoints.EnableJwtRequestUri) { entries.Add(OidcConstants.Discovery.RequestUriParameterSupported, true); } } entries.Add(OidcConstants.Discovery.AuthorizationResponseIssParameterSupported, true); if (Options.MutualTls.Enabled) { entries.Add(OidcConstants.Discovery.TlsClientCertificateBoundAccessTokens, true); } // custom entries if (!Options.Discovery.CustomEntries.IsNullOrEmpty()) { foreach ((string key, object value) in Options.Discovery.CustomEntries) { if (entries.ContainsKey(key)) { Logger.LogError("Discovery custom entry {key} cannot be added, because it already exists.", key); } else { if (value is string customValueString) { if (customValueString.StartsWith("~/") && Options.Discovery.ExpandRelativePathsInCustomEntries) { entries.Add(key, baseUrl + customValueString.Substring(2)); continue; } } entries.Add(key, value); } } } return(entries); }
/// <summary> /// Creates the discovery document. /// </summary> /// <param name="baseUrl">The base URL.</param> /// <param name="issuerUri">The issuer URI.</param> public virtual async Task <Dictionary <string, object> > CreateDiscoveryDocumentAsync(string baseUrl, string issuerUri) { var entries = new Dictionary <string, object>(); // issuer entries.Add(OidcConstants.Discovery.Issuer, issuerUri); // jwks if (Options.Discovery.ShowKeySet) { if ((await Keys.GetValidationKeysAsync()).Any()) { entries.Add(OidcConstants.Discovery.JwksUri, baseUrl + Constants.ProtocolRoutePaths.DiscoveryWebKeys); } } // endpoints if (Options.Discovery.ShowEndpoints) { if (Options.Endpoints.EnableAuthorizeEndpoint) { entries.Add(OidcConstants.Discovery.AuthorizationEndpoint, baseUrl + Constants.ProtocolRoutePaths.Authorize); } if (Options.Endpoints.EnableTokenEndpoint) { entries.Add(OidcConstants.Discovery.TokenEndpoint, baseUrl + Constants.ProtocolRoutePaths.Token); } if (Options.Endpoints.EnableUserInfoEndpoint) { entries.Add(OidcConstants.Discovery.UserInfoEndpoint, baseUrl + Constants.ProtocolRoutePaths.UserInfo); } if (Options.Endpoints.EnableEndSessionEndpoint) { entries.Add(OidcConstants.Discovery.EndSessionEndpoint, baseUrl + Constants.ProtocolRoutePaths.EndSession); } if (Options.Endpoints.EnableCheckSessionEndpoint) { entries.Add(OidcConstants.Discovery.CheckSessionIframe, baseUrl + Constants.ProtocolRoutePaths.CheckSession); } if (Options.Endpoints.EnableTokenRevocationEndpoint) { entries.Add(OidcConstants.Discovery.RevocationEndpoint, baseUrl + Constants.ProtocolRoutePaths.Revocation); } if (Options.Endpoints.EnableIntrospectionEndpoint) { entries.Add(OidcConstants.Discovery.IntrospectionEndpoint, baseUrl + Constants.ProtocolRoutePaths.Introspection); } } // logout if (Options.Endpoints.EnableEndSessionEndpoint) { entries.Add(OidcConstants.Discovery.FrontChannelLogoutSupported, true); entries.Add(OidcConstants.Discovery.FrontChannelLogoutSessionSupported, true); } // scopes and claims if (Options.Discovery.ShowIdentityScopes || Options.Discovery.ShowApiScopes || Options.Discovery.ShowClaims) { var resources = await ResourceStore.GetAllEnabledResourcesAsync(); var scopes = new List <string>(); // scopes if (Options.Discovery.ShowIdentityScopes) { scopes.AddRange(resources.IdentityResources.Where(x => x.ShowInDiscoveryDocument).Select(x => x.Name)); } if (Options.Discovery.ShowApiScopes) { var apiScopes = from api in resources.ApiResources from scope in api.Scopes where scope.ShowInDiscoveryDocument select scope.Name; scopes.AddRange(apiScopes); scopes.Add(IdentityServerConstants.StandardScopes.OfflineAccess); } if (scopes.Any()) { entries.Add(OidcConstants.Discovery.ScopesSupported, scopes.ToArray()); } // claims if (Options.Discovery.ShowClaims) { var claims = new List <string>(); claims.AddRange(resources.IdentityResources.SelectMany(x => x.UserClaims)); claims.AddRange(resources.ApiResources.SelectMany(x => x.UserClaims)); entries.Add(OidcConstants.Discovery.ClaimsSupported, claims.Distinct().ToArray()); } } // grant types if (Options.Discovery.ShowGrantTypes) { var standardGrantTypes = new List <string> { OidcConstants.GrantTypes.AuthorizationCode, OidcConstants.GrantTypes.ClientCredentials, OidcConstants.GrantTypes.RefreshToken, OidcConstants.GrantTypes.Implicit }; if (!(ResourceOwnerValidator is NotSupportedResouceOwnerPasswordValidator)) { standardGrantTypes.Add(OidcConstants.GrantTypes.Password); } var showGrantTypes = new List <string>(standardGrantTypes); if (Options.Discovery.ShowExtensionGrantTypes) { showGrantTypes.AddRange(ExtensionGrants.GetAvailableGrantTypes()); } entries.Add(OidcConstants.Discovery.GrantTypesSupported, showGrantTypes.ToArray()); } // response types if (Options.Discovery.ShowResponseTypes) { entries.Add(OidcConstants.Discovery.ResponseTypesSupported, Constants.SupportedResponseTypes.ToArray()); } // response modes if (Options.Discovery.ShowResponseModes) { entries.Add(OidcConstants.Discovery.ResponseModesSupported, Constants.SupportedResponseModes.ToArray()); } // misc if (Options.Discovery.ShowTokenEndpointAuthenticationMethods) { entries.Add(OidcConstants.Discovery.TokenEndpointAuthenticationMethodsSupported, SecretParsers.GetAvailableAuthenticationMethods().ToArray()); } entries.Add(OidcConstants.Discovery.SubjectTypesSupported, new[] { "public" }); entries.Add(OidcConstants.Discovery.IdTokenSigningAlgorithmsSupported, new[] { Constants.SigningAlgorithms.RSA_SHA_256 }); entries.Add(OidcConstants.Discovery.CodeChallengeMethodsSupported, new[] { OidcConstants.CodeChallengeMethods.Plain, OidcConstants.CodeChallengeMethods.Sha256 }); // custom entries if (!Options.Discovery.CustomEntries.IsNullOrEmpty()) { foreach (var customEntry in Options.Discovery.CustomEntries) { if (entries.ContainsKey(customEntry.Key)) { Logger.LogError("Discovery custom entry {key} cannot be added, because it already exists.", customEntry.Key); } else { var customValueString = customEntry.Value as string; if (customValueString != null) { if (customValueString.StartsWith("~/") && Options.Discovery.ExpandRelativePathsInCustomEntries) { entries.Add(customEntry.Key, baseUrl + customValueString.Substring(2)); continue; } } entries.Add(customEntry.Key, customEntry.Value); } } } return(entries); }
private async Task <IEndpointResult> ExecuteDiscoDocAsync(HttpContext context) { _logger.LogDebug("Start discovery request"); if (!_options.Endpoints.EnableDiscoveryEndpoint) { _logger.LogInformation("Discovery endpoint disabled. 404."); return(new StatusCodeResult(404)); } var baseUrl = context.GetIdentityServerBaseUrl().EnsureTrailingSlash(); var allScopes = await _scopes.GetEnabledScopesAsync(publicOnly : true); var showScopes = new List <Scope>(); var document = new DiscoveryDocument { issuer = context.GetIssuerUri(), subject_types_supported = new[] { "public" }, id_token_signing_alg_values_supported = new[] { Constants.SigningAlgorithms.RSA_SHA_256 }, code_challenge_methods_supported = new[] { OidcConstants.CodeChallengeMethods.Plain, OidcConstants.CodeChallengeMethods.Sha256 } }; // scopes var theScopes = allScopes as Scope[] ?? allScopes.ToArray(); if (_options.DiscoveryOptions.ShowIdentityScopes) { showScopes.AddRange(theScopes.Where(s => s.Type == ScopeType.Identity)); } if (_options.DiscoveryOptions.ShowResourceScopes) { showScopes.AddRange(theScopes.Where(s => s.Type == ScopeType.Resource)); } if (showScopes.Any()) { document.scopes_supported = showScopes.Where(s => s.ShowInDiscoveryDocument).Select(s => s.Name).ToArray(); } // claims if (_options.DiscoveryOptions.ShowClaims) { var claims = new List <string>(); foreach (var s in theScopes) { claims.AddRange(from c in s.Claims where s.Type == ScopeType.Identity select c.Name); } document.claims_supported = claims.Distinct().ToArray(); } // grant types if (_options.DiscoveryOptions.ShowGrantTypes) { var standardGrantTypes = new List <string> { OidcConstants.GrantTypes.AuthorizationCode, OidcConstants.GrantTypes.ClientCredentials, OidcConstants.GrantTypes.RefreshToken, OidcConstants.GrantTypes.Implicit }; if (!(_resourceOwnerValidator is NotSupportedResouceOwnerPasswordValidator)) { standardGrantTypes.Add(OidcConstants.GrantTypes.Password); } var showGrantTypes = new List <string>(standardGrantTypes); if (_options.DiscoveryOptions.ShowExtensionGrantTypes) { showGrantTypes.AddRange(_extensionGrants.GetAvailableGrantTypes()); } document.grant_types_supported = showGrantTypes.ToArray(); } // response types if (_options.DiscoveryOptions.ShowResponseTypes) { document.response_types_supported = Constants.SupportedResponseTypes.ToArray(); } // response modes if (_options.DiscoveryOptions.ShowResponseModes) { document.response_modes_supported = Constants.SupportedResponseModes.ToArray(); } // token endpoint authentication methods if (_options.DiscoveryOptions.ShowTokenEndpointAuthenticationMethods) { document.token_endpoint_auth_methods_supported = _parsers.GetAvailableAuthenticationMethods().ToArray(); } // endpoints if (_options.DiscoveryOptions.ShowEndpoints) { if (_options.Endpoints.EnableAuthorizeEndpoint) { document.authorization_endpoint = baseUrl + Constants.ProtocolRoutePaths.Authorize; } if (_options.Endpoints.EnableTokenEndpoint) { document.token_endpoint = baseUrl + Constants.ProtocolRoutePaths.Token; } if (_options.Endpoints.EnableUserInfoEndpoint) { document.userinfo_endpoint = baseUrl + Constants.ProtocolRoutePaths.UserInfo; } if (_options.Endpoints.EnableEndSessionEndpoint) { document.frontchannel_logout_session_supported = true; document.frontchannel_logout_supported = true; document.end_session_endpoint = baseUrl + Constants.ProtocolRoutePaths.EndSession; } if (_options.Endpoints.EnableCheckSessionEndpoint) { document.check_session_iframe = baseUrl + Constants.ProtocolRoutePaths.CheckSession; } if (_options.Endpoints.EnableTokenRevocationEndpoint) { document.revocation_endpoint = baseUrl + Constants.ProtocolRoutePaths.Revocation; } if (_options.Endpoints.EnableIntrospectionEndpoint) { document.introspection_endpoint = baseUrl + Constants.ProtocolRoutePaths.Introspection; } } if (_options.DiscoveryOptions.ShowKeySet) { if ((await _keys.GetValidationKeysAsync()).Any()) { document.jwks_uri = baseUrl + Constants.ProtocolRoutePaths.DiscoveryWebKeys; } } return(new DiscoveryDocumentResult(document, _options.DiscoveryOptions.CustomEntries)); }