Security

Authentication, credentials, token lifecycle, and session management — SecurityService, JWT token versioning, OAuth2, passkeys, and API tokens.

Overview

Bosca's security layer is built around Principals (user accounts) and Credentials (authentication methods). A single Principal can have multiple credentials — password, OAuth2, API tokens, and WebAuthn passkeys — all managed through the SecurityService.

Principal

The core identity record. Every authenticated user is a Principal.

kotlin
tokenVersion is central to session security — every JWT includes a tver claim that must match the Principal's current version, or the token is rejected.

Credential Types

Credentials are polymorphic — each type stores its data in a JSON attributes field on PrincipalCredential.

TypeStorageNotes
PASSWORDArgon2 hashPrimary login method
PASSWORD_SCRYPTScrypt hashLegacy support — migrated on next login
OAUTH2Provider tokenGoogle, Facebook, Apple
API_TOKENSHA-256 hashScoped tokens with group restrictions
PASSKEYWebAuthn public keyFIDO2 with sign-count anti-cloning

Authentication Flows

Password Login

graphql

Returns a short-lived JWT (token) and a long-lived refreshToken. The refresh token is single-use — exchanging it atomically deletes the old one and issues a new pair.

OAuth2 / Third-Party

Supports GOOGLE, FACEBOOK, and APPLE. The client obtains a provider token and exchanges it via the signupThirdParty or loginThirdParty mutations. Bosca validates the token with the provider and creates or links the credential.

Passkeys (WebAuthn)

FIDO2/WebAuthn passkeys for passwordless authentication. The server tracks the signCount to detect cloned authenticators.

API Tokens

Long-lived tokens for programmatic access. Each token has optional scopes and allowed groups to restrict what it can do. The raw token is shown once at creation; only the SHA-256 hash is stored.

Token Versioning

Every JWT includes a tver (token version) claim. The Principal's tokenVersion is a monotonic counter that increments on security-sensitive events:

  • Password change
  • Identifier (email) change
  • Credential deletion
  • Explicit logout (all sessions)

When tver in the JWT doesn't match the current tokenVersion, the token is rejected — effectively invalidating all outstanding sessions without maintaining a token blacklist.

Groups & Roles

Groups are the foundation of authorization. Three types exist:

GroupTypePurpose
SYSTEMBuilt-in roles (SA, admin, editor, manager)
PRINCIPALAuto-created per user ({principalId}.user), used for personal entity permissions
CUSTOMUser-defined groups for team/project access control
See the Permissions page for how groups interact with PermissionEvaluator to control entity access.

SecurityService

The central interface for all authentication and credential management:

kotlin

Email Verification

New accounts can optionally require email verification. A verificationToken is generated on signup and sent via email. The verify mutation validates the token and marks the Principal as verified.

Password Reset

The forgot-password flow generates a time-limited reset token sent via email. The resetPassword mutation validates the token, updates the password hash, and bumps tokenVersion to invalidate all existing sessions.