12
  • I have a NextJS page where I try to implement Next-Auth.
  • I use credentials to login to my Rails API.
  • My API is returning (already) a JWT-Token. (so NextAuth must not create it)

How to implement the Provider.Credentials for [...nextauth].js in that case?

Flow "Diagram" Next request ---> Next API (with Next-Auth) ---> Rails API (returning Token)

At the momemt I have these options:

 providers: [
    CredentialsProvider({
      name: 'Email',
      credentials: {
        email: { label: "Email", type: "email", placeholder: "meine.email@domain.com" },
        password: {  label: "Passwort", type: "password" }
      },
      async authorize(credentials) {

        // The 'url' is pointing to a Rails API endpoint which returns a JWT Token
        const url = `${process.env.NEXT_PUBLIC_API_URL}/auth/login`;

        const res = await fetch(url, {
          method: 'POST',
          body: JSON.stringify(credentials),
          headers: {
            "Content-Type": "application/json" }
        })
        const user = await res.json()

        // If no error and we have user data, return it
        if (res.ok && user) {
          // I SAW EXAMPLES RETURNING {"email": "blah@tst.com"}
          return user // MY CONTENT {token: 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo0LCJyb2xl…0.OAGiwjj9O_NsH02lIjA2D4HYZkmTQ3_SqtKcVgaIul0'}

        }
        // Return null if user data could not be retrieved
        return null
      }
    })
  ]
}

A session_token is set in the browser, but that content is something (random?) what I dont have set. Where does this content come from if not from my token?

My Rails API Token Content:

{
  "user_id": 4,
  "roles": [
    "user"
  ],
  "exp": 1631096219
}

Next-Auth API Token Content:

{
  "iat": 1631009819,
  "exp": 1633601819
}

Do I have to decode my API token and reassamble that within the Provider.Credentials function?

I implement Next-Auth to provide more Authentications like Twitter and Co, but as well to make use of "useSession" instead of building everything of my own (Wont reinventing the wheel).

jps
  • 20,041
  • 15
  • 75
  • 79
Jan
  • 12,992
  • 9
  • 53
  • 89
  • 1
    Did you find a solution for this eventually? I too am working with an external api. I want to sync the expiry time of the tokens. – ghosh May 17 '22 at 20:31

2 Answers2

11

Add Callbacks.

    export default NextAuth({
      providers: [
        CredentialsProvider({
          name: "Email",
          credentials: {
            email: {
              label: "Email",
              type: "email",
              placeholder: "meine.email@domain.com",
            },
            password: { label: "Passwort", type: "password" },
          },
          async authorize(credentials) {
            // The 'url' is pointing to a Rails API endpoint which returns a JWT Token
            const url = `${process.env.NEXT_PUBLIC_API_URL}/auth/login`;
    
            const res = await fetch(url, {
              method: "POST",
              body: JSON.stringify(credentials),
              headers: {
                "Content-Type": "application/json",
              },
            });
            const user = await res.json();
    
            // If no error and we have user data, return it
            if (res.ok && user) {
              // I SAW EXAMPLES RETURNING {"email": "blah@tst.com"}
              return user; // MY CONTENT {token: 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo0LCJyb2xl…0.OAGiwjj9O_NsH02lIjA2D4HYZkmTQ3_SqtKcVgaIul0'}
            }
            // Return null if user data could not be retrieved
            return null;
          },
        }),
      ],
    
      callbacks: {
        async jwt({ token, user, account, isNewUser }) {// This user return by provider {} as you mentioned above MY CONTENT {token:}
          if (user) {
            if (user.token) {
              token = { accessToken: user.token };
            }
          }
          return token;
        },
    
        // That token store in session
        async session({ session, token }) { // this token return above jwt()
          session.accessToken = token.accessToken;
          //if you want to add user details info
          session.user = { name: "name", email: "email" };//this user info get via API call or decode token. Anything you want you can add
          return session;
        },
      },
    });
Jan
  • 12,992
  • 9
  • 53
  • 89
  • 5
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 11 '21 at 19:50
  • How can I read the cookie to use the JWT in further api calls? – user3174311 Nov 12 '21 at 14:30
  • @user3174311 You can access session import { useSession } from 'next-auth/react'; const {status, data}= useSession(); – shafiul islam Nov 20 '21 at 16:30
  • @shafiulislam is it safe to save your JWT access token inside session? – mac125 Mar 12 '23 at 13:49
0

So the user that you return from the credentials authorize function will get stored in the JWT (JSON Web Token - which is passed around with all authenticated requests) which is a hashed/encoded (not encrypted by default!) version of the object.

You can use https://jwt.io to debug and see whats in your JWT. You paste into that site's debugger field your eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo0LCJyb2xl... value and it'll show you the { iat: 49835898: sub: 47897: email: 'abc@xyz.com' }, etc. value.

jwt.io example

If your rails API is returning a JWT to you in that fetch call in the authorize function, you can use a library like jwt-decode to decode it right there, and append any values from it which you would like to "persist" in your application to the user object you're returning from the authorize function in next-auth.

ndom91
  • 719
  • 1
  • 9
  • 19
  • How is the other way around? could/should requests against the API (to fetch data) call the API with the old (origin) token or with the NextAuth generated JWT-token? The NextAuth one would not be accepted by the API-Server, right? – Jan Sep 19 '21 at 00:24
  • Yeah so it depends on what you mean by API exactly. Are these API routes from next.js? Then the next-auth original jwt. Is it an API from your rails application? Then the rails jwt. Now I'm no oauth expert, but there doesn't seem to be any further identifying information in the rails jwt other than your userId. So I'd be curious if a custom JWT you create out of a combination of next-auth info and rails jwt info would work for both? – ndom91 Sep 19 '21 at 14:38