Browse Source

Add Bitly to the list of supported providers

pull/2023/head
Kévin Chalet 2 years ago
parent
commit
2ac632de48
  1. 21
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs
  2. 59
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs
  3. 20
      src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

21
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Exchange.cs

@ -143,6 +143,27 @@ public static partial class OpenIddictClientWebIntegrationHandlers
var request = context.Transaction.GetHttpRequestMessage() ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0173));
// Note: Bitly only supports using "client_secret_post" for the authorization code grant but not for
// the resource owner password credentials grant, that requires using "client_secret_basic" instead.
if (context.Registration.ProviderType is ProviderTypes.Bitly &&
context.GrantType is GrantTypes.Password &&
!string.IsNullOrEmpty(context.Request.ClientId) &&
!string.IsNullOrEmpty(context.Request.ClientSecret))
{
// Important: the credentials MUST be formURL-encoded before being base64-encoded.
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(new StringBuilder()
.Append(EscapeDataString(context.Request.ClientId))
.Append(':')
.Append(EscapeDataString(context.Request.ClientSecret))
.ToString()));
// Attach the authorization header containing the client credentials to the HTTP request.
request.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Basic, credentials);
// Remove the client credentials from the request payload to ensure they are not sent twice.
context.Request.ClientId = context.Request.ClientSecret = null;
}
// These providers require using basic authentication to flow the client_id
// for all types of client applications, even when there's no client_secret.
if (context.Registration.ProviderType is ProviderTypes.Reddit &&

59
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

@ -209,19 +209,58 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// Errors that are not handled here will be automatically handled
// by the standard handler present in the core OpenIddict client.
if (context.Registration.ProviderType is ProviderTypes.Deezer)
if (context.Registration.ProviderType is ProviderTypes.Bitly &&
(bool?) context.Request["invalid"] is true)
{
// Note: Bitly uses custom "invalid" and "reason" parameters instead of
// the standard "error" parameter defined by the OAuth 2.0 specification.
var error = (string?) context.Request["reason"];
context.Reject(
error: error switch
{
"deny" => Errors.AccessDenied,
_ => Errors.ServerError
},
description: error switch
{
"deny" => SR.GetResourceString(SR.ID2149),
_ => SR.GetResourceString(SR.ID2152)
},
uri: error switch
{
"deny" => SR.FormatID8000(SR.ID2149),
_ => SR.FormatID8000(SR.ID2152)
});
return default;
}
else if (context.Registration.ProviderType is ProviderTypes.Deezer)
{
// Note: Deezer uses a custom "error_reason" parameter instead of the
// standard "error" parameter defined by the OAuth 2.0 specification.
//
// See https://developers.deezer.com/api/oauth for more information.
var error = (string?) context.Request["error_reason"];
if (string.Equals(error, "user_denied", StringComparison.Ordinal))
if (!string.IsNullOrEmpty(error))
{
context.Reject(
error: Errors.AccessDenied,
description: SR.GetResourceString(SR.ID2149),
uri: SR.FormatID8000(SR.ID2149));
error: error switch
{
"user_denied" => Errors.AccessDenied,
_ => Errors.ServerError
},
description: error switch
{
"user_denied" => SR.GetResourceString(SR.ID2149),
_ => SR.GetResourceString(SR.ID2152)
},
uri: error switch
{
"user_denied" => SR.FormatID8000(SR.ID2149),
_ => SR.FormatID8000(SR.ID2152)
});
return default;
}
@ -1091,6 +1130,13 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// Basecamp returns the email address as a custom "email_address" node:
ProviderTypes.Basecamp => (string?) context.UserinfoResponse?["email_address"],
// Bitly returns one or more email addresses as a custom "emails" node:
ProviderTypes.Bitly => context.UserinfoResponse?["emails"]
?.GetUnnamedParameters()
?.Where(parameter => (bool?) parameter["is_primary"] is true)
?.Select(parameter => (string?) parameter["email"])
?.FirstOrDefault(),
// HubSpot returns the email address as a custom "user" node:
ProviderTypes.HubSpot => (string?) context.UserinfoResponse?["user"],
@ -1208,6 +1254,9 @@ public static partial class OpenIddictClientWebIntegrationHandlers
// Bitbucket returns the user identifier as a custom "uuid" node:
ProviderTypes.Bitbucket => (string?) context.UserinfoResponse?["uuid"],
// Bitly returns the user identifier as a custom "login" node:
ProviderTypes.Bitly => (string?) context.UserinfoResponse?["login"],
// DeviantArt returns the user identifier as a custom "userid" node:
ProviderTypes.DeviantArt => (string?) context.UserinfoResponse?["userid"],

20
src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

@ -244,6 +244,26 @@
</Environment>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
██ ▄▄▀█▄ ▄█▄▄ ▄▄██ █████ ███ ██
██ ▄▄▀██ ████ ████ █████▄▀▀▀▄██
██ ▀▀ █▀ ▀███ ████ ▀▀ ████ ████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
-->
<Provider Name="Bitly" Id="f22283c2-b074-4710-af44-a1c86343226e"
Documentation="https://dev.bitly.com/docs/getting-started/authentication/">
<Environment Issuer="https://bitly.com/">
<Configuration AuthorizationEndpoint="https://bitly.com/oauth/authorize"
TokenEndpoint="https://api-ssl.bitly.com/oauth/access_token"
UserinfoEndpoint="https://api-ssl.bitly.com/v4/user">
<GrantType Value="authorization_code" />
<GrantType Value="password" />
</Configuration>
</Environment>
</Provider>
<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█ ▄▄▀██ ▄▀▄ █ ▄▄▀██ ▄▄▄ ██ ▄▄▄ ██ ▀██ ████ ▄▄▀██ ▄▄▄ ██ ▄▄ ██ ▀██ █▄ ▄█▄▄ ▄▄██ ▄▄▄ ██

Loading…
Cancel
Save