Skip to main content

About the User Object

important

This is only applicable for our NodeJS SDK >= 16.0. For other versions, or SDKs, please see: https://github.com/supertokens/core-driver-interface/wiki

The user object structure is as follows:

type User = {
id: string;
timeJoined: number;
isPrimaryUser: boolean;
tenantIds: string[];
emails: string[];
phoneNumbers: string[];
thirdParty: {
id: string;
userId: string;
}[];
loginMethods: ({
recipeId: "emailpassword" | "thirdparty" | "passwordless";
tenantIds: string[];
timeJoined: number;
recipeUserId: RecipeUserId;
verified: boolean;
email?: string;
phoneNumber?: string;
thirdParty?: {
id: string;
userId: string;
};
hasSameEmailAs: (email: string | undefined) => boolean;
hasSamePhoneNumberAs: (phoneNumber: string | undefined) => boolean;
hasSameThirdPartyInfoAs: (thirdParty?: { id: string; userId: string }) => boolean;
})[];
};

class RecipeUserId {
private recipeUserId: string;
constructor(recipeUserId: string) {
this.recipeUserId = recipeUserId;
}

public getAsString = () => {
return this.recipeUserId;
};
}

Before we dive into the meaning of each of the fields, it is important to understand the concept of a primary and a recipe user ID.

Primary vs recipe user ID#

In SuperTokens, each user can have multiple login methods: for example, one user may be able to login with both, email password and social login. Each of these login methods, will give the user a unique user ID - this is known as a recipeUserId. We call it that, cause email passwors and social login are two different recipes in SuperTokens. Now of course, when that user uses either of the login methods, we must resolve it to the same user ID. This user ID, that is common across all login methods for a user, is known as the primary user ID. The value of the primary user ID is equal to the recipe user ID of the first login method.

Let's take an example. A user first signs up with the email password recipe. This gives them a recipe user ID or r1. Their primary user ID is also r1. Now, they sign in with Google with the same email. This will create a different recipe user ID r2. If you have enabled the automatic account linking, then the two recipe userIds will be linked, and r2's primary user will be r1. Therefore, we will have the following mapping:

r1 -> [r1, r2]

If you have not enabled automatic account linking, then you will have two distinct users:

r1 -> [r1]
r2 -> [r2]

Where the email password user is r1 and Google login user is r2.

User object fields explained#

  • id: This will be the primary user ID of the user (See the section above for an example). This value can change if the user is linked to another user.
  • timeJoined: This is the time (in MS since epoch), when the user first signed up. If a new login method is added for a user, this value is not updated.
  • isPrimaryUser: This is a boolean value, which is true if the user can accept other login methods from other users. For example, when we link two users, u1 and u2, such that post linking, the primary user ID is that of u1's, then u1 must have isPrimaryUser as true, and u2 must have isPrimaryUser as false. Read more about this boolean in the account linking section.
  • tenantIds: This is the list of tenantIds which this user belongs to. It's the union set of all the tenantIds of each of the login methods for this user.
  • emails: This list contains all the emails for this user.
  • phoneNumbers: This list contains all the phone numbers for this user.
  • thirdParty: This list contains the third party info belonging to this user.
    • id: This is a unique identifier for the third party provider. For example, for Google login, the value will be "google"
    • userId: This is the user ID of the user from the third party provider. For example, for Google login, this will be the user's Google user ID.
  • loginMethods: This is a list that represents all the different ways this user can login to your app. Each login method has the following fields:
    • recipeId: This is the ID representing the login method. For example, for email password, this will be "emailpassword".
    • tenantIds: This is the list of tenantIds for this login method.
    • timeJoined: This is the time (in MS since epoch), when the user signed up with this login method.
    • recipeUserId: This is the recipe user ID of this login method.
    • verified: This is a boolean value, which is true if the user has verified their email or phone number for this login method.
    • email: This is the email for this login method. This will be undefined if the login method does not contain an email.
    • phoneNumber: This is the phone number for this login method. This will be undefined if the login method is not "passwordless" and the user has not used their phone number to login.
    • thirdParty: This is the third party info for this login method. This will be undefined if the login method is not third party.
    • hasSameEmailAs: This is a helper function which takes an email as a parameter, and returns true if the email is the same as the email for this login method. It normalises the input email before comparing so that you get accurate results.
    • hasSamePhoneNumberAs: This is a function which takes a phone number as a parameter, and returns true if the phone number is the same as the phone number for this login method. It normalises the input phone number before comparing so that you get accurate results.
    • hasSameThirdPartyInfoAs: This is a function which takes a third party info as a parameter, and returns true if the third party info is the same as the third party info for this login method.

