hydra icon indicating copy to clipboard operation
hydra copied to clipboard

Support RFC8693: Token Exchange

Open adaniline opened this issue 6 years ago • 35 comments

In a zero trust microservices architecture, it is extremely useful to have an ability to generate "on behalf of" access tokens with shorter lifespan and narrower scope when performing service to service calls. Even though OAuth 2.0 Token Exchange (https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16) is a draft right now, it would be extremely useful if Hydra supported a way to exchange an access token with an "on behalf of" token.

Describe the solution you'd like Standard-based:

  • IEFT OAuth 2.0 Token Exchange draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16

Proprietary:

  • Azure AD "On Behalf Of" flow with jwt-bearer grant https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow

adaniline avatar Dec 08 '18 16:12 adaniline

While it looks like a reasonable approach, there are so many different grant extensions to the existing OAuth2 protocol in draft (or self-defined by e.g. Google) that we simply lack the resources to implement and maintain them, which is why drafts are generally not being implemented.

In my personal view, I'm not a fan of using OAuth2, a framework that was initiated to give 3rd party developers a way to access personal information, for things like workload/service auth. I think systems like SPIFFE take a much more sane approach to this. We are actually working with Scytale, co-founded by Evan Gilman (he wrote the Book Zero Trust Networks), to deliver a way to solve workload auth in the context of OAuth2. But this will (obviously) take a while.

Closing this, for now, as a wontfix/wontdo. Feel free to keep the conversation going though.

aeneasr avatar Dec 08 '18 16:12 aeneasr

Sorry @aeneasr for writing in this closed issue but I'm just wondering if you could give more details regarding this statement:

In my personal view, I'm not a fan of using OAuth2, a framework that was initiated to give 3rd party developers a way to access personal information, for things like workload/service auth

We are already using Hydra and OIDC for user authentication and we are planning to use it for authorizing third party applications using the client_credentials grant. I thought that was the right approach and it would simplify our backend authn/authz infrastructure but maybe I'm missing something here?

aberasarte avatar Jun 27 '19 08:06 aberasarte

You can use client_credentials if you want to. The proposed draft above is something completely different.

aeneasr avatar Jun 27 '19 08:06 aeneasr

OK, I misunderstood your sentence then. Thanks for the clarification!

aberasarte avatar Jun 27 '19 08:06 aberasarte

Hi @aeneasr Since January 2020 the OAuth 2.0 token exchange grant type specification is not a draft any more.

In our projects we use Hydra as authorisation server and for some use cases we will need a token exchange. Are there any plans to implement this extension grant type or is there any documentation on how to do it by ourself?

smeir avatar Mar 23 '20 14:03 smeir

We currently lack use cases / popular demand and resources to tackle this, but do welcome contributions. As a word of caution, this will be a lot of work to implement!

aeneasr avatar Mar 23 '20 14:03 aeneasr

Hi @aeneasr We would like to thrive this topic forward with a contribution. Digging through the source code some points are pretty clear. But we would like to have a talk before starting this to get the right direction/architecture decisions.

0ka avatar Apr 20 '20 06:04 0ka

Sounds good! I'll reopen that - for clarification, this will be about implementing https://tools.ietf.org/html/rfc8693 right?

aeneasr avatar Apr 20 '20 12:04 aeneasr

Yes that is RFC8693. We would create a new handler/oauth2/flow_token_exchange.go in the fosite project. Do we need an own issue in fosite or is this issue here sufficient?

0ka avatar May 05 '20 10:05 0ka

Sorry, I overlooked your comment. Yes - no need to create another issue!

aeneasr avatar May 14 '20 13:05 aeneasr

Our use case: We have three applications A, B, and C. User U grants application A access to B and C with auth code grant. Offline access should also work, means that A will get a refresh token. Now application A accesses application B and B accesses application C (in the name of user U), allways with offline access. Here we need the token exchange (A uses its token to access B in the name of U, B exchanges the token to get an own access and refresh tokens to access C in the name of U). This chain of delegation could of course be longer (D, E, ...).

