OpenID Connect (OIDC) is an identity layer on top of OAuth 2.0 that lets you verify user identity and get basic profile information. If you're building a web app that needs to know who the user is, OIDC is the way to go.
Discovery
The OIDC discovery document is available at:
GET /.well-known/openid-configuration
This returns all the endpoints and capabilities of our OIDC implementation. Most OIDC libraries will auto-configure themselves from this URL.
Quick Start
1. Create an OAuth application
Head to the Developer Apps page and create a new app. Make sure to:
- Set your redirect URI (e.g., https://arcade.hackclub.com/auth/callback)
- Note your Client ID and Client Secret
2. Redirect users to authorize
GET https://auth.hackclub.com/oauth/authorize?client_id=your_client_id&redirect_uri=https%3A%2F%2Farcade.hackclub.com%2Fauth%2Fcallback&response_type=code&scope=openid+profile+email
3. Exchange the code for tokens
After the user authorizes, they'll be redirected back with an authorization code:
https://arcade.hackclub.com/auth/callback?code=a1b2c3d4e5f6
Exchange it for tokens:
POST https://auth.hackclub.com/oauth/token
Request body:
{
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"redirect_uri": "https://arcade.hackclub.com/auth/callback",
"code": "a1b2c3d4e5f6",
"grant_type": "authorization_code"
}
Response:
{
"access_token": "idntk.abc123...",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
The id_token is a signed JWT containing the user's identity claims.
4. Validate the ID token
The ID token is a JWT signed with RS256. You can:
- Decode and validate it using a JWT library
- Fetch our public keys from the JWKS endpoint to verify the signature
GET /oauth/discovery/keys
5. (Optional) Fetch user info
You can also get user claims from the userinfo endpoint:
GET /oauth/userinfo
Include the access token in the Authorization header:
Authorization: Bearer idntk.abc123...
Slack's OIDC solution provides a picture field in its claims that gives you a URL to the user's PFP. HCA doesn't currently have this feature, but you can get similar functionality with cachet if you take the Slack ID claim.
Scopes and Claims
Standard OIDC Scopes
| Scope | Claims | Description |
|---|---|---|
openid |
sub |
Required for OIDC. Returns the user's public ID (ident!abc123) |
profile |
name, given_name, family_name, nickname, updated_at |
Basic profile info |
email |
email, email_verified |
Email address |
phone |
phone_number, phone_number_verified |
Phone number |
address |
address |
Structured address object |
birthdate |
birthdate |
Date of birth (ISO 8601) |
Hack Club Custom Scopes
| Scope | Claims | Description |
|---|---|---|
slack_id |
slack_id |
The user's Hack Club Slack ID |
verification_status |
verification_status, ysws_eligible |
Verification status and YSWS eligibility |
Example ID Token Claims
With scopes openid profile email verification_status:
{
"iss": "https://auth.hackclub.com",
"sub": "ident!sdfjksfjd",
"aud": "your_client_id",
"exp": 1700000000,
"iat": 1699996400,
"name": "Heidi Trashworth",
"given_name": "Heidi",
"family_name": "Trashworth",
"email": "[email protected]",
"email_verified": true,
"verification_status": "verified",
"ysws_eligible": true
}
Address Claim Format
When the address scope is granted, the address claim follows the OIDC standard format:
{
"address": {
"street_address": "15 Falls Road",
"locality": "Shelburne",
"region": "VT",
"postal_code": "05482",
"country": "US"
}
}
Reauthentication
If you need to force the user to re-authenticate (for sensitive operations), use the prompt=login parameter:
GET https://auth.hackclub.com/oauth/authorize?client_id=your_client_id&prompt=login&redirect_uri=https%3A%2F%2Farcade.hackclub.com%2Fauth%2Fcallback&response_type=code&scope=openid
This will require the user to verify their identity again, even if they have an active session. They can use TOTP, backup codes, or email verification.
You can also use max_age to require reauthentication if the user's session is older than a certain number of seconds:
max_age=3600
Community Apps
Using an OIDC Library
Most languages have OIDC client libraries that handle the complexity for you. Point them at our discovery URL and they'll figure out the rest:
https://auth.hackclub.com/.well-known/openid-configuration
Example: Better Auth
Better Auth is a popular TypeScript authentication library. Here's how to add Hack Club Auth as an OIDC provider:
1. Install the plugin:
npm i better-auth
2. Configure the server:
// auth.ts
import { betterAuth } from "better-auth"
import { genericOAuth } from "better-auth/plugins"
export const auth = betterAuth({
// ...your other config
plugins: [
genericOAuth({
config: [
{
providerId: "hackclub",
discoveryUrl: "https://auth.hackclub.com/.well-known/openid-configuration",
clientId: process.env.HACKCLUB_CLIENT_ID,
clientSecret: process.env.HACKCLUB_CLIENT_SECRET,
scopes: ["openid", "profile", "email", "verification_status"],
},
],
}),
],
})
3. Add the client plugin:
// auth-client.ts
import { createAuthClient } from "better-auth/client"
import { genericOAuthClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [genericOAuthClient()],
})
4. Sign in:
await authClient.signIn.oauth2({
providerId: "hackclub",
callbackURL: "/dashboard",
})
Better Auth will automatically discover our endpoints, handle the OAuth flow, and validate the ID token for you.
Other Popular Libraries
- Ruby:
omniauth-openid-connect - Node.js:
openid-client - Python:
Authlib - Go:
go-oidc
Happy hacking!