Skip to content

Quick Start

Workers Auth gives you authentication, authorization, and user management that runs entirely on Cloudflare’s edge. This guide walks you through a complete setup: magic link login, GitHub OAuth, role-based access control, and a full admin API.

  1. Install the packages

    Workers Auth is built on Hono. Install both:

    Terminal window
    npm install workers-auth hono
  2. Create your infrastructure

    Workers Auth stores users and sessions in D1, with KV as a fast session cache. Create both from the command line:

    Terminal window
    wrangler d1 create auth
    wrangler kv namespace create SESSIONS

    Then wire the returned IDs into your wrangler.toml:

    name = "my-app"
    main = "src/index.ts"
    compatibility_date = "2024-12-01"
    [[d1_databases]]
    binding = "DB"
    database_name = "auth"
    database_id = "<your-database-id>"
    [[kv_namespaces]]
    binding = "SESSIONS"
    id = "<your-kv-id>"
  3. Set your secrets

    Workers Auth needs API keys for email delivery and (optionally) OAuth. Store them as encrypted secrets — never in source control:

    Terminal window
    wrangler secret put RESEND_API_KEY
    wrangler secret put GITHUB_CLIENT_ID
    wrangler secret put GITHUB_CLIENT_SECRET
  4. Build your app

    This is the complete Worker. It configures both authentication strategies, sets up RBAC, and mounts the auth handler alongside the admin API:

    import { Hono } from 'hono';
    import { WorkersAuth } from 'workers-auth';
    import { MagicLinkStrategy } from 'workers-auth/authn/magic-link';
    import { GitHubStrategy } from 'workers-auth/authn/github';
    import { RBACPolicy } from 'workers-auth/authz/rbac';
    import { ResendProvider } from 'workers-auth/providers/resend';
    import { D1Adapter } from 'workers-auth/adapters/d1';
    import { KVAdapter } from 'workers-auth/adapters/kv';
    import { defaultTemplate } from 'workers-auth/templates/default';
    type Env = {
    DB: D1Database;
    SESSIONS: KVNamespace;
    RESEND_API_KEY: string;
    GITHUB_CLIENT_ID: string;
    GITHUB_CLIENT_SECRET: string;
    };
    const app = new Hono<{ Bindings: Env }>();
    const auth = WorkersAuth({
    database: (binding) => D1Adapter(binding),
    cache: (binding) => KVAdapter(binding),
    authn: {
    strategies: [
    MagicLinkStrategy({
    provider: ResendProvider({
    apiKey: process.env.RESEND_API_KEY!,
    from: 'auth@yourdomain.com',
    }),
    template: defaultTemplate,
    }),
    GitHubStrategy({
    clientId: process.env.GITHUB_CLIENT_ID!,
    clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
    ],
    session: { secret: 'your-secret-key-here' },
    },
    authz: RBACPolicy({
    roles: { admin: ['*'], user: ['read'] },
    defaultRole: 'user',
    }),
    redirectUrl: '/dashboard',
    });
    // Auth routes — login, logout, session management
    app.route('/auth', auth.handler);
    // Admin API — user management (protect with auth + admin role)
    app.use('/auth/admin/*', auth.authenticate);
    app.use('/auth/admin/*', auth.authorize('role', 'admin'));
    app.route('/auth/admin', auth.admin);
    // Protect your API routes — requires a valid session
    app.use('/api/*', auth.authenticate);
    // Your application routes
    app.get('/api/me', (c) => c.json(c.get('user')));
    export default app;
  5. Get a Resend API key

    Resend handles magic link email delivery. Sign up, verify your sending domain, and create an API key. You already stored it as a secret in step 3.

  6. Create a GitHub OAuth App (optional)

    If you included the GitHub strategy:

    1. Open GitHub Developer Settings and click New OAuth App
    2. Set the callback URL to https://your-app.workers.dev/auth/github/callback
    3. Copy the Client ID and Client Secret — you stored these as secrets in step 3
  7. Deploy

    Terminal window
    wrangler deploy

    D1 tables are created automatically on the first request. No migrations, no setup scripts.

That single file gave you a production-ready auth system. Here is every route Workers Auth registered:

Mounted via app.route('/auth', auth.handler):

RouteMethodDescription
/auth/magic-link/sendPOSTSend a magic link email
/auth/magic-link/verifyGETVerify the token and create a session
/auth/githubGETStart the GitHub OAuth flow
/auth/github/callbackGETHandle the GitHub OAuth callback
/auth/sessionGETReturn the current session and user
/auth/logoutPOSTDestroy the active session

Mounted via app.route('/auth/admin', auth.admin), protected behind authenticate and authorize('role', 'admin'):

RouteMethodDescription
/auth/admin/usersGETList users with pagination
/auth/admin/users/:idGETGet a single user with roles
/auth/admin/users/:id/banPOSTBan a user and revoke all sessions
/auth/admin/users/:id/unbanPOSTUnban a user
/auth/admin/users/:id/rolesPOSTAssign a role to a user
/auth/admin/users/:id/roles/:roleDELETERemove a role from a user

Defined in your app code, protected by auth.authenticate:

RouteMethodDescription
/api/meGETReturn the authenticated user
  • Magic Links — customize email templates and link expiry
  • GitHub OAuth — configure scopes and callback handling
  • RBAC — define roles and permissions for your app
  • D1 Adapter — database schema and custom adapters
  • KV Adapter — session caching and custom cache adapters
  • API Reference — full list of exports and types