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

feat: Forward idToken to callbacks #837

Closed
wants to merge 4 commits into from
Closed

feat: Forward idToken to callbacks #837

wants to merge 4 commits into from

Conversation

balazsorban44
Copy link
Member

@balazsorban44 balazsorban44 commented Nov 7, 2020

This is a bare minimum change required so an OpenID Connect compliant Identity Provider, (like IdentityServer4) can initiate a logout process from the IdP from within an app using next-auth, and return to the application afterwards.

According to the spec, an id_token must be present as either a query param (in case of GET) or as a body in case of POST to https://IdP.com/connect/endsession to be able to redirect back to the application (or anywhere else explicitely allowed so in the IdP client by post_logout_redirect_uri) after a successful logout.

This change forwards the id_token as-is to callbacks.signIn and callbacks.jwt initially, and leaves it up to the user to store that as they want to (probably either in a session database or in the JWT token).

There may be other situations where access to the id_token in that manner might be useful.

Related issues: #836, closes #393, closes #378

UPDATE:

I decided that in case an id_token is present, it should always be sent to the callbacks, regardless of idToken: true is set, or not.

The reasoning is that I thought that by setting idToken: true, I could skip an extra request to the /userinfo IdP endpoint. The problem is, that if I use id_token, all the claims must be sent from the IdP, making the id_token too big to send it again while using the /connect/endsession endpoint, destroying the purpose of this PR.

So here is a rough breakdown of how this PR solves my problem.

  1. Create an /api endpoint in Next.js, call it /api/auth/federated-logout
import sessionsDB from "lib/session-db" // an in-memory session database
import jwt from "next-auth/jwt"
import log from "utils/server-logger"

export default async function federatedLogout (req, res){
  const token = await jwt.getToken({req, secret: process.env.SECRET, encryption: true})

  if (token) {
    const { userId, sessionId } = token
    const userSession = await sessionsDB.getUserSession(userId, sessionId)
    const endsessionURL = `https://identity-provider.com/connect/endsession`
    const endsessionParams = new URLSearchParams({
      id_token_hint: userSession?.rawIdToken, // since it is an in-memory DB, a server restart would make the redirect not possible. 😢 If needed though, the DB can be moved out of memory. I tried to keep it simple.
      post_logout_redirect_uri: `http://localhost:3000?forceLogout=true`,
    })
    res.redirect(`${endsessionURL}?${endsessionParams}`)
    return
  }
  res.redirect("http://localhost:3000?forceLogout=true")
}
  1. With the provided id_token_hint to /connect/endsession will be able log the user out without consent, and redirect back to http://localhost:3000?forceLogout=true

  2. In _app add the following:

  import { signOut } from "next-auth/client"

  //...
  const router = useRouter()
  React.useEffect(() => {
    if (router.query.forceLogout) {
      signOut({ callbackUrl: "http://localhost:3000" }) // get rid of the `forceLogout=true` param
    }
  }, [router.query.forceLogout])
  1. Step 3. makes sure that after the user is logged out of the IdP, the app also drops the now invalid session.
  2. When a user want to initiate a federated logout, we just add a <a href="/api/auth/federated-logout">Log out everywhere</a> link somewhere in the app.

@vercel
Copy link

vercel bot commented Nov 7, 2020

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/nextauthjs/next-auth/q93uvnpwq
✅ Preview: https://next-auth-git-fork-nhi-feature-forward-id-token.nextauthjs.vercel.app

@vercel vercel bot temporarily deployed to Preview November 7, 2020 10:39 Inactive
@vercel vercel bot temporarily deployed to Preview November 7, 2020 14:47 Inactive
@balazsorban44 balazsorban44 changed the base branch from main to canary December 5, 2020 16:10
@balazsorban44 balazsorban44 added the enhancement New feature or request label Dec 5, 2020
@vercel vercel bot temporarily deployed to Preview December 5, 2020 16:28 Inactive
@balazsorban44
Copy link
Member Author

@@ -25,7 +25,7 @@ You can specify a handler for any of the callbacks below.
session: async (session, user) => {
return Promise.resolve(session)
},
jwt: async (token, user, account, profile, isNewUser) => {
jwt: async (token, user, account, profile, isNewUser, idToken) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iaincollins This (and probably any other public-facing function signature using more than 2 params) should at some point (maybe v4) become an object to leverage named parameters It is much easier for the user to pick only those params that they are going to use.

@balazsorban44 balazsorban44 changed the title Forward idToken to callbacks feat: Forward idToken to callbacks Dec 6, 2020
@ryangittings
Copy link

Can we get this merged? Happy to help if I can but desperate to use this on a project.

Cheers! :)

@vercel vercel bot temporarily deployed to Preview December 30, 2020 16:44 Inactive
@balazsorban44
Copy link
Member Author

@ryangittings hope to get this merged soon. As it's a user facing change, I would like to review it with someone else from the core team before merge. (will have a chat with @iaincollins tomorrow, so hopefully then 🤞)

@balazsorban44
Copy link
Member Author

Continued at #1024

@github-actions
Copy link

github-actions bot commented Jan 1, 2021

🎉 This issue has been resolved in version 3.2.0-canary.10 🎉

The release is available on:

Your semantic-release bot 📦🚀

@balazsorban44 balazsorban44 deleted the feature/forward-id-token branch January 1, 2021 20:52
@github-actions
Copy link

github-actions bot commented Feb 1, 2021

🎉 This issue has been resolved in version 3.3.0-canary.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
2 participants