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