Skip to content
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

Use/Validate Authorization in external API #402

Closed
1 of 5 tasks
janus-reith opened this issue Jul 7, 2020 · 5 comments
Closed
1 of 5 tasks

Use/Validate Authorization in external API #402

janus-reith opened this issue Jul 7, 2020 · 5 comments
Labels
question Ask how to do something or how something works stale Did not receive any activity for 60 days

Comments

@janus-reith
Copy link

Your question
I'm looking for the most straight forward way to use authentication in a separate GraphQL API.

What are you trying to do
Currently, I have implemented a custom oauth 2 flow, and each client can request their access token(but not request token) in an api endpoint, where it is read from their encrypted cookie. That token is then passed as Header when querying the GraphQL API from client.

I want to use next-auth to provide additional signup options, and I already found issues describing how to make the access token available as part of the session that the client can fetch.

However, this has two drawbacks:

  1. I wouldn't know how the email signup would be validated.
  2. I would have to implement logic for each provider in my API, e.g to verify a twitter access token on twitter.

What I'm looking for is a generalized way to validate a session coming from one of the next-auth supported Providers, including email. Also, I wondered if there is some kind of caching for finished authorization flows during their lifespan, which I could make use of?
Because I imagine that fetching e.g. the twittter api each time an authenticated request comes in to validate the token is highly inefficient and slow.

A general consideration: While most implementations will use the same domain, this should also work if the API is not using the domain and therefore probably has no safe access to the cookie.

Documentation feedback

  • Found the documentation helpful
  • Found documentation but was incomplete
  • Could not find relevant documentation
  • Found the example project helpful
  • Did not find the example project helpful
@janus-reith janus-reith added the question Ask how to do something or how something works label Jul 7, 2020
@iaincollins
Copy link
Member

iaincollins commented Jul 7, 2020

Currently NextAuth.js provides account creation, authentication and session management.

It doesn't currently support also handling rotating provider Access Tokens or tracking when they expire for API access - if you want to do that you will need to write code to handle that explicitly.

To make this easier, it records the Refresh Token (and initial Access Token) for each user and provider on the first time a signs in with a provider (if they are supplied by the provider) and it creates a table to store Access Tokens and when they expire so you know when you need to fetch a new one.

RE: Cross domain access

You can use a custom cookie policy to allow same domain access to the Session Token for subdomains - this actually just came up in #405 which links to the relevant documentation - but you cannot share cookies between domains as that is a fundamental limitation of cookies.

If you need to share data across domains then you are probably going to need to look at a solution involving iFrames and the postMessage API.

@janus-reith
Copy link
Author

@iaincollins Thanks for the feedback!

You can use a custom cookie policy to allow same domain access to the Session Token for subdomains - this actually just came up in #405 which links to the relevant documentation - but you cannot share cookies between domains as that is a fundamental limitation of cookies.

If you need to share data across domains then you are probably going to need to look at a solution involving iFrames and the postMessage API.

I think I won't approach this option further just as I expected initially, as I can't seem to cleanly fit this into my usecase.
Technically, sure, having an iframe to somewhere on the domain my API is hosted on to make sure that also has a cookie set with credentials I send over using postMessage would probably be possible, but with several drawbacks. E.g. the first authenticated GraphQL call would have to be deferred until that iframe request finished, so performance would in all cases be suboptimal.

To make this easier, it records the Refresh Token (and initial Access Token) for each user and provider on the first time a signs in with a provider (if they are supplied by the provider) and it creates a table to store Access Tokens and when they expire so you know when you need to fetch a new one.

This is good to know, and the part that might actually be interesting to me. I assume these tokens only are stored in the database after they were verified on the Provider they belong to? Like, I can't somehow inject a wrong token there as an user, assuming I somehow got past the cookie encyption?
If that is how it works, I guess it is safe to assume that my API could use this as the source of truth during the time a token is valid. (The only exception is, that the OAuth Provider couldn't really revoke that access token during its lifespan for this usage then, but I guess that is ok.)

Now, instead of directly grabbing the access token and doing a provider-specific check in my API, I could pass some identifier to my api, which could then call some api route that makes use of some to-be-determined next-auth functionality, which returns if an entry exists for that identifer, which provider it belongs to, plus the auth token and maybe other relevant session data.
I wonder if any such non-guessable identifier or kind of internal token exists already and is stored together with that data, maybe the crsf token?
While I could just use any access token for this some provider issued, I assume there is some probability left that two different providers issue the same token, therefore I better avoid that.

Also, I considered to make things a bit more secure by having both the nextjs api and my API use a secret known to both, so don't even have the pass the bare token, but that is probably redundant as at that point, leaking the encrypted token would have the same result and give access anyway. Instead, protecting the next-auth API route as such might make more sense.

So in short, what I would probably need:

  • A provider-agnostic, non-guessable unique field on each stored token record which allows to return the access token + further details if known, which doesn't compromise security. (Maybe that already exists, will look it up right away)
  • A way to expose functionality over an API route which allows to fetch details of that database record by providing such an identifier/token. Protecting this route with some static secret also known to my API might actually give some added security, assuming the leaked identifier isn't already used somewhere else internally where it could provide direct access (e.g. in the case of the crsf token somehow?)

@ericvrp
Copy link

ericvrp commented Aug 14, 2020

We are building a version 2 site with NextJS and next-auth is a great fit for us. However it will take time to have this feature complete in production and for the current version 1 (plain html/javescript) we already need to use the same authentication system.

So the plan is to have version 2 in production with just the next-auth features and have v1 use this cross domain.
BTW v1 is already on a subdomain so my guess is that creating a custom cookie as described in #405 will not work?

Is there an example of using on iframe with postMessage to make this work?

@stale
Copy link

stale bot commented Dec 5, 2020

Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep ot open. Thanks!

@stale stale bot added the wontfix This will not be worked on label Dec 5, 2020
@balazsorban44 balazsorban44 added stale Did not receive any activity for 60 days and removed wontfix This will not be worked on labels Dec 5, 2020
@stale
Copy link

stale bot commented Dec 12, 2020

Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!

@stale stale bot closed this as completed Dec 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Ask how to do something or how something works stale Did not receive any activity for 60 days
Projects
None yet
Development

No branches or pull requests

4 participants