Skip to content

Commit 9eae2a4

Browse files
authored
Add Alibaba Cloud (Aliyun) to the list of supported providers
1 parent ad45269 commit 9eae2a4

File tree

4 files changed

+76
-18
lines changed

4 files changed

+76
-18
lines changed

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ public ValueTask HandleAsync(HandleConfigurationResponseContext context)
108108
// types is amended to include the known supported types for the providers that require it.
109109

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

288+
// Alibaba Cloud doesn't document whether sending client credentials using basic authentication
289+
// is supported and doesn't return a "token_endpoint_auth_methods_supported" nor a
290+
// "revocation_endpoint_auth_methods_supported" node containing alternative authentication
291+
// methods, making basic authentication the default. While both token and revocation requests
292+
// currently work, "client_secret_post" is manually added here to avoid potential issues.
293+
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud)
294+
{
295+
context.Configuration.TokenEndpointAuthMethodsSupported.Add(
296+
ClientAuthenticationMethods.ClientSecretPost);
297+
298+
context.Configuration.RevocationEndpointAuthMethodsSupported.Add(
299+
ClientAuthenticationMethods.ClientSecretPost);
300+
}
301+
286302
// Apple implements a non-standard client authentication method for its endpoints that
287303
// is inspired by the standard private_key_jwt method but doesn't use the standard
288304
// client_assertion/client_assertion_type parameters. Instead, the client assertion
289305
// must be sent as a "dynamic" client secret using client_secret_post. Since the logic
290306
// is the same as private_key_jwt, the configuration is amended to assume Apple supports
291307
// private_key_jwt and an event handler is responsible for populating the client_secret
292308
// parameter using the client assertion once it has been generated by OpenIddict.
293-
if (context.Registration.ProviderType is ProviderTypes.Apple)
309+
else if (context.Registration.ProviderType is ProviderTypes.Apple)
294310
{
295311
context.Configuration.RevocationEndpointAuthMethodsSupported.Add(
296312
ClientAuthenticationMethods.PrivateKeyJwt);

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,23 +357,23 @@ public ValueTask HandleAsync(ExtractTokenResponseContext context)
357357
context.Response.RefreshToken = null;
358358
}
359359

360+
// Note: Alibaba Cloud and Exact Online returns a non-standard "expires_in"
361+
// parameter formatted as a string instead of a numeric type.
362+
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud or ProviderTypes.ExactOnline &&
363+
long.TryParse((string?) context.Response[Parameters.ExpiresIn],
364+
NumberStyles.Integer, CultureInfo.InvariantCulture, out long value))
365+
{
366+
context.Response.ExpiresIn = value;
367+
}
368+
360369
// Note: Deezer doesn't return a standard "expires_in" parameter
361370
// but returns an equivalent "expires" integer parameter instead.
362-
if (context.Registration.ProviderType is ProviderTypes.Deezer)
371+
else if (context.Registration.ProviderType is ProviderTypes.Deezer)
363372
{
364373
context.Response[Parameters.ExpiresIn] = context.Response["expires"];
365374
context.Response["expires"] = null;
366375
}
367376

368-
// Note: Exact Online returns a non-standard "expires_in"
369-
// parameter formatted as a string instead of a numeric type.
370-
else if (context.Registration.ProviderType is ProviderTypes.ExactOnline &&
371-
long.TryParse((string?) context.Response[Parameters.ExpiresIn],
372-
NumberStyles.Integer, CultureInfo.InvariantCulture, out long value))
373-
{
374-
context.Response.ExpiresIn = value;
375-
}
376-
377377
// Note: Huawei returns a non-standard "error" parameter as a numeric value, which is not allowed
378378
// by OpenIddict (that requires a string). Huawei also returns a non-standard "sub_error" parameter
379379
// that contains additional error information, with which the error code can demonstrate a specific

src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,13 +1853,28 @@ public ValueTask HandleAsync(ProcessChallengeContext context)
18531853
throw new ArgumentNullException(nameof(context));
18541854
}
18551855

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

