-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication
Authentication runs on Better Auth, backed by
the project's own Prisma/PostgreSQL database. Configuration lives in
src/lib/auth/server.ts.
DataShield used Auth.js (next-auth v5) until the
better_authmigration.AUTH_SECRETandAUTH_URLwere replaced byBETTER_AUTH_SECRETandBETTER_AUTH_URL. See Configuration.
Each sign-in writes a row to the Session table rather than relying on a signed
cookie alone. Sessions can therefore be listed, revoked and audited server-side,
which is what makes Remediation able to cut an exposed employee's access.
| Method | Plugin | Notes |
|---|---|---|
| Email and password | built in | Passwords hashed with bcryptjs, set explicitly on emailAndPassword.password rather than the library default |
| TOTP two-factor | twoFactor |
Per-user enrollment, with backup codes and lockout after repeated failures |
| Email OTP | twoFactor |
Second factor delivered by email |
| Passkeys | @better-auth/passkey |
WebAuthn. A passkey sign-in is complete primary authentication, not a second factor |
| SSO (OIDC) | @better-auth/sso |
One provider per company, with domain verification |
A company chooses which second factors it accepts through
Company.allowedAuthMethods (AuthMethod[], default [TOTP]). See
PATCH /api/company/auth-policy in the API Reference.
Two company-level switches drive the policy, both on the Company model:
-
allowedAuthMethods: which ofTOTP,EMAIL_OTP,PASSKEYmay be used. -
ssoMandatory: when true, local sign-in is refused and members must come through the identity provider.
User.ssoExempt is the anti-lockout valve. An expired IdP certificate must not
lock a whole company out of its own security product, so an exempt user can
still sign in locally while ssoMandatory is on. The rule is one function,
deniesLocalSignIn in src/lib/sso/policy.ts.
The policy is enforced on the passkey path too. A passkey sign-in creates the
session itself, so without an explicit check a company that enabled
ssoMandatory to cut someone's access would still have let them in through the
passkey button.
src/lib/auth/two-factor-gate.ts decides whether a signed-in user is routed to
enrollment. It refuses to force enrollment on an account with no password,
because enabling TOTP requires confirming the current password: a
pre-provisioned SSO account has none, so forcing it would strand the user on a
form they cannot satisfy. For those accounts the identity provider owns the
second factor.
The SSO plugin exposes provider management to any authenticated session, which
would let a Viewer enroll an identity provider on their own company. DataShield
gates four plugin paths behind sso:config (src/lib/sso/policy.ts):
/sso/register
/sso/update-provider
/sso/request-domain-verification
/sso/verify-domain
Sign-in and the callback stay open by design, since they are the login path.
Provider records live in SsoProvider, one per company, with domain and
domainVerified. The OIDC client configuration is encrypted at rest through a
Prisma extension (src/lib/sso/encryption.ts), so it is sealed on write and
opened on read without the call sites having to think about it.
POST /api/sso/resolve runs before sign-in: the login page asks whether a typed
email's company has a verified provider, so it can send the user to the right
place. It is deliberately unauthenticated, since there is no session yet.
New users are invited rather than created with a password
(src/lib/auth/invitation.ts):
- The invitation token is single-use and expires after 72 hours
(
INVITATION_TTL_HOURS). - Only a hash of the token is stored, in
UserInvitation. - The invitee sets a password between 12 and 72 characters. The upper bound is not cosmetic: bcrypt truncates at 72 bytes.
An administrator can force a rotation with
POST /api/users/[id]/require-password-change, which sets
User.mustChangePassword. A user in that state is refused by the normal guard
everywhere except POST /api/account/password, which re-verifies the current
password before writing the new one.
src/middleware.ts protects every route except api/auth, static assets and
/login. Authorization beyond "is signed in" is permission-based and covered in
Roles and Permissions.
- Roles and Permissions for what a signed-in user is allowed to do
- Audit Log for what gets recorded
- Security for encryption, rate limiting and the CI gates
DataShield is source-available software by Melvin PETIT (WhiteMuush). Live demo, read only, no signup.
Getting started
Architecture
Features
- Breach Scanning
- Risk Scoring
- Directory Integrations
- MFA Coverage
- SCIM Provisioning
- Dashboard and Widgets
- Reports
- Exposure Register
Integrations
Identity and access
Reference
Contributing