Implementation idea:

  • New flow_token_exchnage.go in fosite
  • Clients that have grant type "urn:ietf:params:oauth:grant-type:token-exchange" are allowed to ask for token exchange
  • Request for token_exchange is similar to client_cresentials request with additional parameters as per RFC8693 (e.g. "subject_token", "subject_token_type")

Permission checks Option 1:

  • Clients have an additional claim "may_act" with a list of all IDs of the clients that should be allowed to exchange tokens. Tokens/request from the cient than contains the "may_act" field. During processing of the token exchange fosite verify that the original token/request allows the exchange for the current client requesting the exchange. (Issue here is that the spec define only one may_act field and not a list, whould be needed for chained delegation)

Option 2:

  • On token-exchange hydra calls a configured callback similar to the consent app that allows to make checks externaly.

What's your opinion on that?

mpnunes avatar Jun 22 '20 17:06 mpnunes

Thank you for your thoughts! I think that sounds reasonable! The idea of may_act is to restrict who can exchange an access token? So in your example, the client of C would have may_act: B?

Are there best practices around this? I do think that it might be tricky if every client is allowed to exchange token with one another so we probably need some type of restriction.

I think a callback wouldn't work that well because there is no user interaction (similar to client_credentials), so probably option 1 would be the way to go.

aeneasr avatar Jun 26 '20 08:06 aeneasr

Correct, the may_act claim specifies whether a client is allowed to exchange the token it has received in order to "act" has the original client (of the token it received).

So in the example before (and in answer to your question) the token of A should contain may_act claims for B and C (assuming C should keep offline access / get a refresh token), specifying that B and C can exchange the token sent by A.

The problem we have in this scenario is that rfc8693 only provides a brief example with a flat structure for may_act, e.g.:

"may_act" : { "sub": "B" "iss": "..." }

and what we need would rather be something like an array of multiple subjects e.g.:

