Skip to content

Commit

Permalink
Add Alibaba Cloud (Aliyun) to the list of supported providers
Browse files Browse the repository at this point in the history
  • Loading branch information
gehongyan authored Feb 26, 2025
1 parent ad45269 commit 9eae2a4
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ public ValueTask HandleAsync(HandleConfigurationResponseContext context)
// types is amended to include the known supported types for the providers that require it.

if (context.Registration.ProviderType is
ProviderTypes.Apple or ProviderTypes.FaceIt or
ProviderTypes.LinkedIn or ProviderTypes.QuickBooksOnline)
ProviderTypes.AlibabaCloud or ProviderTypes.Apple or
ProviderTypes.FaceIt or ProviderTypes.LinkedIn or
ProviderTypes.QuickBooksOnline)
{
context.Configuration.GrantTypesSupported.Add(GrantTypes.AuthorizationCode);
context.Configuration.GrantTypesSupported.Add(GrantTypes.RefreshToken);
Expand Down Expand Up @@ -250,7 +251,8 @@ public ValueTask HandleAsync(HandleConfigurationResponseContext context)
// While it is a recommended node, these providers don't include "scopes_supported" in their
// configuration and thus are treated as OAuth 2.0-only providers by the OpenIddict client.
// To avoid that, the "openid" scope is manually added to indicate OpenID Connect is supported.
else if (context.Registration.ProviderType is ProviderTypes.EpicGames or ProviderTypes.Xero or ProviderTypes.EveOnline)
else if (context.Registration.ProviderType is
ProviderTypes.EpicGames or ProviderTypes.EveOnline or ProviderTypes.Xero)
{
context.Configuration.ScopesSupported.Add(Scopes.OpenId);
}
Expand Down Expand Up @@ -283,14 +285,28 @@ public ValueTask HandleAsync(HandleConfigurationResponseContext context)
throw new ArgumentNullException(nameof(context));
}

// Alibaba Cloud doesn't document whether sending client credentials using basic authentication
// is supported and doesn't return a "token_endpoint_auth_methods_supported" nor a
// "revocation_endpoint_auth_methods_supported" node containing alternative authentication
// methods, making basic authentication the default. While both token and revocation requests
// currently work, "client_secret_post" is manually added here to avoid potential issues.
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud)
{
context.Configuration.TokenEndpointAuthMethodsSupported.Add(
ClientAuthenticationMethods.ClientSecretPost);

context.Configuration.RevocationEndpointAuthMethodsSupported.Add(
ClientAuthenticationMethods.ClientSecretPost);
}

// Apple implements a non-standard client authentication method for its endpoints that
// is inspired by the standard private_key_jwt method but doesn't use the standard
// client_assertion/client_assertion_type parameters. Instead, the client assertion
// must be sent as a "dynamic" client secret using client_secret_post. Since the logic
// is the same as private_key_jwt, the configuration is amended to assume Apple supports
// private_key_jwt and an event handler is responsible for populating the client_secret
// parameter using the client assertion once it has been generated by OpenIddict.
if (context.Registration.ProviderType is ProviderTypes.Apple)
else if (context.Registration.ProviderType is ProviderTypes.Apple)
{
context.Configuration.RevocationEndpointAuthMethodsSupported.Add(
ClientAuthenticationMethods.PrivateKeyJwt);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,23 +357,23 @@ public ValueTask HandleAsync(ExtractTokenResponseContext context)
context.Response.RefreshToken = null;
}

// Note: Alibaba Cloud and Exact Online returns a non-standard "expires_in"
// parameter formatted as a string instead of a numeric type.
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud or ProviderTypes.ExactOnline &&
long.TryParse((string?) context.Response[Parameters.ExpiresIn],
NumberStyles.Integer, CultureInfo.InvariantCulture, out long value))
{
context.Response.ExpiresIn = value;
}

// Note: Deezer doesn't return a standard "expires_in" parameter
// but returns an equivalent "expires" integer parameter instead.
if (context.Registration.ProviderType is ProviderTypes.Deezer)
else if (context.Registration.ProviderType is ProviderTypes.Deezer)
{
context.Response[Parameters.ExpiresIn] = context.Response["expires"];
context.Response["expires"] = null;
}

// Note: Exact Online returns a non-standard "expires_in"
// parameter formatted as a string instead of a numeric type.
else if (context.Registration.ProviderType is ProviderTypes.ExactOnline &&
long.TryParse((string?) context.Response[Parameters.ExpiresIn],
NumberStyles.Integer, CultureInfo.InvariantCulture, out long value))
{
context.Response.ExpiresIn = value;
}

