I’m seeing differences between the token sub value and user_id everywhere else in auth0 and curious why this is the case. What what I’ve read, I think they should generally be the same. The sub values are all valid UUIDs, while the user_ID values everywhere else are other format |
It’s causing issues for me because I’m saving off the ID when a user first logs in with post-login-actions. In other parts of the app, I then grab data from the user with the management API. For example, when I get role information on the user, the ID I have saved (pure UUID) does not match the ID in auth0 via management API (| format).
In any case, I’ve created a post-login-action to make a claim to user_id and that solves my issue. But curious why they aren’t the same and if there’s some setup or anything I’m missing. I’m just getting rolling with auth0, so there’s every chance I missed something!
How are you saving the user ID initially? I have tested on my end and all the values retrieved from the action and the sub provided after login appear to be the same (auth0|{user_id})
If you can provide a snipped of your action to take a look that would be great!
Hi Nik, thanks for reaching out! I’m using next-auth and saving it back on the authorization callback (it’s still pretty POC at this point…). I’m seeing in the session callback that user_id and sub are not equal. I added user_id in the post-login-actions.
import NextAuth, { User as NextAuthUser } from 'next-auth';
import Auth0 from 'next-auth/providers/auth0';
import { saveUserToDB } from '@/src/lib/data';
interface User extends NextAuthUser {
roles: string[];
user_id: string;
}
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Auth0({
clientId: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
issuer: process.env.AUTH0_ISSUER_BASE_URL,
authorization: {
params: {
scope: 'openid profile email',
},
},
})
],
callbacks: {
async jwt({ token, account }) {
if (account?.id_token) {
const decoded = JSON.parse(
Buffer.from(account.id_token.split(".")[1], "base64").toString()
);
token.roles = decoded["https://<my_app>.com/roles"] || [];
token.user_id = decoded["https://<my_app>.com/user_id"] || token.sub;
}
return token;
},
async session({ session, token }) {
(session.user as unknown as User).roles = token.roles as string[];
(session.user as unknown as User).user_id = typeof token.user_id === 'string' ? token.user_id : '';
session.user.id = token.sub ?? ''; // Attach Auth0 user ID to session
if (session.user) {
await saveUserToDB({
auth0_user_id: session.user.user_id ?? '',
email: session.user.email,
name: session.user.name ?? '',
});
}
return session;
},
},
})
As far as I have checked, everything looks good, I believe what is happening is that when you retrieve the user_id from the session you have established with Auth0, it uses the global identifier of their user_id which would be without the provider identifier: auth0|.
For example, if Actions, if you would try to test it out, inside the event parameters you would have the following:
You appear to be accessing this user_id. Alternatively, you could try to retrieve the provider and append the two values together. It is completely normal to have this discrepancy when decoding the token and checking the session of the user…
Just to confirm, the only difference you see in the sub value and user_id value is that the user_id is missing the provider ( auth0| ), and they are not completely different, right?
If you have any other questions or if the information above was helpful, please let me know!
I’m seeing the sub and user_ids are different, not just missing the prepended provider. For example, looking at the session object, it looks like this:
From what I have checked in your code, it appears that the session.user.user_id is set correctly and your session.user.id which is being set with token.sub appears to parse is what appears to be the ID of the session.
Usually, you would retrieve the user_id using Next-Auth like this:
As shown above in one of the code snippets, could you try switching session.user.id = token.sub to session.user.id = token.id?
Also, please try to console log the token that you are decoding to see what values are you setting from it and if possible, provide a snippet on the post.