OpenIddict - Additional authentication workflow examples
Is there an existing article or article request for this?
- [X] I have searched the existing resources
Describe the article you'd like
If an external system (browserless) wants to communicate with API method, which requires authentication (so that permissions for this particular user are determined) it should provide JWT. But jwt has to be generated inside auth server (OpenIddict) based on provided username/password. This is ordinary flow in abp.
However, many external system does not have option that additional development should be made to handle authentication with abp-based application.
There should be other way (safe, of course) that external browserless system introduce (authenticate) itself to abp-based application.
I found: https://oauth.net/2/grant-types/
So how to implement or use "Authorization flow" (https://oauth.net/2/grant-types/authorization-code/) or "Device Code" (https://oauth.net/2/grant-types/device-code/) using OpenIddict in abp and which is more suitable for described scenario?
Thank you.
I also found this: https://learn.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/msa-oauth?view=odsp-graph-online Look at "Code flow" section.
hi @leonkosak
OpenIddict supports the code flow. And it meets the standard of oauth2. So you can find a third-party class library in your browserless client.
@maliming as far as I understand "Client credentials grant" is the preferred way for my use case (machine-to-machine communication): https://documentation.openiddict.com/guides/choosing-the-right-flow.html#client-credentials-grant-recommended-for-machine-to-machine-communication
How to create a user in abp-based application for such login? I cannot find documentation about that. Thank you.
hi
There is no user concept if you using client_credentials.
It is a server(client)-to-server(client) communication.
How can I add "client_credentials user" so that I can authenticate that way? Is this even possible or do I have to decide just for one method in abp application?
It is impossible by default. This is the specification of the oauth2 protocol.
So you suggest, that life-long JWT token should be generated for specific abp user and then always used as Bearer header inside http request in external system? Is it possible to generate jwt based on Expire date? https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client.IdentityModel.WebAssembly/Volo/Abp/Http/Client/IdentityModel/WebAssembly/AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator.cs
hi @leonkosak
I suggest you follow the rules of the oauth2. This actually has nothing to do with abp or openiddict.
Don't know if it's still relevant as the question was posted 3 months ago and the OP probably found out the solution, but I'll add my 2 cents.
@leonkosak If you need to use "client credentials grant" for machine-to-machine authentication, you need to register the client as an application in Openiddict, not as a user, that's why @maliming said it's impossible.
You can see the sample in OpenIddict sample repository.
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "console",
ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207",
DisplayName = "My client application",
Permissions =
{
Permissions.Endpoints.Token,
Permissions.GrantTypes.ClientCredentials
}
});
In this case, the client is an application in OpenIddict, there is no "user" involved in the authentication process, in fact, in order to use "client credentials grant" or "device authorization grant" flows, the device needs to be registered as an application with a client_id and a client_secret, you can do the application registration in your code (like the sample does above) or write a UI to manage all application (client) registrations.
Hope this clarify the confusions, I had the same question when I started to use OpenIddict and it took me hours to finally get it clarified.
Thank you @JamesLiang23!
I found this solution (and also how new applications can be created via GUI in abp Commercial), but I still don't know how to limit application for M2M communication inside abp that has access only to specific API methods (exactly what can be achieved with permissions on users/roles and Authorize["permission_name"] attribute on API method).
If @JamesLiang23 or @maliming know an answer, please let me know. :)
@leonkosak To use AuthorizeAttribute, the access token you issue to the device will need to include some claims like roles or custom permission claims.
Please refer to the sample code, after you authenticated the client, you may add role or permission claims to its access token like follows.
identity.SetClaims(Claims.Role, "DeviceRole");
identity.SetClaim("Permission", "SalesOrder.Read");
Next time when the device present the access token to the resource server, the server can use Authorize attribute on a Web API method to check its eligibility.
P.s. I am not aware of a built-in feature to assign roles or permissions to applications (clients), typically OAuth2 use scope to limit the API access, you may want to create your own data tables and UIs to store/assign roles to applications. Please correct me if I'm wrong about it.
I understand, thank you @JamesLiang23. @maliming do you have any recommendations on how to achieve described on custom application (for M2M communication purposes) in abp/abp Commercial? I would like to achieve this dynamically and via GUI as much as possible, because end users would create such applications for M2M communication. Thank you.
hi @leonkosak
You can grant permissions to a client/application on openiddict management page.
Then check the permissions on the application service/API endpoint.
Thank you @maliming. I have one more question.
https://documentation.openiddict.com/guides/choosing-the-right-flow.html
Based on this documentation, abp application (at least MVC version) uses grant_type=password, which is not recommended according to this documentation (and also labeled as Legacy in official documentation) - and will probably be abandoned in the future versions of OAuth.
As far as I understand, the most recommended flow for interactive use (which involves users) is Authorization code flow. If this assumption is correct - should abp MVC UI (Razor Pages) use Authorization code flow when users login into application? What do you think @maliming?
Actually ABP applications including MVC app use the authorization code flow, not the resource owner grant flow. When the DbMigrator runs, it uses OpenIddictDataSeedContributor in the Domain project to create an application for MVC app and specify the grant types to authorization code flow and implicit, please see the code in the template. The MVC app uses this application (client_id and client_secret configured in its appsettings.json) to redirect the users to the auth server for authentications.
Could you point out where do you find the password flow in ABP applications?
hi
abp application (at least MVC version) uses grant_type=password,
ABP uses the authorization code instead of the password for MVC login.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.