aaronpk / oauth.net

:lock: The oauth.net website. Feel free to send pull requests with updates.
https://oauth.net
280 stars 340 forks source link

Explanation on id tokens vs access tokens #285

Open eran-medan opened 2 years ago

eran-medan commented 2 years ago

I think there should be some explanation on this sentence in https://github.com/aaronpk/oauth.net/blob/main/public/id-tokens-vs-access-tokens/index.php as this is used as a source for a lot of online discussions.

ID tokens should never be sent to an API. Access tokens should never be read by the client.

I think there should at least be an explanation on the difference in the 3rd party case (e.g. app X wants to use your Y account in to perform scopes Z - in this case the sentence makes a lot of sense) vs the 1st party case (e.g. an SPA with a stateless e.g. serverless backend, which is being used a lot de-facto, in which the client must have access to either access or id tokens to make XHR calls with an authorization header*)

For more context on the confusion this causes (at least to me), please see my rant comment here: https://github.com/auth0/auth0-spa-js/pull/54#issuecomment-1108781511

As it stands now, unless I don't understand the interpretation of client, any SPA out there that sends XHR calls with an Authorization header (even with an access token because they bothered reading the first half of the sentence) will violate the second half.

In addition, Google does recommend sending ID tokens https://developers.google.com/identity/sign-in/web/backend-auth Also AWS API Gateway also allows Cognito ID Tokens.

Since the two of the 3 largest cloud providers allow ID tokens for "your frontend accessing your backend first party use case" (violating the first half), and a lot of "stateless" SPAs out there have to let you read the access token to add an authorization header when making backend calls, I think an explanation on either why it's still bad or why it's sometimes ok (de jure vs de facto) will help people make better educated decisions.

I'll be happy to suggest a pull request with clarifications but before I do I want to make sure I understand it enough to be able to explain it correctly.

* as the alternative of storing an httpOnly cookie with the JWT, which is not possible unless the backend is same origin, and if you send a JS readable cookie might as well store it in sessionStorage / localStorage, let's put aside the XSRF vs XSS tradeoff argument

qds-x commented 1 year ago

Another case of identity tokens being sent to an API is the kubernetes API server https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens, which can be configured to validate the token signature and use the ID token as a source of identity for API requests. The identity token in this instance is obtained by a client (say a kubectl plugin) and then passed as a bearer token in Authorization headers.

I even found an issue raised with the kubernetes project asking whether their use of ID tokens is legitimate, which was closed with a comment explaining that kubernetes is not a resource server wrt. the OIDC issuer.