-
Notifications
You must be signed in to change notification settings - Fork 391
Make id_token available via Auth0Client.getIdToken() #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Hi @tehpsalmist, First of all, thanks for your work on this PR. We've had some discussion about this internally and the decision we came to is that we won't be exposing the ID token directly from the SDK. While you have a case for using with the Hasura GraphQL platform, we don't feel it's strong enough to take this particular feature forward in the SDK itself. It's strange to say that given that enabling the ability to retrieve the ID token is fairly trivial (as you've kindly demonstrated), but it's a case of "just because we can, doesn't mean we should". It enables an undesirable precedent where people use these tokens to then go and call APIs (precisely what the access token is for). In this case, given that there are other ways to work with Hasura than ID tokens (i.e., use an access token in JWT form, or using their webhook authentication feature), we need a better concrete example before we enable the ability to do this. Happy to continue the discussion - closing this for now, but if you have more examples for us to have a look at and discuss, please let us know. |
|
Yeah, I suppose that's fair. Maybe I just have some fundamental misunderstandings of what differentiates and idToken from a JWT access token in the first place. |
|
Is there clear documentation somewhere on what the 2 tokens are actually supposed to be used for? When we were initially speaking with the Auth0 account folks and evaluating Auth0, and I asked about this, they just said one caries the identity and the other the permissions, but never really explained why they weren't one combined token or how they were supposed to be used. After speaking with the Auth0 Professional Services folks, I was under the impression that the ID Token was the one you would pass to APIs, and the Authorizations Token was for use internally by an API, but that API would look up that token based on the identity. (thought what they may have meant is that the UI gets the ID Token so that it can display the user's name and stuff like that, and the API uses the Auth Token to validate permissions) As a consumer of Auth0 and someone making an API; an API always needs to know both the Identity and the Authorizations of all requests. Having to fumble around with 2 tokens seems overly complicated. If I wasn't using this library and had instead implemented this myself, my implementation would have been to pass the ID Token to APIs, not the Auth token, but I guess I would have been wrong in doing so? It seems very unclear... As a suggestion for Auth0 written APIs, it would be really nice if functions and parameters were not named |
|
@rally25rs There is an amazing video series we produced that has everything you need to know about identity. If you want only the specifics (access_token vs id_token), here's the link that will take you to that direct point in time: https://auth0.com/docs/videos/learn-identity/04-calling-an-api#wistia_yw6hmdhnft?time=2007.5 |
|
Hi @luisrudge , I know this PR was closed a few days ago, but we're trying to use this library to get granted to a Kong Gateway API using the native JWT module, following this old post and I'm trying to understand the whole process and/or update it. I checked the video you sent and our business case is exactly the narrowed case when we need to extract information out of the id_token. Is there any workaround for this use? Thanks |
|
Yea, I have this need too. We have a gateway that's using JWT tokens. It's able to decrypt JWT from Auth0 but we can't properly retrieve it on frontend... |
|
It seems the larger issue here is that getting an access_token in jwt format requires extra legwork creating a "dummy" server, so maybe that is where the work can be done to make it easier to toggle the format of the access_tokens when a server isn't otherwise needed by the developer. |
|
@tehpsalmist that's not the case, though. You can get a JWT just by using a custom |
|
So there is no need to set up an API in Auth0? |
|
@tehpsalmist Yes, but that's not a dummy server 😬 The only reason you should ever need an access token is to interact with an API server. So, it makes sense to require you to create an API in the Dashboard so you can request an access token to that specific API endpoint. |
|
Auth is hard. |
|
@tehpsalmist I fully appreciate that! That's what we're here for 😅 |
|
For anyone else using Hasura I suggest the approach that @tehpsalmist posted at hasura/graphql-engine#2655 (comment). |
|
Here is a use case for the id_token being available in the Auth0 SPA JS Library which is validated by the video you shared about the tokens. First party apps in the video at 35:50 We are doing an SPA and first party API that, specifically addressed by the video starting at 35:50. In our case we have an api gateway that needs to authenticate the user, capture contact data to keep our CRM up to date, and delegate requests based on our sharding strategy which is driven by information which can be found in the id_token. In this case the opaque access token received by default is insufficient/inefficient for our uses because it means we need to make another call to Auth0 from our API to get the userprofile and update our CRM. The second requests is a point of failure, and requires additional bandwidth and processing time that can become expensive at our scale. |
|
@dopry We have now exposed the ID token from the library since this issue was closed, you can find an example of how to do that here. |
|
Link is broken, here is the relevant line auth0-spa-js/static/index.html Line 367 in 476caea
This is how I get my idToken: |
|
@stevehobbsdev I deeply suggest you add this type of information to the calling an API / quickstart guides. I have been for the past 5 days bouncing from Auth0js, to passport-auth0 to react-sdk-spa and I have been very confused about what to do. I feel like you should really explain things instead of having quickstarts. Quickstarts are good but not for something as important as authentication/authorization. I have finally seen that you have decided to expose the id token and that's great news! |
|
Thanks for raising @afrancht. This information does not appear in those sections because using an ID token to call APIs is (mostly) not recommended. You should use an access token instead when performing those tasks. There are however some very limited use cases where using an ID token in this manner cutie he useful, which is why we chose to give access to this token in its original form. We have a fantastic suite of videos that attempt to explain the ins and outs of identity, including this section on calling an API which should hopefully clear things up (Scroll down to hit the link on "Do not use ID tokens to call APIs") |
|
Hey @stevehobbsdev thanks for the videos, I had not come across these before. It's interesting because I don't see addressed or haven't understood properly the scenario where I use my client to retrieve an access token from Auth0 and then use that token to sign in into my API, creating a user in my database and then issuing a token myself with only the userId to authenticate and authorize certain calls. For instance: say a bank wants to do a transaction from Alice (id: 123) to Bob (id: 456) as far as I know I cannot distinguish an access token from Alice or Bob when I send it to my API from my client, thus I need an ID_TOKEN? I'm sure that this has probably been solved with access tokens but I have not found/understood a way to do such a thing. For clarity I've created this diagram: Please tell me what I'm doing wrong as I have tried passport-auth0 and faced a problem there, using only the react-sdk isn't enough and auht0.js looks like it's slowly being substituted. Thank you so much Steve! |
|
@afrancht The access token will contain a If you need more detailed profile information, you can then use this access token to call the userinfo endpoint. Does that make sense? |
|
As someone who’s trying to integrate Auth0 with a system that expects JWTs, now I’m confused. I have prior experience with Firebase and ID tokens. Seems that Firebase Authentication SDK provides direct access to ID tokens and when calling a Callable Cloud Function, it sends the So I am surprised that Auth0 says “Do not use ID tokens to gain access to an API.” I have watched the linked video and articles about
The recommendations from Google and Auth0 are contradicting each other. It seems to me like there must be some nuance that makes sending ID tokens to API a recommended practice for Firebase Auth, but not recommended for Auth0. Am I missing something here? (I stumble upon this issue while trying to retrieve the ID token from |
|
Thanks for raising @dtinth. This is more general feedback for the Auth0 product and guidance, I would encourage you to raise it for discussion on our Community Forums where someone more familiar with the overall product guidance and direction will be able to take that feedback on board 👍🏻 |
|
I understand that according to https://oauth.net/id-tokens-vs-access-tokens/ Which I assume is the source of the contention. But this raises the questions:
My interpretation is: if you are working with a 3rd party, the claims are 100% correct, the client should never even see the tokens, e.g. integration with gmail - you get the code, the backend exchanges it for tokens, stores it in the backend, when you make calls to the gmail API, you only send an access token, in this case the sentence makes perfect sense. But for a 1st party (your frontend making calls to your backend) you have basically 2 choices, make all XHR calls with credentials included (which means you need XSRF protection and all, and the client basically has no access to any tokens at all, which is trading off a slight less XSS risk for the favor of needing XSRF) - but in serverless scenarios, storing a session state is not always desirable, so many implementations mean you need either an access token or id token available in the client, BOTH will violate the Therefore I would say that this sentence and page needs to be explained, and defended, because the industry seems to shrug and vote with their feet. Educating people should be made by better explaining the spec, and also explaining why it's ok to have the client read the access token but not ok to send an id token... and why a 1st party use case is the same as a 3rd party use case. Understanding causes people to change behavior more than just plain axioms. And while I do understand (and agree) the case with a 3rd party OAuth2 flow, I don't see how it's possible to build a stateless (cookieless) SPA without violating at least one of the parts of that requirement. It means that any (even same origin) "Ajax" call with an Authorization header, is in violation, period, both for id token and access token. So we should all go back to cookie based XHR with include credentials? I expect CSRF going back to be an OWASP top 10 this way... tl;dr: In my very humble opinion. There is either a security issue or there isn't with sending id tokens, if there is, it should be part of NIST, SOC2, PCI, and every single security framework, and no one should be sending id tokens anywhere. If there isn't, then this is an opinion / recommendation, and users should be able to make an informed choice. p.s. I might be completely wrong and misinterpreting the spec, so please forgive my ignorance and I'll be happy to learn what I am missing. |
|
@eran-medan This would be a good discussion for our Auth0 Community rather than here on SDKs, as the topics you're discussing transcend any given SDK into more general identity topics. However, couple of things I wanted to mention:
Read this as "access tokens should never be decoded by the client". An access token forms part of the contract between the IdP and the resource server, and doesn't involve the client. The client is able to access the access token insofar as it can take it and attach it to an outgoing HTTP request to an API (otherwise, how would you call protected APIs?), but shouldn't try to inspect it or decode it and make use of any of the claims within. This is to protect the client from changes to that contract, i.e. changes to the token format or anything within that is explicitly intended for consumption by an API.
This scenario you mention is one of the few cases where using an ID token in this manner is probably acceptable and is really up to you to implement. It's part of a wider pattern called BFF (Backend For Frontends) where you have a backend specifically there to service your single frontend, so there's a 1:1 mapping between a backend and its frontend. It'd be a simpler model to just use cookies in this case but you could do it with ID tokens. More broadly, the issue with using ID tokens to access resource servers from many client apps is that, beyond ID tokens not being intended for resource servers and are explicitly intended to be consumed by client applications, they also contain no concept of scope and thus don't have any real security control, as you can't control what the token can do. So you get an all-or-nothing security model. |
Not to be rude but the Auth0 side of this discussion is crazy to me. The vast majority of startups small enough to really need a product like Auth0 are likely not doing complex microservice architectures with several backends talking to each other and strict separation between authorization servers and resource servers. If my company is doing monolithic BFF for the foreseeable future, why can't we just get the id token, send it with requests, and have our API server check it to verify the user? This seems like it would be a very common use case for starting Auth0 customers and something that should even have a Quickstart of its own. Instead we get unexplained blanket statements in the official docs like "ID tokens should never be sent to an API." Looking for explanations of these statements turns up acknowledgement of the use case, but refusal to support it with suggestions like:
Obviously, I'll be going with number 1 to start with, but I really don't understand why it should be like this. It seems to be encouraging unnecessary complexity. What is the actual goal here?
Cookies are a storage mechanism, not an authentication/authorization method in and of themselves. "Just use cookies" isn't a solution because it says nothing about what data should be in the cookies and how an API should consume that data. |
|
To address the concern of the audience of the Id token not matching the eventual recipient, is it not possible to have our front end request an ID token with our API as the audience? That is, after all, what we are intending to do-- get some proof of the user's identity from Auth0 that our API can consume. As with access tokens, the front end doesn't even need to look at it-- just pass it along. |

Description
This PR makes the id_token directly available via Auth0Client.getIdToken(). This is very useful for anyone using JWT authentication in their server (for example, Hasura has JWT mode, which is seamless to use... if you have the id_token to send).
References
A brief discussion occurred in the Auth0 Community Forum.
Testing
Unit tests are included.
The app produced by
npm run devwill fascilitate manual testing, which can be done by simply calling the.getIdToken()method after successfully calling.getTokenSilently().getTokenWithPopup().loginWithPopup()Additional manual testing was done on Chrome from a Mac in a React app, following the quick start guide for auth0-spa-js.
Checklist
masterI verified that the auto-generated docs are accurate, but didn't venture much further than that.