# Differences Between sub and user\_id

**URL:** <https://community.auth0.com/t/differences-between-sub-and-user-id/180773>\
**Category:** Get Help\
**Tags:** sessions, access-token\
**Created:** [February 3, 2025, 8:15pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773 "2025-02-03T20:15:36Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![charlie.hammond3](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/charlie.hammond3/32/63850_2.png) [@charlie.hammond3](https://community.auth0.com/u/charlie.hammond3)\
**Post date:** [February 3, 2025, 8:15pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/1 "2025-02-03T20:15:36Z")

</div>

Hello,

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!

---

<div class="post-metadata">

**Author:** ![nik.baleca](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/nik.baleca/32/68749_2.png) [@nik.baleca](https://community.auth0.com/u/nik.baleca)\
**Post date:** [February 3, 2025, 8:36pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/3 "2025-02-03T20:36:31Z")

</div>

Hi @charlie.hammond3

Welcome to the Auth0 Community!

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!

Kind Regards,  
Nik

---

<div class="post-metadata">

**Author:** ![charlie.hammond3](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/charlie.hammond3/32/63850_2.png) [@charlie.hammond3](https://community.auth0.com/u/charlie.hammond3)\
**Post date:** [February 4, 2025, 12:49am UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/4 "2025-02-04T00:49:49Z")

</div>

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.

```auto
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;
    },
  },
})

```

---

<div class="post-metadata">

**Author:** ![nik.baleca](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/nik.baleca/32/68749_2.png) [@nik.baleca](https://community.auth0.com/u/nik.baleca)\
**Post date:** [February 4, 2025, 6:03pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/5 "2025-02-04T18:03:18Z")

</div>

Hi @charlie.hammond3

Thank you for sharing the implementation.

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:

```auto
"identities": [
      {
        "connection": "Username-Password-Authentication",
        "isSocial": false,
        "provider": "auth0",
        "userId": "5f7c8ec7c33c6c004bbafe82",
        "accessToken": "{random_access_token}",
        "profileData": {},
        "user_id": "5f7c8ec7c33c6c004bbafe82"
      }

```

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!

Kind Regards,  
Nik

---

<div class="post-metadata">

**Author:** ![charlie.hammond3](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/charlie.hammond3/32/63850_2.png) [@charlie.hammond3](https://community.auth0.com/u/charlie.hammond3)\
**Post date:** [February 4, 2025, 6:49pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/6 "2025-02-04T18:49:47Z")

</div>

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:

```auto
session {
  user: {
    name: '<name>',
    email: '<email>',
    image: 'https://lh3.googleusercontent.com/a/<id>',
    roles: [<role ids>],
    user_id: 'google-oauth2|1163208141182<8 numeric digits>',
    id: '4046a84f-9c4a-490f-8b02-<remainder of UUID>'
  },
  expires: '2025-03-06T18:43:17.373Z'
}

```

```auto
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
      console.log('session', session);
      if (session.user) {
        await saveUserToDB({
          auth0_user_id: session.user.user_id ?? '',
          email: session.user.email,
          name: session.user.name ?? '',
        });
      }
      return session;

```

---

<div class="post-metadata">

**Author:** ![nik.baleca](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/nik.baleca/32/68749_2.png) [@nik.baleca](https://community.auth0.com/u/nik.baleca)\
**Post date:** [February 4, 2025, 7:56pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/7 "2025-02-04T19:56:38Z")

</div>

Hi again @charlie.hammond3

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:

```auto
callbacks: {
  jwt({ token, account, user }) {
    if (account) {
      token.accessToken = account.access_token
      token.id = user?.id
    }
    return token
  }
  session({ session, token }) {

      session.user.id = token.id;

      return session;
    },
}

```

or

```auto
export default NextAuth({
  ...
  callbacks: {
    session: async ({ session, token }) => {
      if (session?.user) {
        session.user.id = token.sub;
      }
      return session;
    },
    jwt: async ({ user, token }) => {
      if (user) {
        token.uid = user.id;
      }
      return token;
    },
  },
  session: {
    strategy: 'jwt',
  },
  ...
});

```

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.

Let me know if that changes the outcome.

Kind Regards,  
Nik

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/auth0/original/3X/b/5/b560f266932fcce5d57f09a6595bd50518cae3f3.jpeg) [@system](https://community.auth0.com/u/system)\
**Post date:** [February 18, 2025, 7:57pm UTC](https://community.auth0.com/t/differences-between-sub-and-user-id/180773/8 "2025-02-18T19:57:04Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
