Waymaker Host

Site Auth: Add Waymaker Login to Your Site

Learn about Site Auth: Add Waymaker Login to Your Site in WaymakerOS.

AuthenticationSite AuthSecurity

Waymaker Site Auth lets any static site or app hosted on Waymaker Host use your existing Waymaker login for authentication. Add a script tag and three lines of JavaScript — your users sign in with their Waymaker account, and your Ambassadors know exactly who is making each request.

Quick Start

1. Add the Auth Script

Include the Waymaker auth client on any page that needs login:

<script src="https://cdn.waymakerone.com/auth.js"></script>

2. Initialize and Check Login

<script>
  const wm = WaymakerAuth.init({ appId: 'your-app-id' })

  if (!wm.isAuthenticated()) {
    wm.login()
  }
</script>

That's it. Unauthenticated visitors are redirected to the Waymaker login page, then returned to your site with a valid session.

3. Use the Session

Once authenticated, you have access to the user's identity and a token for API calls:

const user = wm.getUser()
// { id: 'user_abc', email: 'jane@acme.com', name: 'Jane Smith', role: 'admin' }

const token = wm.getToken()
// Use this token when calling your Ambassadors

How It Works

  1. User visits your protected page (e.g., yourdomain.com/admin)
  2. WaymakerAuth.init() checks for an existing session in browser storage
  3. No session found — wm.login() redirects to auth.waymakerone.com
  4. User signs in with their Waymaker account (email, password, or SSO)
  5. After sign-in, the user is redirected back to your page with a short-lived exchange token
  6. The auth client automatically exchanges the token for a session and stores it
  7. Your page now has access to the user's identity and an access token for API calls

The entire flow takes a few seconds. Your site never handles passwords or credentials directly.

API Reference

MethodReturnsDescription
WaymakerAuth.init({ appId })WaymakerAuthInitialize auth with your Host app ID
wm.isAuthenticated()booleantrue if the user has a valid session
wm.login()voidRedirects to Waymaker login, returns to current page after sign-in
wm.logout()voidEnds the session and clears stored credentials
wm.getToken()`stringnull`
wm.getUser()`Usernull`
wm.onAuthChange(callback)() => voidCalls your function when auth state changes. Returns an unsubscribe function

User Object

{
  id: 'user_abc123',        // Waymaker user ID
  email: 'jane@acme.com',   // Email address
  name: 'Jane Smith',       // Display name
  role: 'admin'             // Role within the workspace
}

Full Example: Protected Admin Page

Here is a complete HTML page with authentication and an Ambassador API call:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Admin</title>
  <script src="https://cdn.waymakerone.com/auth.js"></script>
</head>
<body>
  <div id="loading">Checking login...</div>
  <div id="admin" style="display: none;">
    <h1>Welcome, <span id="user-name"></span></h1>
    <p>Email: <span id="user-email"></span></p>
    <button id="upload-btn">Upload Document</button>
    <button id="logout-btn">Sign Out</button>
  </div>

  <script>
    const wm = WaymakerAuth.init({ appId: 'your-app-id' })

    if (!wm.isAuthenticated()) {
      wm.login() // Redirects to Waymaker login
    } else {
      // User is signed in — show the admin UI
      document.getElementById('loading').style.display = 'none'
      document.getElementById('admin').style.display = 'block'

      const user = wm.getUser()
      document.getElementById('user-name').textContent = user.name
      document.getElementById('user-email').textContent = user.email

      // Call an Ambassador with the auth token
      document.getElementById('upload-btn').addEventListener('click', async () => {
        const response = await fetch('https://ambassador.waymakerone.com/your-app/upload', {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${wm.getToken()}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({ title: 'My Document' })
        })

        if (response.ok) {
          alert('Upload successful')
        } else if (response.status === 401) {
          wm.login() // Session expired — re-authenticate
        }
      })

      // Sign out
      document.getElementById('logout-btn').addEventListener('click', () => {
        wm.logout()
        window.location.reload()
      })
    }
  </script>
</body>
</html>

Validating Tokens in Ambassadors

When your Ambassador receives a request with a Bearer token, validate it against the Context API:

async function handleRequest(request: Request) {
  // 1. Extract the token
  const token = request.headers.get('Authorization')?.replace('Bearer ', '')
  if (!token) {
    return new Response('Unauthorized', { status: 401 })
  }

  // 2. Validate against Context API
  const auth = await fetch('https://auth.waymakerone.com/context/auth/validate', {
    headers: { 'Authorization': `Bearer ${token}` }
  })

  if (!auth.ok) {
    return new Response('Unauthorized', { status: 401 })
  }

  // 3. Use the verified identity
  const { user, workspace } = await auth.json()
  // user.id, user.email, user.role
  // workspace.id, workspace.tier

  // Now process the request knowing who made it
  return new Response(`Hello ${user.name}`, { status: 200 })
}

The Ambassador never handles credentials directly. It receives a token, validates it with one API call, and gets back the user's identity and workspace context.

ES Module Usage

If you prefer ES modules over a script tag:

<script type="module">
  import { WaymakerAuth } from 'https://cdn.waymakerone.com/auth.mjs'

  const wm = WaymakerAuth.init({ appId: 'your-app-id' })

  if (!wm.isAuthenticated()) {
    wm.login()
  }
</script>

Auth State Changes

Subscribe to authentication changes to update your UI when the user signs in or out:

const unsubscribe = wm.onAuthChange((isAuthenticated) => {
  if (isAuthenticated) {
    showAdminUI(wm.getUser())
  } else {
    showLoginPrompt()
  }
})

// Later, stop listening
unsubscribe()

Finding Your App ID

Your app ID is assigned when you create an app in Waymaker Host. You can find it:

  • In Host, open your app's settings — the app ID is displayed at the top
  • Using the CLI: waymaker host apps list
  • Using Claude Desktop: "What's the app ID for my app?"

Allowed Domains

For security, each app must register the domains that are allowed to use authentication. Waymaker only redirects back to registered domains after sign-in.

Your app's domains are configured automatically when you set up a custom domain in Host. If you need to add additional domains, update them in your app's settings or contact support.

Token Lifecycle

  • Session storage: Tokens are stored in the browser's session storage (cleared when the tab closes)
  • Automatic refresh: The auth client refreshes tokens before they expire — no re-login needed during a session
  • 1-hour tokens: Access tokens are valid for 1 hour and refreshed automatically
  • Sign out: Calling wm.logout() invalidates the session on the server and clears local storage

Troubleshooting

"Unauthorized" errors from Ambassador

  1. Confirm your app ID matches the one in Host
  2. Check that the domain is registered in your app's allowed domains
  3. Verify the token is being sent in the Authorization header as Bearer <token>
  4. If the token has expired, call wm.login() to start a fresh session

Login redirect loops

  1. Make sure your app ID is correct
  2. Verify your domain is in the allowed domains list for that app
  3. Clear your browser's session storage and try again

Token not found after redirect

The auth client reads the exchange token from the URL after sign-in. If this fails:

  1. Check that the auth script is loaded before your initialization code
  2. Ensure nothing else is modifying the URL query parameters on page load
  3. Try a different browser to rule out extension interference