OAuth Client
Sign in with GitHub or Google. Scaffolded by
soli generate oauth
— the opposite of
OIDC provider
(your app as the IdP).
Prerequisites
soli generate auth # User + sessions (required)
soli generate oauth github # and/or google
soli db:migrate up
What gets generated
| Path | Role |
|---|---|
app/models/oauth_identity.sl | Links User ↔ provider + uid |
app/services/oauth_client.sl | State CSRF, PKCE, find-or-create user |
app/services/github_oauth.sl | GitHub authorize / token / profile |
app/services/google_oauth.sl | Google OIDC code + PKCE |
app/controllers/oauth_controller.sl | /auth/:provider + callback |
db/migrations/*_create_oauth_identities.sl | Unique index on (provider, uid) |
Environment
GitHub
GITHUB_CLIENT_ID=…
GITHUB_CLIENT_SECRET=…
GITHUB_REDIRECT_URI=http://localhost:3000/auth/github/callback
GOOGLE_CLIENT_ID=…
GOOGLE_CLIENT_SECRET=…
GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback
Login button
Add a link yourself (generator does not rewrite session views):
<a href="/auth/github">Sign in with GitHub</a>
<a href="/auth/google">Sign in with Google</a>
Security
- Callback verifies
stateagainst the session (CSRF) - PKCE is
S256.begin_pkce()stores a random verifier in the session and returnsbase64url(SHA256(verifier))unpadded, per RFC 7636 §4.2. Earlier cuts sent the raw verifier withcode_challenge_method=plain, where the challenge and the verifier are the same string — PKCE in name only. Never shipplain. - The services call
HTTP.request(method, url, headers, body).HTTP.get/HTTP.postread their options hash fortimeoutalone and return the body as a String, so a"headers"key there is silently dropped — which is why the generated flow used to 401. Provider responses are status-checked, so a 401 reports as a 401 rather than a JSON parse error on the provider's error page. - Google requires a verified email
- OAuth-created accounts get a random password and confirmed email
- Use HTTPS redirect URIs in production
Ceiling
v1 providers: GitHub and Google only. Longer walkthroughs: GitHub, Google.