167 lines
6.0 KiB
Markdown
167 lines
6.0 KiB
Markdown
# 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 Apple** → **Configure**.
|
|
- 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):
|
|
|
|
```go
|
|
// 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`.
|