Skip to content
vv1.14.0
Main

Identity vs Credentials Architecture

This document explains the architectural decision to separate Identity (who the user is) from Credentials (how the user proves who they are).

Overview

In many systems, user data and passwords live in the same table. In this boilerplate, we've decoupled these concerns into two distinct domains to improve security, scalability, and modularity.

Why separate them?

1. Security (Principle of Least Privilege)

By separating credentials, we can enforce stricter access controls. For example:

  • The Identity domain can be accessed by various services (profile page, search, social features) without ever having visibility into hashing algorithms or password metadata.
  • The Credentials domain can be isolated in a more secure database schema or even a different microservice.

2. Flexibility

Different authentication methods can be added without modifying the Identity entity:

  • A user can have one Identity linked to multiple Credentials (Password, OAuth, Passkeys).
  • We can rotate security protocols in the Credentials domain without affecting social features.

3. Modular Testing

Separating these domains allows for cleaner unit tests. We can test identity profile updates independently of password hashing logic and vice versa.

Validation Rules

To maintain high security and data integrity, the Credentials domain enforces strict validation rules via standardized pipes:

  • Type Compatibility: Each credential type is restricted to specific providers (e.g., PASSWORD is only allowed for the LOCAL provider).
  • Mandatory Secrets: Credentials of type PASSWORD, API_KEY, or SERVICE must include a secret.
  • Subject Requirement: OIDC-based credentials (GOOGLE, GITHUB) must include a subject (typically the provider's unique user ID).
  • Mutually Exclusive Fields: If a subject is required, it must be provided; if not required, it must be omitted to avoid data pollution.

How it works

When a user logs in, the system verifies the Credentials first. Once validated, it retrieves the associated Identity to populate the session/token.

LoginVerifyRetrieveJWT Token

Infrastructure Support

To ensure these domains remain decoupled but efficient, we use:

  • Shared Pipes: Standardized cryptographic utilities in src/infrastructure/pipes.
  • Cross-Domain Builders: Test builders that can link entities together consistently.
  • Relational Mapping: Drizzle-ORM relationships that maintain referential integrity between the identities and credentials tables.