This repository provides Identra, an authentication + user management service. For “agents” (CLI tools, bots, backend services, web/mobile apps), Identra’s role is to issue and refresh JWTs and to provide login methods (GitHub OAuth, email code, email+password).
identra-grpc: gRPC server implementingidentra.v1.IdentraService(business logic, persistence, token signing).identra-gateway: HTTP server using grpc-gateway to expose REST/JSON endpoints (and optionally serve a frontend SPA).- JWT + JWKS: Tokens are RS256-signed and the public key is exposed as JWKS for verification by other services.
The service interface is defined in proto/identra/v1/identra_service.proto and exported as OpenAPI at gen/openapi/identra.swagger.json.
The gateway mounts the API under an /api/ prefix, so routes below are typically reachable as:
GET /api/.well-known/jwks.jsonPOST /api/password/login- etc.
-
JWKS
GET /.well-known/jwks.json: fetch public keys for verifying JWTs.
-
OAuth (GitHub)
GET /oauth/url?provider=github&redirect_url=...: returns{ url, state }for starting OAuth.POST /oauth/login: exchange{ code, state }for aTokenPair.POST /oauth/bind: bind GitHub identity to an existing user with{ access_token, code, state }.
-
Email verification code
POST /email/code: send a login code to{ email, use_html }.POST /email/login: exchange{ email, code }for aTokenPair.
-
Email + password
POST /password/login: exchange{ email, password }for aTokenPair.
-
Tokens
POST /token/refresh: exchange{ refresh_token }for a newTokenPair.
-
Session introspection
POST /me/login-info: returns linked login methods for{ access_token }(email, GitHub link status, etc.).
TokenPair contains:
- access_token: short-lived JWT used to authenticate API calls (default 15 minutes).
- refresh_token: long-lived JWT used only to refresh tokens (default 7 days).
- token_type:
"Bearer".
- Tokens are signed using RS256 and include a
kidheader. - Retrieve keys from
GET /.well-known/jwks.jsonand select the matchingkid.
Identra uses standard registered claims plus a few custom ones:
- Registered:
iss,sub(user id),exp,iat,nbf,jti - Custom
uid: user id (duplicatessub)typ:"access"or"refresh"
Identra’s own “authenticated” endpoints (/oauth/bind, /me/login-info) currently accept the access token in the JSON body as access_token.
Other services should typically accept it via the standard HTTP header:
Authorization: Bearer <access_token>
POST /email/codewith{ "email": "...", "use_html": true }- User receives a 6-digit code (stored in Redis with TTL).
POST /email/loginwith{ "email": "...", "code": "123456" }→TokenPair
POST /password/loginwith{ "email": "...", "password": "..." }- If the user does not exist, Identra creates it and stores a password hash.
- If the user exists but has no password set yet, Identra sets it on first login.
GET /oauth/url?provider=github&redirect_url=<your callback URL>→{ url, state }- User completes GitHub consent; your callback receives
code(and you already havestate). POST /oauth/loginwith{ "code": "...", "state": "..." }→TokenPair
- Start OAuth the same way (
/oauth/url). POST /oauth/bindwith{ "access_token": "<current access token>", "code": "...", "state": "..." }- Returns a refreshed
TokenPairafter linking.
POST /token/refreshwith{ "refresh_token": "<refresh token>" }→ newTokenPair
See CONTRIBUTING.md:
buf dep updatebuf generate --clean
- Redis is required for email-code login (verification codes are stored in Redis).
- SMTP is optional (email sending is disabled when
smtp_mailer.hostis empty). - Persistence defaults to SQLite via GORM (
data/users.db) but MongoDB is supported.
Config keys are defined in internal/infrastructure/configs/keys.go and set in configs/grpc/default.toml / configs/gateway/default.toml:
- Ports
grpc_porthttp_port
- Auth
auth.rsa_private_key(optional; if empty Identra generates a key pair at startup)auth.oauth_state_expirationauth.access_token_expiration,auth.refresh_token_expirationauth.token_issuerauth.github.client_id,auth.github.client_secret
- Redis
redis.urls,redis.password
- Persistence
persistence.type(gormormongo)persistence.gorm.*,persistence.mongo.*
- SMTP
smtp_mailer.*
OAuth state is currently stored in an in-memory store (internal/infrastructure/oauth/state_store.go). In a multi-instance deployment, you’ll need a shared store (e.g., Redis) to make the OAuth flow work reliably across replicas.