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
Identitydomain can be accessed by various services (profile page, search, social features) without ever having visibility into hashing algorithms or password metadata. - The
Credentialsdomain 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
Identitylinked to multipleCredentials(Password, OAuth, Passkeys). - We can rotate security protocols in the
Credentialsdomain 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
typeis restricted to specificproviders(e.g.,PASSWORDis only allowed for theLOCALprovider). - Mandatory Secrets: Credentials of type
PASSWORD,API_KEY, orSERVICEmust include asecret. - Subject Requirement: OIDC-based credentials (
GOOGLE,GITHUB) must include asubject(typically the provider's unique user ID). - Mutually Exclusive Fields: If a
subjectis 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.
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
identitiesandcredentialstables.