private async Task InvokeConfigurationEndpointAsync() { var notification = new ConfigurationEndpointContext(Context, Options); notification.Issuer = Context.GetIssuer(Options); // Metadata requests must be made via GET. // See http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest if (!string.Equals(Request.Method, "GET", StringComparison.OrdinalIgnoreCase)) { Logger.LogError("Configuration endpoint: invalid method used."); return; } if (Options.AuthorizationEndpointPath.HasValue) { notification.AuthorizationEndpoint = notification.Issuer.AddPath(Options.AuthorizationEndpointPath); } if (Options.CryptographyEndpointPath.HasValue) { notification.CryptographyEndpoint = notification.Issuer.AddPath(Options.CryptographyEndpointPath); } if (Options.ProfileEndpointPath.HasValue) { notification.ProfileEndpoint = notification.Issuer.AddPath(Options.ProfileEndpointPath); } if (Options.ValidationEndpointPath.HasValue) { notification.ValidationEndpoint = notification.Issuer.AddPath(Options.ValidationEndpointPath); } if (Options.TokenEndpointPath.HasValue) { notification.TokenEndpoint = notification.Issuer.AddPath(Options.TokenEndpointPath); } if (Options.LogoutEndpointPath.HasValue) { notification.LogoutEndpoint = notification.Issuer.AddPath(Options.LogoutEndpointPath); } if (Options.AuthorizationEndpointPath.HasValue) { // Only expose the implicit grant type if the token // endpoint has not been explicitly disabled. notification.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.Implicit); if (Options.TokenEndpointPath.HasValue) { // Only expose the authorization code and refresh token grant types // if both the authorization and the token endpoints are enabled. notification.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.AuthorizationCode); } } if (Options.TokenEndpointPath.HasValue) { notification.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.RefreshToken); // If the authorization endpoint is disabled, assume the authorization server will // allow the client credentials and resource owner password credentials grant types. if (!Options.AuthorizationEndpointPath.HasValue) { notification.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.ClientCredentials); notification.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.Password); } } // Only populate response_modes_supported and response_types_supported // if the authorization endpoint is available. if (Options.AuthorizationEndpointPath.HasValue) { notification.ResponseModes.Add(OpenIdConnectConstants.ResponseModes.FormPost); notification.ResponseModes.Add(OpenIdConnectConstants.ResponseModes.Fragment); notification.ResponseModes.Add(OpenIdConnectConstants.ResponseModes.Query); notification.ResponseTypes.Add(OpenIdConnectConstants.ResponseTypes.Token); notification.ResponseTypes.Add(OpenIdConnectConstants.ResponseTypes.IdToken); notification.ResponseTypes.Add( OpenIdConnectConstants.ResponseTypes.IdToken + ' ' + OpenIdConnectConstants.ResponseTypes.Token); // Only expose response types containing code when // the token endpoint has not been explicitly disabled. if (Options.TokenEndpointPath.HasValue) { notification.ResponseTypes.Add(OpenIdConnectConstants.ResponseTypes.Code); notification.ResponseTypes.Add( OpenIdConnectConstants.ResponseTypes.Code + ' ' + OpenIdConnectConstants.ResponseTypes.Token); notification.ResponseTypes.Add( OpenIdConnectConstants.ResponseTypes.Code + ' ' + OpenIdConnectConstants.ResponseTypes.IdToken); notification.ResponseTypes.Add( OpenIdConnectConstants.ResponseTypes.Code + ' ' + OpenIdConnectConstants.ResponseTypes.IdToken + ' ' + OpenIdConnectConstants.ResponseTypes.Token); } } notification.Scopes.Add(OpenIdConnectConstants.Scopes.OpenId); notification.SubjectTypes.Add(OpenIdConnectConstants.SubjectTypes.Public); notification.SigningAlgorithms.Add(OpenIdConnectConstants.Algorithms.RS256); await Options.Provider.ConfigurationEndpoint(notification); if (notification.HandledResponse) { return; } var payload = new JObject(); payload.Add(OpenIdConnectConstants.Metadata.Issuer, notification.Issuer); if (!string.IsNullOrEmpty(notification.AuthorizationEndpoint)) { payload.Add(OpenIdConnectConstants.Metadata.AuthorizationEndpoint, notification.AuthorizationEndpoint); } if (!string.IsNullOrEmpty(notification.ProfileEndpoint)) { payload.Add(OpenIdConnectConstants.Metadata.UserinfoEndpoint, notification.ProfileEndpoint); } if (!string.IsNullOrEmpty(notification.ValidationEndpoint)) { payload.Add(OpenIdConnectConstants.Metadata.IntrospectionEndpoint, notification.ValidationEndpoint); } if (!string.IsNullOrEmpty(notification.TokenEndpoint)) { payload.Add(OpenIdConnectConstants.Metadata.TokenEndpoint, notification.TokenEndpoint); } if (!string.IsNullOrEmpty(notification.LogoutEndpoint)) { payload.Add(OpenIdConnectConstants.Metadata.EndSessionEndpoint, notification.LogoutEndpoint); } if (!string.IsNullOrEmpty(notification.CryptographyEndpoint)) { payload.Add(OpenIdConnectConstants.Metadata.JwksUri, notification.CryptographyEndpoint); } payload.Add(OpenIdConnectConstants.Metadata.GrantTypesSupported, JArray.FromObject(notification.GrantTypes.Distinct())); payload.Add(OpenIdConnectConstants.Metadata.ResponseModesSupported, JArray.FromObject(notification.ResponseModes.Distinct())); payload.Add(OpenIdConnectConstants.Metadata.ResponseTypesSupported, JArray.FromObject(notification.ResponseTypes.Distinct())); payload.Add(OpenIdConnectConstants.Metadata.SubjectTypesSupported, JArray.FromObject(notification.SubjectTypes.Distinct())); payload.Add(OpenIdConnectConstants.Metadata.ScopesSupported, JArray.FromObject(notification.Scopes.Distinct())); payload.Add(OpenIdConnectConstants.Metadata.IdTokenSigningAlgValuesSupported, JArray.FromObject(notification.SigningAlgorithms.Distinct())); var context = new ConfigurationEndpointResponseContext(Context, Options, payload); await Options.Provider.ConfigurationEndpointResponse(context); if (context.HandledResponse) { return; } using (var buffer = new MemoryStream()) using (var writer = new JsonTextWriter(new StreamWriter(buffer))) { payload.WriteTo(writer); writer.Flush(); Response.ContentLength = buffer.Length; Response.ContentType = "application/json;charset=UTF-8"; buffer.Seek(offset: 0, loc: SeekOrigin.Begin); await buffer.CopyToAsync(Response.Body, 4096, Context.RequestAborted); } }
/// <summary> /// Called by the client applications to retrieve the OpenID Connect configuration associated with this instance. /// An application may implement this call in order to do any final modification to the configuration metadata. /// </summary> /// <param name="context">The context of the event carries information in and results out.</param> /// <returns>Task to enable asynchronous execution</returns> public virtual Task ConfigurationEndpoint(ConfigurationEndpointContext context) => OnConfigurationEndpoint(context);