Add Alibaba Cloud (Aliyun) to the list of supported providers#2256
Add Alibaba Cloud (Aliyun) to the list of supported providers#2256kevinchalet merged 9 commits intoopeniddict:devfrom
Conversation
DocsAlibaba Cloud provides services to developers in mainland China under the brand name Aliyun. Documentation is provided on both Alibaba Cloud and Aliyun. OpenID is provided in the RAM (Resource Access Management) product.
Hints
Note Question 1: The token revocation does not work yet in the console sample when refreshing tokens. It seems that only refresh tokens can be revoked. How do we handle this issue? Useful Screenshots
|
|
Thanks for your PR, @gehongyan! Woooo, compared to their Alipay OAuth 2.0 implementation, it's really night and day! (because let's be honest, Alipay is the worst/most non-standard implementation I've ever seen in my entire life! 🤣) This new Alibaba Cloud service doesn't cover Alipay, right?
It's rare, but it happens and it's something the specification allows. There's nothing we can do on our side, but as long as you're able to confirm it works fine by temporarily tweaking the console sample to send the refresh token instead of the access token, that's fine 👍🏻 |
| // Alibaba Cloud requires attaching the "client_id" parameter to revocation requests. | ||
| if (context.Registration.ProviderType is ProviderTypes.AlibabaCloud) | ||
| { | ||
| context.Request.ClientId = context.Registration.ClientId; |
There was a problem hiding this comment.
Note: OpenIddict is expected to take care of sending the client credentials automatically (client_id/client_secret/client_assertion). Were you seeing an error without that custom handler?
There was a problem hiding this comment.
In my recollection, the first time I invoked the token revocation, it returned an error saying the request was missing the client_id parameter. So, I immediately tried adding this handler. After that, the error message changed to indicating that only refresh_token could be revoked.
Strangely, after removing the handler, I haven't been able to reproduce the original error. Furthermore, after adjusting the console sample, the token revocation request succeeded. Therefore, given the current situation, I'll remove it for now.
There was a problem hiding this comment.
Maybe the first time you tried, your client was confidential and was assigned a client secret?
When OpenIddict doesn't find an explicit revocation_endpoint_auth_methods_supported node in the server configuration, it uses client_secret_basic - i.e the default method - if both a client identifier and client secret are expected to be sent. In that case, the client credentials are not sent as regular OAuth 2.0 parameters but are sent using the HTTP WWW-Authenticate header. If no client secret is configured, the client_id is sent alone as a regular OAuth 2.0 parameter.
Can you please check the type of client you configured with Alibaba's portal?
There was a problem hiding this comment.
Can you please check the type of client you configured with Alibaba's portal?
I tested both WebApp and NativeApp, and both can be revoked successfully.
There was a problem hiding this comment.
I tested both WebApp and NativeApp, and both can be revoked successfully.
After changing to web app, you updated your OpenIddict registration to call SetClientSecret(...), right?
Anyway, I took a look at the docs and they don't mention basic authentication support.
Just in case, we should probably tweak the returned configuration response to add client_secret_post to both token_endpoint_auth_methods_supported and revocation_endpoint_auth_methods_supported so that client credentials are always sent as part of the request form.
Can you please give it a try?
There was a problem hiding this comment.
After changing to web app, you updated your OpenIddict registration to call SetClientSecret(...), right?
Actually, I added registrations for both application types in my test code to conduct these tests.
Test code
.AddAlibabaCloud(options =>
options
.SetRegion("CN")
.SetProviderName("AliyunWeb")
.SetProviderDisplayName("Aliyun Web")
.SetClientId("******************")
.SetClientSecret("***********************************************")
.SetAccessType("offline")
// .SetPrompt("admin_consent")
.SetRedirectUri("callback/login/aliyun-web")
.AddScopes("aliuid", "profile"))
// Aliyun NativeApp
.AddAlibabaCloud(options =>
options
.SetRegion("CN")
.SetProviderName("AliyunNative")
.SetProviderDisplayName("Aliyun Native")
.SetClientId("******************")
.SetClientSecret("***********************************************")
// .SetPrompt("admin_consent")
.SetRedirectUri("callback/login/aliyun-native")
.AddScopes("aliuid", "profile"))
// Alibaba Cloud WebApp
.AddAlibabaCloud(options =>
options
.SetProviderName("AlibabaWeb")
.SetProviderDisplayName("Alibaba Web")
.SetClientId("******************")
.SetClientSecret("***********************************************")
.SetRedirectUri("callback/login/alibabacloud-web")
.SetAccessType("offline")
// .SetPrompt("admin_consent")
.AddScopes("aliuid", "profile"))
// Alibaba Cloud NativeApp
.AddAlibabaCloud(options =>
options
.SetProviderName("AlibabaNative")
.SetProviderDisplayName("Alibaba Native")
.SetClientId("******************")
.SetClientSecret("***********************************************")
// .SetPrompt("admin_consent")
.SetRedirectUri("callback/login/alibabacloud-native")
.AddScopes("aliuid", "profile"))Just in case, we should probably tweak the returned configuration response.
Sounds good. Completed. All of the registrations above still work well.
Yes, Alibaba Cloud and Alipay are different products. |
|
Alibaba Cloud categorizes OAuth applications into WebApp and NativeApp. There appear to be subtle differences in their This seems similar to Huawei's implementation. Using the Native application type directly can bypass this, but if a developer specifies WebApp, we should also support this scenario. I'll implement this later. |
It's indeed fairly common: Google does that too... and if you don't specify |
|
I've implemented the The Regarding the |
| var settings = context.Registration.GetAlibabaCloudSettings(); | ||
|
|
||
| context.Request["access_type"] = settings.AccessType; | ||
| context.Request["prompt"] = settings.Prompt; |
There was a problem hiding this comment.
| context.Request["prompt"] = settings.Prompt; | |
| context.Request.Prompt = settings.Prompt; |
You can directly use the Prompt property since it's a standard OIDC parameter exposed by the OpenIddictRequest primitive 😃
There was a problem hiding this comment.
While you're changing that, let's also change line 1862 to use the same pattern:
context.Request.Resources = [settings.Resource];There was a problem hiding this comment.
Completed.
I also changed "display" to the Display property in Huawei and Weibo providers. I hope that I haven't made things worse.
There was a problem hiding this comment.
Excellent, thanks!
I also changed
"display"to theDisplayproperty in Huawei and Weibo providers. I hope that I haven't made things worse.
Great initiative 👍🏻
There was a problem hiding this comment.
The type of "resource" is changed from a
string?to astring?[]?likely resulting in a breaking change.
How that property is represented internally by the OpenIddictRequest primitive doesn't affect how it's eventually represented as an OAuth 2.0 parameter: for authorization request parameters, multi-valued parameters are always represented as multiple parameters (which was explicitly forbidden in the initial OAuth 2.0 specification, but was allowed in subsequent specifications, including the specification that defines the standard version of the resource parameter). Here, since there's just one value, the representation in the authorization request doesn't actually change at all.
That said, I had not realized that setting was optional in the AD provider, so it's possible that an empty parameter value may be set by using the property. Eventually, there shouldn't be any difference in the actual authorization request as OpenIddict excludes parameters with empty values when generating the URI (e.g multiple resource parameters with string.Empty or null as the value), but you're right it's technically a behavior change that is observable from custom event handlers, so I reverted it (I just used the appropriate constant since it's a standard parameter) 👍🏻
There was a problem hiding this comment.
When I made the change, I did have doubts about whether it was a breaking change, which is why I wrote that deleted reply. Later, however, I realized it was about the internal handling of parameters, so I deleted it.
I truly couldn't think of or understand if it would have any other impacts. I appreciate that you considered and pointed it out, which is truly admirable. It seems that raising reasonable doubts is never a bad idea after all. 👍
There was a problem hiding this comment.
I appreciate that you considered and pointed it out, which is truly admirable. It seems that raising reasonable doubts is never a bad idea after all. 👍
🙏🏻
(using the dedicated property actually looked nicer so I pushed a commit to bring it back but guard the call with a string.IsNullOrEmpty() check 😄)
Signed-off-by: Gehongyan <gehongyan1996@126.com>
Signed-off-by: Gehongyan <gehongyan1996@126.com>
|
Response from Aliyun support:
|
Interesting 👍🏻 (their response time is also top notch!) If you don't plan on making additional changes, I'll merge your PR later today 😃 |
Sure! Big thanks for your support! ❤️ |
|
Merged. Thanks a lot for this great new contribution! 🎉 🙏🏻 |











This pull request would like to add Alibaba Cloud (Aliyun) to the list of supported providers.