abp icon indicating copy to clipboard operation
abp copied to clipboard

OpenIddict - Additional authentication workflow examples

Open leonkosak opened this issue 2 years ago • 17 comments

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.

leonkosak avatar Sep 14 '23 11:09 leonkosak

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.

leonkosak avatar Sep 14 '23 11:09 leonkosak

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 avatar Sep 15 '23 06:09 maliming

@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.

leonkosak avatar Sep 18 '23 12:09 leonkosak

hi

There is no user concept if you using client_credentials. It is a server(client)-to-server(client) communication.

maliming avatar Sep 19 '23 00:09 maliming

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?

leonkosak avatar Sep 21 '23 11:09 leonkosak

It is impossible by default. This is the specification of the oauth2 protocol.

maliming avatar Sep 22 '23 01:09 maliming

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

leonkosak avatar Sep 22 '23 20:09 leonkosak

hi @leonkosak

I suggest you follow the rules of the oauth2. This actually has nothing to do with abp or openiddict.

maliming avatar Sep 27 '23 02:09 maliming

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.

JamesLiang23 avatar Dec 06 '23 01:12 JamesLiang23

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 avatar Dec 06 '23 05:12 leonkosak

@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.

JamesLiang23 avatar Dec 06 '23 05:12 JamesLiang23

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.

leonkosak avatar Dec 06 '23 06:12 leonkosak

hi @leonkosak

You can grant permissions to a client/application on openiddict management page.

Then check the permissions on the application service/API endpoint.

image

maliming avatar Dec 06 '23 08:12 maliming

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?

leonkosak avatar Dec 13 '23 15:12 leonkosak

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?

JamesLiang23 avatar Dec 13 '23 18:12 JamesLiang23

hi

abp application (at least MVC version) uses grant_type=password,

ABP uses the authorization code instead of the password for MVC login.

maliming avatar Dec 14 '23 02:12 maliming

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.

stale[bot] avatar Apr 26 '25 23:04 stale[bot]

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.

stale[bot] avatar Jun 26 '25 23:06 stale[bot]