diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs index e0dce7af..4489eb62 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Revocation.cs @@ -135,6 +135,12 @@ public static partial class OpenIddictClientWebIntegrationHandlers response.Content.Headers.ContentType = context.Registration.ProviderType switch { + // MusicBrainz returns empty revocation responses declared as "text/html" responses. + // + // Since empty HTML payloads are not valid JSON nodes, the Content-Length is manually set + // to 0 to prevent OpenIddict from trying to extract a JSON payload from such responses. + ProviderTypes.MusicBrainz when response.Content.Headers.ContentLength is 0 => null, + // Reddit returns empty revocation responses declared as "application/json" responses. // // Since empty JSON payloads are not valid JSON nodes, the Content-Length is manually set diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs index ff21f513..ce984b2a 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs @@ -1136,6 +1136,9 @@ public static partial class OpenIddictClientWebIntegrationHandlers // Mailchimp returns the username as a custom "accountname" node: ProviderTypes.Mailchimp => (string?) context.UserinfoResponse?["accountname"], + // Mailchimp returns the username as a custom "sub" node: + ProviderTypes.MusicBrainz => (string?) context.UserinfoResponse?["sub"], + // Nextcloud returns the username as a custom "displayname" or "display-name" node: ProviderTypes.Nextcloud => (string?) context.UserinfoResponse?["displayname"] ?? (string?) context.UserinfoResponse?["display-name"], @@ -1216,6 +1219,9 @@ public static partial class OpenIddictClientWebIntegrationHandlers // Mixcloud returns the user identifier as a custom "key" node: ProviderTypes.Mixcloud => (string?) context.UserinfoResponse?["key"], + // MusicBrainz returns the user identifier as a custom "metabrainz_user_id" node: + ProviderTypes.MusicBrainz => (string?) context.UserinfoResponse?["metabrainz_user_id"], + // Notion returns the user identifier as a custom "bot/owner/user/id" node but // requires a special capability to access this node, that may not be present: ProviderTypes.Notion => (string?) context.UserinfoResponse?["bot"]?["owner"]?["user"]?["id"], @@ -1531,6 +1537,16 @@ public static partial class OpenIddictClientWebIntegrationHandlers context.Request["access_type"] = settings.AccessType; } + // By default, MusicBrainz doesn't return a refresh token but allows sending an "access_type" + // parameter to retrieve one (but it is only returned during the first authorization dance). + else if (context.Registration.ProviderType is ProviderTypes.MusicBrainz) + { + var settings = context.Registration.GetMusicBrainzSettings(); + + context.Request["access_type"] = settings.AccessType; + context.Request["approval_prompt"] = settings.ApprovalPrompt; + } + // Pro Santé Connect's specification requires sending an acr_values parameter containing // the desired level of authentication (currently, only "eidas1" is supported). For more // information, see https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000045551195. diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml index 3462ba96..c0507e5d 100644 --- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml +++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml @@ -857,6 +857,42 @@ + + + + + + + + + + + + + + + + + + + + + +