Examples#

Example 1: Email password user without account linking#

In a simple case, if we just have a user who signed up with email password (with test@example.com), and automatic account linking is not enabled, their user object would look like:

{
id: "3f23dca5-79da-4d84-9a72-90286ef6ea0d";
timeJoined: 1693286254150;
isPrimaryUser: false;
tenantIds: ["public"];
emails: ["test@example.com"];
phoneNumbers: [];
thirdParty: [];
loginMethods: [{
recipeId: "emailpassword";
tenantIds: ["public"];
timeJoined: 1693286254150;
recipeUserId: new RecipeUserId("3f23dca5-79da-4d84-9a72-90286ef6ea0d");
verified: false;
email: "test@example.com";
hasSameEmailAs: (email: string | undefined) => boolean;
hasSamePhoneNumberAs: (phoneNumber: string | undefined) => boolean;
hasSameThirdPartyInfoAs: (thirdParty?: { id: string; userId: string }) => boolean;
}];
};
  • Notice that the value of isPrimaryUser is false. This means that if this user is linked to another user, this user's primary user ID will change to the other user's primary user ID.
  • This user has just one login method (email password), since it's not linked to any other user.

Example 2: Email password user linked with a social login user#

We have a user who signed up with email password (with test@example.com), and then with Google (with the same email). Automatic account linking is enabled, therefore these two users get linked.

{
id: "3f23dca5-79da-4d84-9a72-90286ef6ea0d";
timeJoined: 1693286254150;
isPrimaryUser: true;
tenantIds: ["public"];
emails: ["test@example.com"];
phoneNumbers: [];
thirdParty: [{
id: "google";
userId: "1234567890";
}];
loginMethods: [{
recipeId: "emailpassword";
tenantIds: ["public"];
timeJoined: 1693286254150;
recipeUserId: new RecipeUserId("3f23dca5-79da-4d84-9a72-90286ef6ea0d");
verified: false;
email: "test@example.com";
hasSameEmailAs: (email: string | undefined) => boolean;
hasSamePhoneNumberAs: (phoneNumber: string | undefined) => boolean;
hasSameThirdPartyInfoAs: (thirdParty?: { id: string; userId: string }) => boolean;
}, {
recipeId: "thirdparty";
tenantIds: ["public"];
timeJoined: 1693286254250;
recipeUserId: new RecipeUserId("6ffc0ac5-d840-4a5b-92e8-86965f67c2ea");
verified: true;
email: "test@example.com";
thirdParty: {
id: "google";
userId: "1234567890";
};
hasSameEmailAs: (email: string | undefined) => boolean;
hasSamePhoneNumberAs: (phoneNumber: string | undefined) => boolean;
hasSameThirdPartyInfoAs: (thirdParty?: { id: string; userId: string }) => boolean;
}];
};
  • Notice that the value of isPrimaryUser is true. This means that if this user is linked to another user, this user's primary user ID will NOT change.
  • This user has just two login methods (email password and third party). The top level timeJoined value is the min of the two timeJoined values in the loginMethods.
  • In this example, the top level emails array just has one item since both the login methods emails as the same, but if they were different, there would be two items in this array.