Skip to main content

Auth Methods

Kyqu supports multiple authentication methods that can be enabled/disabled per project.

Available Methods

MethodStatusDescription
Email/Password✅ DoneStandard email + password authentication
Email Verification✅ DoneRequire email confirmation before granting access
Password Reset✅ DoneReset forgotten passwords via email
Magic Link✅ DonePasswordless sign-in via emailed link
TOTP 2FA✅ DoneTime-based one-time passwords with authenticator apps
Passkeys (WebAuthn)✅ DoneFIDO2 WebAuthn with platform authenticators
Social Login (OAuth)✅ DoneSign in with Google, GitHub
OIDC / ID Tokens✅ DoneOpenID Connect Discovery and RS256 ID tokens
SMS📋 PlannedSMS-based verification codes
SSO📋 PlannedSAML/OIDC single sign-on as relying party

Email/Password

Default auth method. Users sign up with email and password:

const { user, session } = await kyqu.signup({
email: "user@example.com",
password: "correct-horse-battery-staple"
});

Password requirements:

  • Minimum length configurable per project (default: 10 characters)
  • scrypt hashed (not stored in plaintext)
  • Compared using constant-time timingSafeEqual

Email Verification

When enabled, signup creates a user account without a session. The user must verify their email before logging in:

// Signup — no session returned
const { user, session: null, verificationRequired: true } = await kyqu.signup({...});

// Verification email is sent automatically
// User clicks link in email → email verified

// Now they can log in
const { user, session } = await kyqu.login({...});

Verification flow:

  1. User signs up → verification email sent
  2. User clicks link → browser hits GET /verify-email/confirm?token=...
  3. If email_verified_url configured → redirect to project's UI
  4. If no redirect URL → JSON response with user data

Password Reset

Users can reset forgotten passwords via email:

// Request reset
await kyqu.requestPasswordReset("user@example.com");

// Email received → user clicks link
// Link points to GET /password-reset/confirm?token=...

// If password_reset_url configured → redirect with token as query param
// Project's UI collects new password and POSTs to confirm
const { user, session } = await kyqu.confirmPasswordReset({
token: "token-from-email",
password: "new-password-42"
});

Passwordless sign-in via email:

// Request magic link
await kyqu.requestMagicLink("user@example.com");

// Email received → user clicks link
// GET /magic-link/confirm?token=...
// If login_url configured → redirect with session token
// Session token is in query param: ?token={raw-session-token}

TOTP 2FA

Time-based one-time passwords using authenticator apps (Google Authenticator, Authy, 1Password, etc.):

// Step 1: Start enrollment (user must be logged in)
const { enrollmentUrl } = await kyqu.enrollTotp(sessionToken);
// enrollmentUrl: "otpauth://totp/..."

// Render enrollmentUrl as QR code for the user to scan

// Step 2: Confirm enrollment
const { backupCodes } = await kyqu.confirmTotp(sessionToken, "123456");
// Returns 8 one-time backup codes — show immediately

// Step 3: Login with TOTP
const { user, session } = await kyqu.login({
email: "user@example.com",
password: "correct-horse-battery-staple",
totpCode: "123456" // or backupCode: "abcd-efgh-ijkl-mnop"
});

TOTP Implementation Details:

  • RFC 6238 compliant
  • HMAC-SHA1, 30-second window
  • ±1 window tolerance (90-second grace period)
  • 20-byte Base32-encoded secrets
  • Backup codes: 8 codes, XXXX-XXXX-XXXX format, hashed in database

Backup Codes

When TOTP is enabled, the user receives 8 one-time backup codes. Each code can be used once for login when the authenticator app is unavailable.

Passkeys (WebAuthn)

Passkeys allow users to authenticate with platform biometrics (Touch ID, Face ID, Windows Hello) or cross-device credentials.

How it works:

Kyqu handles the server side of the WebAuthn ceremony. The client SDK exposes methods that pair with navigator.credentials.create() and navigator.credentials.get():

Registration

// Step 1: Get registration options from server
const options = await kyqu.getPasskeyRegistrationOptions(token);

// Step 2: Create credential via browser WebAuthn API
const credential = await navigator.credentials.create({
publicKey: options
});

// Step 3: Verify and store the credential
await kyqu.registerPasskey(token, credential, "My MacBook Pro");

Authentication

// Step 1: Get authentication options
const options = await kyqu.getPasskeyAuthenticationOptions();

// Step 2: Get assertion from browser
const assertion = await navigator.credentials.get({
publicKey: options
});

// Step 3: Verify and receive session
const { user, session } = await kyqu.authenticateWithPasskey(assertion);

Credential Management

// List registered passkeys
const { passkeys } = await kyqu.listPasskeys(token);

// Delete a passkey
await kyqu.deletePasskey(token, credentialId);

Implementation details:

  • FIDO2 WebAuthn Level 2 compliant
  • Supported platform authenticators: macOS Touch ID, Windows Hello, Android biometric, iOS Face ID/Touch ID
  • Cross-device authentication via QR code (hybrid transport)
  • Credentials stored as CBOR-encoded public keys with credential ID
  • Challenge generated per ceremony with TTL and one-time use

Social Login (OAuth)

Kyqu supports OAuth 2.0 social login via Google and GitHub identity providers.

Setup

Configure OAuth providers in the admin dashboard per project:

  1. Register your app with the provider (Google Cloud Console / GitHub OAuth Apps)
  2. Set the redirect URI to: https://auth.example.com/api/projects/{projectId}/auth/oauth/{provider}/callback
  3. Enter client ID and client secret in Kyqu admin dashboard

Authentication Flow

// Step 1: Redirect user to provider's consent screen
const authorizeUrl = kyqu.getOAuthAuthorizeUrl("google");
window.location.href = authorizeUrl;

// Step 2: After callback, user is either:
// - Logged in (existing linked account)
// - Prompted to link to existing email/password account (new OAuth user)

Account Linking

When a user signs in with OAuth for the first time:

  • If the email matches an existing project user, the OAuth identity is linked to that account
  • If the email is new, a new user is created with the OAuth identity attached

Implementation Details

  • Authorization code flow with PKCE
  • State parameter with CSRF protection
  • Provider configurations stored per project in project_oauth_providers table
  • OAuth states tracked in project_oauth_states with TTL
  • Account links stored in project_user_oauth_links