1862-
context.Request["resource"] = settings.Resource;
1862+
if (!string.IsNullOrEmpty(settings.Resource))
1863+
{
1864+
context.Request.Resources = [settings.Resource];
1865+
}
1866+
}
1867+
1868+
// By default, Alibaba Cloud doesn't return a refresh token for native applications but allows sending an
1869+
// "access_type" parameter to retrieve one (but it is only returned during the first authorization dance).
1870+
// The documentation also indicates the "prompt" parameter is supported but not required,
1871+
// which can be set to "admin_consent" to force the display of the authorization page
1872+
if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud)
1873+
{
1874+
var settings = context.Registration.GetAlibabaCloudSettings();
1875+
1876+
context.Request["access_type"] = settings.AccessType;
1877+
context.Request.Prompt = settings.Prompt;
18631878
}
18641879

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

19011916
context.Request["access_type"] = settings.AccessType;
1902-
context.Request["display"] = settings.Display;
1917+
context.Request.Display = settings.Display;
19031918
}
19041919

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

1959-
context.Request["display"] = settings.Display;
1974+
context.Request.Display = settings.Display;
19601975
context.Request["forcelogin"] = settings.ForceLogin;
19611976
context.Request["language"] = settings.Language;
19621977
}

src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationProviders.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,33 @@
7474
</Environment>
7575
</Provider>
7676

77+
<!--
78+
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
79+
█ ▄▄▀██ ████▄ ▄██ ▄▄▀█ ▄▄▀██ ▄▄▀█ ▄▄▀████ ▄▄▀██ █████ ▄▄▄ ██ ██ ██ ▄▄▀██
80+
█ ▀▀ ██ █████ ███ ▄▄▀█ ▀▀ ██ ▄▄▀█ ▀▀ ████ █████ █████ ███ ██ ██ ██ ██ ██
81+
█ ██ ██ ▀▀ █▀ ▀██ ▀▀ █ ██ ██ ▀▀ █ ██ ████ ▀▀▄██ ▀▀ ██ ▀▀▀ ██▄▀▀▄██ ▀▀ ██
82+
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
83+
-->
84+
85+
<Provider Name="AlibabaCloud" DisplayName="Alibaba Cloud (Aliyun)" Id="078caf87-3c5b-46aa-a8af-31e7cb2f4b7a"
86+
Documentation="https://www.alibabacloud.com/help/en/ram/user-guide/oauth-management/">
87+
<!--
88+
Note: Alibaba Cloud serves global users, but it is known as Aliyun in China, which has a separate issuer and domain.
89+
-->
90+
91+
<Environment Issuer="https://oauth.{(settings.Region?.ToUpperInvariant() is 'CN' ? 'aliyun' : 'alibabacloud')}.com/"
92+
ConfigurationEndpoint="https://oauth.{(settings.Region?.ToUpperInvariant() is 'CN' ? 'aliyun' : 'alibabacloud')}.com/.well-known/openid-configuration" />
93+
94+
<Setting PropertyName="Region" ParameterName="region" Type="String" Required="false" DefaultValue="Global"
95+
Description="The Alibaba Cloud (Aliyun) service region ('Global' for the global Alibaba Cloud by default, or can be set to 'CN' for Aliyun)" />
96+
97+
<Setting PropertyName="AccessType" ParameterName="type" Type="String" Required="false"
98+
Description="The value used as the 'access_type' parameter (can be set to 'offline' to retrieve a refresh token)" />
99+
100+
<Setting PropertyName="Prompt" ParameterName="prompt" Type="String" Required="false"
101+
Description="The value used as the 'prompt' parameter (can be set to 'admin_consent' to force the display of the authorization page)" />
102+
</Provider>
103+
77104
<!--
78105
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
79106
█ ▄▄▀██ ▄▀▄ █ ▄▄▀██ ▄▄▄ ██ ▄▄▄ ██ ▀██ ██

0 commit comments

Comments
 (0)