Skip to main content

Overview

Email/password authentication is a traditional authentication method that allows users to sign up and sign in using their email address and password. SuperTokens Core implements secure password hashing using BCrypt or Argon2 algorithms and provides comprehensive password reset flows.

Sign Up

Create a new user account with email and password.

Implementation

The sign-up process is implemented in io.supertokens.emailpassword.EmailPassword.signUp() - View source Key Features:
  • Email normalization and validation
  • Secure password hashing (BCrypt or Argon2)
  • Automatic duplicate email detection
  • Support for fake emails (auto-verified)
  • Multi-tenancy support

Password Hashing

Passwords are hashed using one of two algorithms: BCrypt:
String passwordHash = BCrypt.hashpw(password, BCrypt.gensalt(bcryptLogRounds));
Argon2:
String passwordHash = argon2id.hash(
    iterations,
    memoryKb,
    parallelism,
    password.toCharArray()
);
Configuration is done via:
  • password_hashing_alg: Choose between BCRYPT or ARGON2
  • bcrypt_log_rounds: BCrypt cost factor (default: 11)
  • argon2_iterations: Number of iterations for Argon2 (default: 1)
  • argon2_memory_kb: Memory cost in KB (default: 87795)
  • argon2_parallelism: Parallelism factor (default: 2)

API Endpoint

POST /recipe/signup Request Body:
{
  "email": "[email protected]",
  "password": "securePassword123"
}
Response:
{
  "status": "OK",
  "user": {
    "id": "user-id",
    "email": "[email protected]",
    "timeJoined": 1234567890
  }
}

Sign In

Authenticate an existing user with email and password.

Implementation

The sign-in process is implemented in io.supertokens.emailpassword.EmailPassword.signIn() - View source Process:
  1. Retrieve user by email
  2. Verify password against stored hash
  3. Support for multiple password hashing formats (BCrypt, Argon2, Firebase SCrypt)
  4. Return user information on success

Password Verification

The system supports multiple password hash formats:
  • BCrypt: Identified by $2a$, $2b$, or $2y$ prefix
  • Argon2: Identified by $argon2id$, $argon2i$, or $argon2d$ prefix
  • Firebase SCrypt: For imported users from Firebase

API Endpoint

POST /recipe/signin Request Body:
{
  "email": "[email protected]",
  "password": "securePassword123"
}
Response:
{
  "status": "OK",
  "user": {
    "id": "user-id",
    "email": "[email protected]",
    "timeJoined": 1234567890
  }
}
Error Response:
{
  "status": "WRONG_CREDENTIALS_ERROR"
}

Password Reset

Secure password reset flow using time-limited tokens.

Generate Password Reset Token

Implementation: io.supertokens.emailpassword.EmailPassword.generatePasswordResetToken() - View source Token Generation Process:
  1. Generate 64 bytes of random data
  2. Generate 64 bytes of salt
  3. Apply PBKDF2 with 1000 iterations
  4. Convert to Base64 URL-safe format
  5. Hash with SHA-256 for storage
  6. Store with expiry time (default: 1 hour)
API Endpoint: POST /recipe/user/password/reset/token Request Body:
{
  "userId": "user-id",
  "email": "[email protected]"
}
Response:
{
  "status": "OK",
  "token": "generated-reset-token"
}

Consume Password Reset Token

Implementation: io.supertokens.emailpassword.EmailPassword.consumeResetPasswordToken() - View source Validation Process:
  1. Hash the provided token with SHA-256
  2. Look up token in database
  3. Verify token hasn’t expired
  4. Delete all tokens for the user
  5. Return user ID and email
API Endpoint: POST /recipe/user/password/reset/token/consume Request Body:
{
  "method": "token",
  "token": "reset-token"
}
Response:
{
  "status": "OK",
  "userId": "user-id",
  "email": "[email protected]"
}

Reset Password

Implementation: io.supertokens.emailpassword.EmailPassword.resetPassword() - View source API Endpoint: POST /recipe/user/password/reset Request Body:
{
  "method": "token",
  "token": "reset-token",
  "newPassword": "newSecurePassword123"
}

Update User

Update user email or password.

Implementation

Implementation: io.supertokens.emailpassword.EmailPassword.updateUsersEmailOrPassword() - View source Features:
  • Update email with duplicate check
  • Update password with re-hashing
  • Account linking validation
  • Transaction-based updates
API Endpoint: PUT /recipe/user Request Body:
{
  "userId": "user-id",
  "email": "[email protected]",
  "password": "newPassword123"
}

Import Users

Import users from other systems with existing password hashes.

Supported Hash Formats

  1. BCrypt: Standard BCrypt hashes
  2. Argon2: Argon2id, Argon2i, Argon2d variants
  3. Firebase SCrypt: Custom Firebase password hashing

Implementation

Implementation: io.supertokens.emailpassword.EmailPassword.importUserWithPasswordHash() - View source API Endpoint: POST /recipe/user/import Request Body:
{
  "email": "[email protected]",
  "passwordHash": "$2a$11$...",
  "hashingAlgorithm": "BCRYPT"
}

Configuration

Password Hashing Settings

# Choose hashing algorithm
password_hashing_alg: ARGON2  # or BCRYPT

# BCrypt settings
bcrypt_log_rounds: 11

# Argon2 settings
argon2_iterations: 1
argon2_memory_kb: 87795
argon2_parallelism: 2
argon2_hashing_pool_size: 1

# Firebase SCrypt (for imports)
firebase_password_hashing_signer_key: "base64-encoded-key"
firebase_password_hashing_pool_size: 1

Password Reset Settings

# Token lifetime in milliseconds
password_reset_token_lifetime: 3600000  # 1 hour

Security Features

Password Storage

  • Never stored in plaintext: All passwords are hashed before storage
  • Salt included: BCrypt and Argon2 automatically include unique salts
  • Configurable cost: Adjust hashing parameters based on security requirements

Concurrency Control

  • Bounded queues: Argon2 and Firebase SCrypt use bounded queues to prevent resource exhaustion
  • Thread-safe: All hashing operations are thread-safe

Email Normalization

All emails are normalized:
  • Converted to lowercase
  • Whitespace trimmed
  • Validation performed

Error Handling

Common Exceptions

  • DuplicateEmailException: Email already exists
  • WrongCredentialsException: Invalid email/password combination
  • ResetPasswordInvalidTokenException: Token expired or invalid
  • UnknownUserIdException: User not found
  • EmailChangeNotAllowedException: Email change conflicts with account linking
  • UnsupportedPasswordHashingFormatException: Invalid password hash format

Best Practices

  1. Use Argon2: More secure than BCrypt for modern applications
  2. Enforce password policies: Minimum length, complexity requirements
  3. Rate limiting: Implement rate limiting on sign-in attempts
  4. Email verification: Verify email addresses after signup
  5. HTTPS only: Always use HTTPS for authentication endpoints
  6. Token expiry: Keep password reset token lifetime short (e.g., 1 hour)
  7. Multi-factor authentication: Consider adding MFA for enhanced security

Multi-Tenancy Support

All email/password operations support multi-tenancy:
  • Users are isolated by tenant
  • Each tenant can have different password hashing configurations
  • Email uniqueness enforced per tenant
  • Account linking respects tenant boundaries

Build docs developers (and LLMs) love