DEV Community

Peter Jacxsens
Peter Jacxsens

Posted on • Updated on

21/ NextAuth + Strapi: Final pieces and conclusion

There are some issues that we left unhandled, let's quickly go over them.

Automatically signing in on reset password in NextAuth

In our auth flow, we added the forgot/reset password option for credentials. But, as our flow stands now, we prompt the user to sign in after resetting the password. This is acceptable but not ideal.

A successful password reset in Strapi actually returns the user object + a Strapi token. In other words, everything we need to sign the user in automatically. I delayed talking talking about this because we didn't have all the necessary pieces just yet! But we do now.

We can now use what we learned in the change username and change password functionality and apply it to reset password. That is, stop using useFormState. Call our server action in a submitHandler function, await the response from this server action and on success call the useSession.update function. What would we pass it? Everything you need to update the token.

Note: I didn't actually try this out so you may run into some problems. But, I'm pretty sure it can be done.

Automatically signing in on email confirmation in NextAuth

When first signing up, the user receives an email confirmation request. Upon clicking the confirmation link the user gets a success message and is asked to sign in. Can we do this automatically?

Maybe, but we would have to seriously rework our component. First on the actual first sign up we would have to integrate NextAuth. Our Strapi endpoint for signing up returns (on success) the user object but no token. So, we would have to put this user into the NextAuth token. I think you can listen for the trigger 'signup' inside the jwt callback for this.

It would also be necessary to use a second CredentialsProvider for sign up and give it a unique ID. You can then call the signIn function with this ID, f.e.

// not
signIn('credentials', ...)
// use ID
signIn('signin', ...)
signIn('signup', ...)
Enter fullscreen mode Exit fullscreen mode

Inside this second CredentialsProvider (with id signup), you can then write an authorize function that calls the Strapi signup endpoint + handle errors and everything else that needs to be done.

The issue now is how to get the Strapi token. On email confirmation, the Strapi endpoint will not return the token but redirect the user. Also, we don't have a password to sign in with. (DO NOT send the password along any requests!)

And that is where I run aground. Maybe it can be done but I don't know how because I can't get to the Strapi token.

Also note that you would have to update your guarded components. No longer only checking if(session) but also something like && session.user.authorized.

Tokens and expiry in Strapi and NextAuth

We used a lot of tokens in our auth flow: Strapi sign in token, request reset token, reset password token, NextAuth token,... All of these tokens have expiry dates. This means that they are only valid within a certain period. I'm pretty sure the expiry date is encoded inside the token.

On top of that, tokens also can be invalidated but not expired. A good example of this is the password reset token. Once you've used it to reset a password, Strapi will invalidate it. This token will then be invalid even though the expiry date may not have been reached yet.

Note, I don't know how this works yet. I'm yet to study it. I only know bits and pieces but I do know it's a problem we have to deal with.

When our NextAuth token expires, the user will simply be signed out and will have to sign in again. No problems there. There are ways to automate this with f.e. GoogleProvider. On sign in, we leverage some NextAuth callbacks to request a new NextAuth token ... somehow. Not sure how but it is possible.

A more immediate problem is when our NextAuth token is still valid or hasn't expired but the Strapi token has. This would lead to a cascade of problems and very confusing error message. The user would still be logged in, yet Strapi would throw errors like 'invalid credentials' or something. That is a problem and I don't know how to solve this yet.

We already came across another problem. Upon changing our password, Strapi returned us a new Strapi token. We then updated the NextAuth token via the useSession.update method. But, what happened to the old token? Spoilers, it is still valid. This means that it could be used to access our app. So, again, something we would have to manage.

Strapi also has a block user option. You would have to look into this to find out what this means for the token.

That is pretty much all I know about this for the moment. Takeaway: handle token expiry.

Final conclusion

We setup a complete auth using credentials and GoogleProvider in Next and Strapi using NextAuth. Contrary to some articles in the wild, this wasn't easy and it wasn't quick - if done right.

On top of that, we took some shortcuts. We avoided some problems by simplifying our app or choosing a basic auth flow. Building a production level auth flow will complicate things. Meeting design specs will complicate things even more.

There will be things you can't do. Partly due to NextAuth's insufficient server code support but also just hard restrictions. Things NextAuth just can't do.

That being said, we did do a lot. We do having a fully functioning auth flow. One I hope I was able to explain clearly. It's important to get a feel for how NextAuth works. Feel the flow. Especially inside the callbacks. Besides this I tried to guide you through countless problems and how I managed to solve them. In the end this took up a lot of our time and I hope you learned from it.

Don't be shy to critique this. If you catch a mistake or a better solution, feel free to let me know in the comments.

Anymore on the way? As mentioned above, I still need to figure out how to handle token. Besides this I may do this series over with NextAuth v5 once it comes out of beta. Not making any promises.

Hope you enjoyed this series. Comment and share if you liked it.

If you want to support my writing, you can donate with paypal.

Top comments (6)

romkagw profile image
romka_gw • Edited

Hi, very cool article, it's a pity that there is no information on how to get around the error if you create several providers for example (google and github) and log in first through one service and then when you try to log in through another and if the email is the same, there will be an error, and it's still hard for me to think of what to do in this case, how best to handle such a login without displaying an error and so that it does not crash. Perhaps you will be interested and you could help me in this).

peterlidee profile image
Peter Jacxsens

It depends on your setup. In the case of this article, the error would be thrown by Strapi. So, you would have to get the error from Strapi to NextAuth. That means you have to use one of the callbacks. I haven't actually looked into this specific problem. I would suggest to try it out and see what happens.

romkagw profile image

@peterlidee let's try, I am very interested in how you can handle this case, especially it would be cool to realize the possibility of authorization from different providers but the same email address.

gregfanyan profile image

super cool

psheon profile image

Thank you so much Peter 🥰🥰

peterlidee profile image
Peter Jacxsens

Glad you liked it! At least somebody read it.