3 Authentication
Anton Nesterov edited this page 2026-02-26 16:23:25 +01:00

Authentication Methods

VSKI supports three main authentication methods:

  1. Email/Password - Traditional username and password authentication
  2. API Keys - For service-to-service authentication
  3. OAuth2 - Third-party identity providers (Google, GitHub, etc.)

Email/Password Authentication

User Login

import { VskiClient } from "@vski/sdk";

const client = new VskiClient("http://localhost:3000");

// Login with email and password
const result = await client.auth.login("user@example.com", "password123");

console.log(result.token); // JWT token
console.log(result.user); // User record

The login method returns:

  • token: JWT token for authenticated requests
  • user: Full user record including email, name, etc.

Set Authentication Token

// Set token for subsequent requests
client.setToken(result.token);

// Or use the token directly
const user = await client.auth.me();

Get Current User

const user = await client.auth.me();

console.log(user.id);
console.log(user.email);
console.log(user.name);
console.log(user.verified); // Email verification status

User Registration

// Register a new user
const user = await client.auth.register({
  email: "newuser@example.com",
  password: "SecurePassword123!",
  passwordConfirm: "SecurePassword123!",
  name: "John Doe",
});

Note: Password hashing is handled automatically. The user is created in the configured default auth collection.

Email Verification

// Request verification email (requires email service configuration)
// Note: This feature may not be implemented yet
await client.auth.requestVerification("user@example.com");

// Verify email with token
await client.auth.confirmVerification("verification-token");

Password Reset

// Request password reset email
// Note: This feature may not be implemented yet
await client.auth.requestPasswordReset("user@example.com");

// Confirm password reset with token
await client.auth.confirmPasswordReset(
  "reset-token",
  "NewPassword123!",
  "NewPassword123!",
);

Admin Authentication

VSKI includes a default admin account for administrative tasks:

// Login as admin
const result = await client.admins.authWithPassword(
  "admin@example.com",
  "password123",
);

// The admin client has access to settings and management endpoints
const collections = await client.settings.collections.getList();

Important: Change the default admin password immediately in production!

API Key Authentication

API keys are ideal for service-to-service authentication or worker processes.

Creating API Keys

// Admin endpoint to create API key
const apiKey = await client.keys.generate({
  name: "Worker Service",
  enabled: true,
  roles: "service",
});

console.log(apiKey.key); // The actual API key (only shown once)
console.log(apiKey.token); // The token for authentication
console.log(apiKey.id); // Reference ID for the key

Using API Keys

// Set API key as authentication token
client.setToken("your-api-key-here");

// Use client normally
const records = await client.collection("posts").getList(1, 20);

Managing API Keys

img

OAuth2 Authentication

VSKI supports OAuth2 for third-party identity providers.

Available Providers

// List available OAuth2 providers
const methods = await client.auth.listMethods();

console.log(methods.oauth2.providers);
// [
//   { name: "google", displayName: "Google" },
//   { name: "github", displayName: "GitHub" },
//   // ... other providers
// ]

OAuth2 Flow

// 1. Get authorization URL
const authData = await client.auth.authViaOAuth2(
  "google",
  "authorization-code-from-callback",
  "http://localhost:3000/auth/callback",
);

console.log(authData.token);
console.log(authData.user);

Note: The OAuth2 flow requires obtaining the authorization code separately from the OAuth provider. The authViaOAuth2 method exchanges the code for a JWT token.

Authentication Middleware

The SDK automatically includes the authentication token in request headers:

// Token is set automatically in Authorization header
client.setToken("your-jwt-token-or-api-key");

// All subsequent requests include:
// Authorization: Bearer your-jwt-token-or-api-key

Custom Database Authentication

When using multiple databases, authenticate with a specific database:

// Set authentication for a specific database
client.setAuthHeader("x-dbname", "my-database");
client.setToken("your-token");

// Or use the SDK method
client.setTokenForDatabase("your-token", "my-database");

User Collections

Creating Auth Collections

const usersCollection = await client.settings.collections.create({
  name: "_users",
  type: "auth",
  fields: [
    { name: "email", type: "email", required: true },
    { name: "password", type: "text", required: true },
    { name: "name", type: "text" },
    { name: "avatar", type: "url" },
  ],
});

Auth collections automatically include:

  • id: Unique identifier
  • email: Email address
  • created: Creation timestamp
  • updated: Last update timestamp

Note: The collection's schema defines the additional fields available on user records.

Authentication Errors

try {
  await client.auth.login("user@example.com", "wrong-password");
} catch (error) {
  if (error.message.includes("Invalid credentials")) {
    console.log("Wrong email or password");
  } else if (error.message.includes("401")) {
    console.log("Unauthorized");
  }
}

Security Best Practices

  1. Change default admin password - Immediately after first setup
  2. Use HTTPS in production - Always use secure connections
  3. Rotate API keys - Regularly update API keys
  4. Use strong passwords - Enforce password complexity requirements
  5. Enable email verification - Verify user email addresses
  6. Implement rate limiting - Prevent brute force attacks
  7. Store tokens securely - Use secure storage for JWT tokens
  8. Set appropriate token expiration - Balance security and user experience
  9. Use the principle of least privilege - Give users only the access they need

Token Management

Token Refresh

// Refresh token
const newResult = await client.auth.refresh();
client.setToken(newResult.token);

Token Expiration

// Token expiration is handled automatically
// When a token expires, the SDK will throw an error
try {
  await client.collection("posts").getList(1, 20);
} catch (error) {
  if (error.message.includes("401")) {
    // Token expired - need to re-authenticate
    const result = await client.auth.login(email, password);
    client.setToken(result.token);
  }
}

Role-Based Access Control (RBAC)

VSKI integrates with collections to implement role-based access:

// Create a roles collection
const roles = await client.settings.collections.create({
  name: "_roles",
  type: "base",
  fields: [
    { name: "name", type: "text", required: true },
    { name: "permissions", type: "json" },
  ],
});

// Assign role to user
await client.collection("_users").update("user-id", {
  role: "editor",
});

// Check permissions using rules
await client.settings.rules.create({
  name: "Editor Access",
  collection: "posts",
  rule: "user.role = 'editor'",
});

API Endpoints

Method Endpoint Description
POST /api/auth/login Login with email/password
POST /api/auth/register Register new user
POST /api/auth/refresh Refresh JWT token
GET /api/auth/methods List auth providers
GET /api/auth/me Get current user
GET /api/auth/oauth2-login OAuth2 code exchange
POST /api/admins/auth-with-password Admin authentication
POST /api/admins/init Initialize first admin
GET /api/admins/has-admins Check if admins exist
GET /api/admins/me Get current admin
POST /api/keys Generate API key
POST /api/collections/{collection}/auth-with-password Collection-specific auth