clavitor/clavitor.ai/OAUTH_SETUP.md

6.0 KiB

OAuth Setup — Google, Apple, Meta

The onboarding flow at /signup supports email plus three social providers. Email always works. Social providers light up the moment you set their env vars.

All three need the same three things:

  • A Client ID (public)
  • A Client Secret (keep secret)
  • A Redirect URL registered with the provider — this MUST match what you set on our side, character for character

The redirect URL is where the provider sends the user back after they consent. For production, use the canonical clavitor.ai host:

  • Google: https://clavitor.ai/auth/google/callback
  • Apple: https://clavitor.ai/auth/apple/callback
  • Meta: https://clavitor.ai/auth/meta/callback

For local dev, register a second app per provider with http://localhost:8099/auth/<name>/callback (Apple requires HTTPS even for dev — use a tunnel like Tailscale Funnel or ngrok).

After registering, set the env vars on the server (systemd unit or .env):

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URL=https://clavitor.ai/auth/google/callback

APPLE_CLIENT_ID=
APPLE_CLIENT_SECRET=
APPLE_REDIRECT_URL=https://clavitor.ai/auth/apple/callback

META_CLIENT_ID=
META_CLIENT_SECRET=
META_REDIRECT_URL=https://clavitor.ai/auth/meta/callback

Restart the web server. Look for OAuth: google configured in the logs.


Google

Console: https://console.cloud.google.com/

  1. Create a new project (or pick an existing one).
  2. Open APIs & Services → OAuth consent screen.
    • User type: External.
    • App name: Clavitor. Support email: support@clavitor.ai.
    • Authorized domains: clavitor.ai, clavitor.com.
    • Scopes: add openid, email, profile.
    • Test users: while in "Testing" mode, only listed users can sign in. Promote to "In production" before launch.
  3. Open APIs & Services → Credentials → Create Credentials → OAuth client ID.
    • Application type: Web application.
    • Name: Clavitor (production).
    • Authorized JavaScript origins: https://clavitor.ai, https://clavitor.com.
    • Authorized redirect URIs: https://clavitor.ai/auth/google/callback.
  4. Copy the Client ID and Client Secret into the env vars above.

Apple

Console: https://developer.apple.com/account/resources/

Apple's Sign in with Apple is the most fiddly. You need a paid Apple Developer account ($99/yr).

  1. Create an App ID

    • Identifiers → "+" → App IDs → App.
    • Description: Clavitor. Bundle ID: ai.clavitor.web (reverse-DNS).
    • Capabilities: enable Sign in with Apple.
  2. Create a Services ID (this is what acts as the OAuth client_id)

    • Identifiers → "+" → Services IDs.
    • Description: Clavitor Web. Identifier: ai.clavitor.web.signin.
    • Enable Sign in with AppleConfigure.
      • Primary App ID: the one from step 1.
      • Domains: clavitor.ai, clavitor.com.
      • Return URLs: https://clavitor.ai/auth/apple/callback.
  3. Create a Sign in with Apple key

    • Keys → "+".
    • Name: Clavitor SIWA. Enable Sign in with Apple, configure to the App ID above.
    • Download the .p8 file. You can only download it once.
    • Note the Key ID and your Team ID (top right of the dashboard).
  4. Generate the client_secret — Apple's secret is a JWT you sign with the .p8 key. It expires every 6 months. Use this Go snippet (one-shot tool):

    // tools/apple_secret.go — run once, copy output to APPLE_CLIENT_SECRET
    package main
    
    import (
        "crypto/x509"
        "encoding/pem"
        "fmt"
        "os"
        "time"
        "github.com/golang-jwt/jwt/v5"
    )
    
    func main() {
        teamID := "YOUR_TEAM_ID"
        clientID := "ai.clavitor.web.signin"
        keyID := "YOUR_KEY_ID"
        p8, _ := os.ReadFile("AuthKey_YOUR_KEY_ID.p8")
    
        block, _ := pem.Decode(p8)
        key, _ := x509.ParsePKCS8PrivateKey(block.Bytes)
    
        claims := jwt.MapClaims{
            "iss": teamID,
            "iat": time.Now().Unix(),
            "exp": time.Now().Add(180 * 24 * time.Hour).Unix(),
            "aud": "https://appleid.apple.com",
            "sub": clientID,
        }
        tok := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
        tok.Header["kid"] = keyID
        s, _ := tok.SignedString(key)
        fmt.Println(s)
    }
    
  5. Set the env vars:

    • APPLE_CLIENT_ID = the Services ID from step 2 (ai.clavitor.web.signin)
    • APPLE_CLIENT_SECRET = the JWT from step 4
    • APPLE_REDIRECT_URL = https://clavitor.ai/auth/apple/callback

Note: Apple uses response_mode=form_post, which means the callback comes in as a POST instead of a GET. Our handler already handles both.


Meta (Facebook)

Console: https://developers.facebook.com/

  1. Create an app
    • My Apps → Create App.
    • Use case: Authenticate and request data from users with Facebook Login.
    • App name: Clavitor. Contact email: support@clavitor.ai.
  2. Add Facebook Login
    • Add Product → Facebook Login → Set Up → Web.
    • Site URL: https://clavitor.ai.
  3. Configure
    • Facebook Login → Settings.
    • Valid OAuth Redirect URIs: https://clavitor.ai/auth/meta/callback.
    • Client OAuth Login: ON. Web OAuth Login: ON. Use Strict Mode: ON.
  4. Get credentials
    • Settings → Basic.
    • Copy App ID → META_CLIENT_ID.
    • Copy App Secret → META_CLIENT_SECRET.
  5. Switch to Live mode
    • Top-right toggle: Development → Live.
    • You may need to submit for App Review if you request anything beyond email and public_profile. We only ask for those, so review is usually waived.

Verifying

Tail the web server logs after restart:

OAuth: google configured
OAuth: apple configured
OAuth: meta configured

Each provider that's missing env vars is silently skipped — its button on /signup returns a 503 with a "not configured" message until you finish setup.

Click each button and walk through the consent screen. You should land on /onboarding/profile with your email pre-populated as a customer in corporate.db.