OpenID Connect

Use OIDC for authentication with Hack Club Auth

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://hca.dinosaurbbq.org/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://hca.dinosaurbbq.org/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:

  1. Decode and validate it using a JWT library
  2. 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://hca.dinosaurbbq.org",
  "sub": "ident!sdfjksfjd",
  "aud": "your_client_id",
  "exp": 1700000000,
  "iat": 1699996400,
  "name": "Heidi Trashworth",
  "given_name": "Heidi",
  "family_name": "Trashworth",
  "email": "racc@garbagemail.biz",
  "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://hca.dinosaurbbq.org/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://hca.dinosaurbbq.org/.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://hca.dinosaurbbq.org/.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!