Add sign-in
with JustAuth

Register an app, send your users to JustAuth, and get back a verified GitHub profile through the standard OAuth 2.0 authorization code flow.

>_ terminal
https://justauth.org/oauth/authorize
  ?response_type=code
  &client_id=ja_...
  &redirect_uri=https://myapp.com/auth/callback
  &scope=profile%20email
  &state=RANDOM

Set up your coding agent

Give your coding agent this prompt. It points the agent at /llms.txt, which has everything it needs to wire up the OAuth flow.

Agent prompt

Add Sign in with JustAuth to my app. Fetch https://justauth.org/llms.txt and follow it.

OAuth endpoints

Authorize, token and userinfo. Parameters, scopes and every error code.

Management API

Create and manage apps from code with a personal API key.

llms.txt

These docs as plain Markdown, for coding agents and LLMs.

Status

What works today:

  • Sign in to justauth.org with GitHub.
  • Register apps (OAuth clients) with wildcard redirect URIs.
  • The OAuth 2.0 authorization code flow, with optional PKCE: /oauth/authorize, /oauth/token, /oauth/userinfo.
  • Personal API keys and a Management API at /api/v1/apps for managing apps from code.
  • A dashboard that lists the people who have signed in to your apps.

Not available yet:

  • Official SDK packages. There is no @justauth/* package on npm, no npx justauth command and no cdn.justauth.org script. Do not try to install them. Use any standard OAuth 2.0 client library with the endpoints below.
  • Passkey and email-link sign-in to JustAuth. Today, everyone signs in to JustAuth with GitHub.
  • Refresh tokens, ID tokens (JWTs), OpenID discovery documents and webhooks.
  • Billing. The plans at https://justauth.org/#pricing (Free, Indie, Pro and Scale, priced by monthly active users) are published, but nobody is charged during early access.

Quickstart

  1. Open https://justauth.org, select Sign in, and sign in with GitHub.

  2. In the dashboard, open Apps and create an app. Enter a name and your redirect URIs, for example http://localhost:* and https://myapp.com/auth/callback.

  3. Copy the client ID (starts with ja_) and the client secret (starts with jas_). The secret is shown only once.

  4. Send your users to the authorize endpoint:

    https://justauth.org/oauth/authorize?response_type=code&client_id=ja_...&redirect_uri=https://myapp.com/auth/callback&scope=profile%20email&state=RANDOM
    
  5. JustAuth redirects back to your redirect_uri with ?code=...&state=.... Check that state matches what you sent.

  6. On your server, exchange the code for an access token:

    curl https://justauth.org/oauth/token \
      -d grant_type=authorization_code \
      -d code=CODE_FROM_STEP_5 \
      -d redirect_uri=https://myapp.com/auth/callback \
      -d client_id=ja_... \
      -d client_secret=jas_...
    
    { "access_token": "...", "token_type": "Bearer", "expires_in": 3600, "scope": "profile email" }
    
  7. Read the user's profile:

    curl https://justauth.org/oauth/userinfo -H "Authorization: Bearer ACCESS_TOKEN"
    
    {
      "sub": "42",
      "preferred_username": "octocat",
      "name": "The Octocat",
      "picture": "https://...",
      "email": "octocat@github.com"
    }
    

Use sub as the stable user ID in your app.

Sign in to justauth.org

  1. Select Sign in in the top bar of the homepage.
  2. GitHub asks you to authorize JustAuth. Select Authorize.
  3. You land on /dashboard. If you started from a dashboard page or an app's sign-in, you return there instead.

If sign-in fails (for example, you cancel on GitHub), you return to the homepage with ?auth_error=github in the address.

To sign out, select Sign out at the bottom of the dashboard sidebar, or next to your username on the homepage. This deletes your JustAuth session. It does not revoke JustAuth's authorization on GitHub. To do that, go to GitHub Settings → Applications → Authorized GitHub Apps.

Dashboard

The dashboard requires you to be signed in. It has these sections:

  • Overview (/dashboard): counts of your apps, users and API keys, and the five most recent sign-ins to your apps.
  • Users (/dashboard/users): you, plus everyone who has approved one of your apps, most recent login first. Search matches login, name and email. You can link to a search directly: /dashboard/users?q=octocat.
  • Apps (/dashboard/apps): create, edit and delete apps, and rotate client secrets.
  • API keys (/dashboard/api-keys): create and revoke keys for the Management API.

Apps and redirect URIs

An app is an OAuth client. Each app has a name (up to 100 characters), a client ID (ja_...), a client secret (jas_...) and 1 to 20 redirect URI patterns.

JustAuth stores only a hash of the client secret, so it is shown once, when you create the app or rotate the secret. Rotating a secret makes the old one stop working immediately and revokes the app's access tokens.

Redirect URI patterns may use wildcards:

Pattern Matches
https://myapp.com/auth/callback Exactly that path
https://myapp.com Any path on https://myapp.com
https://myapp.com/auth/* Any path starting with /auth/
https://*.myapp.com Any subdomain, such as preview deployments
http://localhost:* Any port on localhost

Rules:

  • Plain http is allowed only on localhost, 127.0.0.1 and [::1]. Everything else must be https.
  • A wildcard subdomain needs at least two labels after it: https://*.myapp.com is valid, https://*.com is not.
  • Query strings are allowed in the requested redirect_uri, but fragments (#...) and credentials are not.

OAuth reference

GET /oauth/authorize

Parameter Required Notes
response_type Yes Must be code.
client_id Yes Your app's ja_... ID.
redirect_uri Yes Must match one of the app's patterns.
scope No Space-separated. openid, profile, email. Defaults to profile.
state Recommended Returned unchanged. Use it to prevent CSRF.
code_challenge No PKCE. Recommended for browser and mobile apps.
code_challenge_method No S256 (recommended) or plain. Defaults to plain when a challenge is sent.

What happens:

  • If the person is not signed in to JustAuth, they sign in with GitHub first, then continue.
  • The first time, they see a consent screen listing the requested scopes. JustAuth remembers their approval, so later requests for the same scopes skip the screen.
  • On success, JustAuth redirects to redirect_uri with code and state. The code is single-use and expires after 10 minutes.
  • If the person selects Deny, the redirect carries error=access_denied. Other errors are unsupported_response_type, invalid_scope and invalid_request.
  • If client_id is unknown or redirect_uri doesn't match, JustAuth shows an error page instead of redirecting.

POST /oauth/token

Send form-encoded parameters (application/x-www-form-urlencoded):

Parameter Notes
grant_type Must be authorization_code.
code The code from the redirect.
redirect_uri Exactly the same value you sent to /oauth/authorize.
client_id, client_secret In the body, or as an HTTP Basic Authorization header.
code_verifier Required if you sent a code_challenge.

The response contains access_token, token_type (Bearer), expires_in (3600 seconds) and scope. Access tokens last one hour. There are no refresh tokens yet, so send the person through /oauth/authorize again when a token expires. Because they already approved your app, this needs no clicks.

Errors return HTTP 400 or 401 with { "error": "..." }: unsupported_grant_type, invalid_client or invalid_grant.

GET /oauth/userinfo

Send Authorization: Bearer ACCESS_TOKEN. The fields depend on the granted scopes:

Field Scope
sub Always. Stable JustAuth user ID.
preferred_username profile. GitHub login.
name profile. GitHub name, or login if there is none.
picture profile. Avatar URL.
email email. Public GitHub email, or null.

An invalid or expired token returns HTTP 401 with { "error": "invalid_token" }.

Management API

Manage your apps from code.

  1. Create a key on the API keys page of the dashboard. Keys start with jak_ and are shown once.
  2. Send the key as a Bearer token. Send request bodies as JSON with Content-Type: application/json.
curl https://justauth.org/api/v1/apps \
  -H "Authorization: Bearer $JUSTAUTH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "My App", "redirect_uris": ["https://myapp.com", "http://localhost:*"]}'
Method Path What it does
GET /api/v1/apps List your apps: { "apps": [...] }
POST /api/v1/apps Create an app. Body: name, redirect_uris. Returns HTTP 201 with client_secret, shown once.
GET /api/v1/apps/:client_id Get one app.
PATCH /api/v1/apps/:client_id Change name and/or redirect_uris.
DELETE /api/v1/apps/:client_id Delete an app. Returns HTTP 204.
POST /api/v1/apps/:client_id/secret Rotate the secret. Returns the new client_secret and revokes the app's access tokens.

An app object looks like this:

{
  "client_id": "ja_...",
  "name": "My App",
  "redirect_uris": ["https://myapp.com"],
  "created_at": "2026-10-27T00:00:00.000Z"
}

Errors return { "error": "...", "message": "..." }:

Status error Meaning
400 invalid_request The body isn't a JSON object, or Content-Type isn't application/json.
401 unauthorized The API key is missing or invalid.
404 not_found No app with that client_id belongs to you.
422 invalid_app The name or a redirect URI is invalid. message says which.

The API accepts only API keys. It ignores browser cookies.

What we store

  • Your GitHub profile: user ID, login, name, public email and avatar URL, plus when you first and last signed in. Each sign-in updates these.
  • Apps: name, client ID, redirect URIs and a hash of the client secret.
  • Consents: which apps each person has approved, and for which scopes.
  • Authorization codes, access tokens and API keys: hashes only. The plaintext goes only to you or your app.

JustAuth does not store your GitHub access token. It uses the token once, to read your profile during sign-in, and then discards it.

Your browser keeps one session cookie, ja_session. It is signed, HTTP-only and expires after 30 days. Short-lived cookies protect sign-in against forged requests.

All routes

Method Path What it does
GET / Homepage
GET /docs This page
GET /llms.txt This page as plain Markdown
GET /api/auth/github Starts GitHub sign-in to justauth.org. Optional ?next=/path to return to afterwards.
GET /api/auth/callback/github GitHub returns here.
POST /api/auth/signout Signs out and redirects to /.
GET /oauth/authorize OAuth authorization endpoint
POST /oauth/token OAuth token endpoint
GET /oauth/userinfo OAuth user info endpoint
* /api/v1/apps... Management API
GET /dashboard... Dashboard. Requires sign-in.

For agents and LLMs

  • Read /llms.txt for this page as Markdown.
  • To add "Sign in with JustAuth" to an app, use a standard OAuth 2.0 authorization code client with the endpoints in the OAuth reference. Do not generate code that imports @justauth/* packages: they are not published.
  • Signing in to justauth.org requires a person to approve access on github.com in a browser. An agent cannot do this alone, so it cannot create the first app or API key by itself.
  • Once a person gives you an API key (jak_...), you can create and manage apps through the Management API without a browser.
  • Client secrets and API keys are shown only once. Store them as secrets, never in source code.