"may_act" : [ { "sub": "B" "iss": "..." } { "sub": "C" "iss": "..."" } ... ]

in order to define a possible chain of delegation, or perhaps something simpler. RFC 8693 is not so clear at this point. Quote:

"The may_act claim makes a statement that one party is authorized to become the actor and act on behalf of another party. The claim might be used, for example, when a subject_token is presented to the token endpoint in a token exchange request and may_act claim in the subject token can be used by the authorization server to determine whether the client (or party identified in the actor_token ) is authorized to engage in the requested delegation or impersonation. The claim value is a JSON object, and members in the JSON object are claims that identify the party that is asserted as being eligible to act for the party identified by the JWT containing the claim."

I totally agree with you, not every client should be able to exchange any token it receives, therefore the importance of the "may_act" claim in the token to be exchanged. Unfortunately I could not find any best practices on this subject.

After a longer discussion we came up with the use case that at some point, in the previously given scenario, user U may wish to revoke the a exchange grant it gave before to some application (e.g. application B or C). If we restrict the check to the may_act claim within the token to be exchanged, it would not be possible to revoke a previously issued token when this has e.g offline access, as the application could indefinitely refresh its token. Considering this, it would be enough to have this information within the client, at least for an first implementation, as a list of "clients" that are allowed to perform the exchange. So in the previous example, U gave exchange rights to applications B and C, B did an exchange and got an own refresh token, passes the token to C and C exchanges and gets an own refresh token. If at some point U remove the exchange permission to B, when using the refresh token again B would get an unauthorized. This would imply extending the refresh logic to check if the client refreshing the exchanged token still has the right to do so.

mpnunes avatar Aug 22 '20 15:08 mpnunes

I am marking this issue as stale as it has not received any engagement from the community or maintainers in over half a year. That does not imply that the issue has no merit! If you feel strongly about this issue

  • open a PR referencing and resolving the issue;
  • leave a comment on it and discuss ideas how you could contribute towards resolving it;
  • open a new issue with updated details and a plan on resolving the issue.

We are cleaning up issues every now and then, primarily to keep the 4000+ issues in our backlog in check and to prevent maintainer burnout. Burnout in open source maintainership is a widespread and serious issue. It can lead to severe personal and health issues as well as enabling catastrophic attack vectors.

Thank you for your understanding and to anyone who participated in the issue! 🙏✌️

If you feel strongly about this issues and have ideas on resolving it, please comment. Otherwise it will be closed in 30 days!

github-actions[bot] avatar Sep 21 '21 00:09 github-actions[bot]

Marked as stale in error.

aeneasr avatar Sep 21 '21 05:09 aeneasr

Hello contributors!

I am marking this issue as stale as it has not received any engagement from the community or maintainers a year. That does not imply that the issue has no merit! If you feel strongly about this issue

  • open a PR referencing and resolving the issue;
  • leave a comment on it and discuss ideas how you could contribute towards resolving it;
  • leave a comment and describe in detail why this issue is critical for your use case;
  • open a new issue with updated details and a plan on resolving the issue.

Throughout its lifetime, Ory has received over 10.000 issues and PRs. To sustain that growth, we need to prioritize and focus on issues that are important to the community. A good indication of importance, and thus priority, is activity on a topic.

Unfortunately, burnout has become a topic of concern amongst open-source projects.

It can lead to severe personal and health issues as well as opening catastrophic attack vectors.

The motivation for this automation is to help prioritize issues in the backlog and not ignore, reject, or belittle anyone.

If this issue was marked as stale erroneous you can exempt it by adding the backlog label, assigning someone, or setting a milestone for it.

Thank you for your understanding and to anyone who participated in the conversation! And as written above, please do participate in the conversation if this topic is important to you!

Thank you 🙏✌️

github-actions[bot] avatar Sep 22 '22 00:09 github-actions[bot]

Hi, any news on this?

thomasvargiu avatar Oct 07 '22 13:10 thomasvargiu

https://datatracker.ietf.org/doc/html/rfc8693 declares new grant type "urn:ietf:params:oauth:grant-type:token-exchange". We tested hydra 2.0 for use with new grant type but without success. Also, we didn't found any configuration options for this flow or any code in codebase which is intended to support it

FYI @aeneasr

drwatsno avatar Nov 25 '22 08:11 drwatsno

Same here, we are also trying to use the same. Although same is implemented in Keycloak. We were very enthusiastically planning to migrate from keycloak but unfortunately got stuck here.

rverma-dev avatar Nov 27 '22 15:11 rverma-dev

Why not implement it and submit a pull request?

I'm sure the project would greatly appreciate it.

ghenry avatar Nov 27 '22 15:11 ghenry

@ghenry, the release notes state that this RFC is implemented, but I can't seem to find any trace of it in the docs or codebase.

alee792 avatar Nov 28 '22 20:11 alee792

Where are folks seeing this mentioned?

Nothing on the code base - https://github.com/ory/hydra/search?q=RFC8693

ghenry avatar Nov 28 '22 21:11 ghenry

Nothing here https://github.com/ory/hydra/releases/tag/v2.0.2

ghenry avatar Nov 28 '22 21:11 ghenry

https://github.com/ory/hydra/releases/tag/v2.0.0

On Mon, Nov 28, 2022, 3:55 PM Gavin Henry @.***> wrote:

Nothing here https://github.com/ory/hydra/releases/tag/v2.0.2

— Reply to this email directly, view it on GitHub https://github.com/ory/hydra/issues/1218#issuecomment-1329806166, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABO2MOOR54MID6D5XNGERDTWKUS5HANCNFSM4GJG2QEQ . You are receiving this because you commented.Message ID: @.***>

alee792 avatar Nov 28 '22 22:11 alee792

It looks like it might just be from the go client sdk:

https://github.com/ory/hydra/blob/d768cf6580b3410f7d0b3b9420760ce0818a5fe2/client/client.go#L74 https://github.com/ory/hydra/pull/3337 https://github.com/ory/hydra/blob/74d4569a0c15d7b2d1bbf435937d0cf98175ff57/internal/httpclient/docs/OAuth2TokenExchange.md https://github.com/ory/hydra/blob/d768cf6580b3410f7d0b3b9420760ce0818a5fe2/oauth2/handler.go#L779 https://github.com/ory/hydra/blob/74d4569a0c15d7b2d1bbf435937d0cf98175ff57/internal/httpclient/docs/OAuth2Api.md https://github.com/ory/hydra/blob/74d4569a0c15d7b2d1bbf435937d0cf98175ff57/internal/httpclient/docs/OAuth2Api.md#Oauth2TokenExchange https://github.com/ory/hydra/blob/c586e035bb78752747845f6a27189121d2d53034/internal/httpclient/api/openapi.yaml#L3393 https://github.com/ory/hydra/blob/c586e035bb78752747845f6a27189121d2d53034/spec/swagger.json#L2889

ghenry avatar Nov 28 '22 22:11 ghenry

I believe those are auth code for token exchange but will take a second look.

On Mon, Nov 28, 2022, 4:11 PM Gavin Henry @.***> wrote:

It looks like it might just be from the go client sdk:

https://github.com/ory/hydra/blob/d768cf6580b3410f7d0b3b9420760ce0818a5fe2/client/client.go#L74 #3337 https://github.com/ory/hydra/pull/3337

https://github.com/ory/hydra/blob/74d4569a0c15d7b2d1bbf435937d0cf98175ff57/internal/httpclient/docs/OAuth2TokenExchange.md

https://github.com/ory/hydra/blob/d768cf6580b3410f7d0b3b9420760ce0818a5fe2/oauth2/handler.go#L779

https://github.com/ory/hydra/blob/74d4569a0c15d7b2d1bbf435937d0cf98175ff57/internal/httpclient/docs/OAuth2Api.md

https://github.com/ory/hydra/blob/74d4569a0c15d7b2d1bbf435937d0cf98175ff57/internal/httpclient/docs/OAuth2Api.md#Oauth2TokenExchange

https://github.com/ory/hydra/blob/c586e035bb78752747845f6a27189121d2d53034/internal/httpclient/api/openapi.yaml#L3393

https://github.com/ory/hydra/blob/c586e035bb78752747845f6a27189121d2d53034/spec/swagger.json#L2889

— Reply to this email directly, view it on GitHub https://github.com/ory/hydra/issues/1218#issuecomment-1329821236, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABO2MOJXCR5OSJJC56M6RMDWKUUY3ANCNFSM4GJG2QEQ . You are receiving this because you commented.Message ID: @.***>

alee792 avatar Nov 28 '22 22:11 alee792

A low effort search to check if the IETF URN for exchange is used within Hydra or Fosite yields no results: https://github.com/search?l=&q=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange+repo%3Aory%2Fhydra+repo%3Aory%2Ffosite&type=code

@aeneasr, any chance we can get clarification and whether it's implemented or the release notes jumped the gun?

alee792 avatar Nov 30 '22 18:11 alee792

OAuth 2.0 Token Exchange (RFC8693) is now fully supported, including the JSON Web Token profile!

it seems only support rfc7523 @aeneasr

mutexlock avatar Dec 02 '22 11:12 mutexlock

Yes, we messed up in here unfortunately. Can you help us identify all the places where the incorrect RFC is linked? We have to update it :)

aeneasr avatar Dec 02 '22 11:12 aeneasr

Hello all,

have a look at this community project: https://github.com/Exact-Realty/ts-hydra-rfc8693

This will help you use OAuth2 Token Exchange until its implemented in Ory Hydra

vinckr avatar May 23 '23 08:05 vinckr