// Note: Huawei returns a non-standard "error" parameter as a numeric value, which is not allowed
// by OpenIddict (that requires a string). Huawei also returns a non-standard "sub_error" parameter
// that contains additional error information, with which the error code can demonstrate a specific
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1853,13 +1853,28 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
throw new ArgumentNullException(nameof(context));
}

// Active Directory Federation Services allows sending a custom "resource"
// Active Directory Federation Services allows sending an optional custom "resource"
// parameter to define what API resources the access token will give access to.
if (context.Registration.ProviderType is ProviderTypes.ActiveDirectoryFederationServices)
{
var settings = context.Registration.GetActiveDirectoryFederationServicesSettings();

context.Request["resource"] = settings.Resource;
if (!string.IsNullOrEmpty(settings.Resource))
{
context.Request.Resources = [settings.Resource];
}
}

// By default, Alibaba Cloud doesn't return a refresh token for native applications but allows sending an
// "access_type" parameter to retrieve one (but it is only returned during the first authorization dance).
// The documentation also indicates the "prompt" parameter is supported but not required,
// which can be set to "admin_consent" to force the display of the authorization page
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud)
{
var settings = context.Registration.GetAlibabaCloudSettings();

context.Request["access_type"] = settings.AccessType;
context.Request.Prompt = settings.Prompt;
}

// Atlassian requires sending an "audience" parameter (by default, "api.atlassian.com").
Expand Down Expand Up @@ -1899,7 +1914,7 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
var settings = context.Registration.GetHuaweiSettings();

context.Request["access_type"] = settings.AccessType;
context.Request["display"] = settings.Display;
context.Request.Display = settings.Display;
}

// By default, MusicBrainz doesn't return a refresh token but allows sending an "access_type"
Expand Down Expand Up @@ -1956,7 +1971,7 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
{
var settings = context.Registration.GetWeiboSettings();

context.Request["display"] = settings.Display;
context.Request.Display = settings.Display;
context.Request["forcelogin"] = settings.ForceLogin;
context.Request["language"] = settings.Language;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,33 @@
</Environment>
</Provider>

<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█ ▄▄▀██ ████▄ ▄██ ▄▄▀█ ▄▄▀██ ▄▄▀█ ▄▄▀████ ▄▄▀██ █████ ▄▄▄ ██ ██ ██ ▄▄▀██
█ ▀▀ ██ █████ ███ ▄▄▀█ ▀▀ ██ ▄▄▀█ ▀▀ ████ █████ █████ ███ ██ ██ ██ ██ ██
█ ██ ██ ▀▀ █▀ ▀██ ▀▀ █ ██ ██ ▀▀ █ ██ ████ ▀▀▄██ ▀▀ ██ ▀▀▀ ██▄▀▀▄██ ▀▀ ██
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
-->

<Provider Name="AlibabaCloud" DisplayName="Alibaba Cloud (Aliyun)" Id="078caf87-3c5b-46aa-a8af-31e7cb2f4b7a"
Documentation="https://www.alibabacloud.com/help/en/ram/user-guide/oauth-management/">
<!--
Note: Alibaba Cloud serves global users, but it is known as Aliyun in China, which has a separate issuer and domain.
-->

<Environment Issuer="https://oauth.{(settings.Region?.ToUpperInvariant() is 'CN' ? 'aliyun' : 'alibabacloud')}.com/"
ConfigurationEndpoint="https://oauth.{(settings.Region?.ToUpperInvariant() is 'CN' ? 'aliyun' : 'alibabacloud')}.com/.well-known/openid-configuration" />

<Setting PropertyName="Region" ParameterName="region" Type="String" Required="false" DefaultValue="Global"
Description="The Alibaba Cloud (Aliyun) service region ('Global' for the global Alibaba Cloud by default, or can be set to 'CN' for Aliyun)" />

<Setting PropertyName="AccessType" ParameterName="type" Type="String" Required="false"
Description="The value used as the 'access_type' parameter (can be set to 'offline' to retrieve a refresh token)" />

<Setting PropertyName="Prompt" ParameterName="prompt" Type="String" Required="false"
Description="The value used as the 'prompt' parameter (can be set to 'admin_consent' to force the display of the authorization page)" />
</Provider>

<!--
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
█ ▄▄▀██ ▄▀▄ █ ▄▄▀██ ▄▄▄ ██ ▄▄▄ ██ ▀██ ██
Expand Down

0 comments on commit 9eae2a4

Please sign in to comment.