A production-ready OAuth 2.0 toolkit for Go — covering both the Authorization Server and a smart CLI client that auto-selects the right flow for the runtime environment.
| Repository | Description |
|---|---|
authgate |
OAuth 2.0 Authorization Server — Device Grant + Auth Code Flow with PKCE |
cli |
Smart OAuth CLI — auto-detects environment and picks the right flow |
Designed for web apps, SPAs, and mobile apps. PKCE replaces client secrets for public clients, preventing authorization code interception.
sequenceDiagram
participant App as App (SPA / Mobile / CLI)
participant Browser as Browser
participant Server as AuthGate Server
App->>App: Generate code_verifier + code_challenge (S256)
App->>Browser: Redirect to /oauth/authorize?code_challenge=...&state=...
Browser->>Server: GET /oauth/authorize (Login + Consent page)
Server-->>Browser: Render login / consent UI
Browser->>Server: POST /oauth/authorize (user approves)
Server->>Browser: 302 redirect_uri?code=XXXXX&state=...
Browser->>App: Authorization code delivered to callback
App->>App: Verify state parameter (CSRF check)
App->>Server: POST /oauth/token (code + code_verifier + client_id)
Server->>Server: Verify SHA256(code_verifier) == code_challenge
Server-->>App: access_token + refresh_token + expires_in
Security properties:
- PKCE (RFC 7636) — prevents authorization code interception attacks
stateparameter — CSRF protection on the callback- No client secret required for public clients (SPA, mobile, CLI)
- Callback server binds to
127.0.0.1only (CLI mode)
Designed for CLI tools, IoT devices, and headless environments where a browser is not available.
sequenceDiagram
participant CLI as CLI / Device
participant Server as AuthGate Server
participant User as User (Browser on another device)
CLI->>Server: POST /oauth/device/code (client_id + scope)
Server-->>CLI: device_code + user_code + verification_uri + expires_in + interval
Note over CLI: Display to user:<br/>"Visit verification_uri<br/>and enter user_code"
User->>Server: GET /device (enter user_code)
Server-->>User: Render code entry page (login required)
User->>Server: POST /device/verify (user_code)
Server-->>User: ✅ Authorization approved
loop Poll every interval seconds (default 5 s)
CLI->>Server: POST /oauth/token (device_code + grant_type)
alt still waiting
Server-->>CLI: error: authorization_pending
else user approved
Server-->>CLI: access_token + refresh_token + expires_in
else slow down
Server-->>CLI: error: slow_down (increase interval)
else expired / denied
Server-->>CLI: error: expired_token / access_denied
end
end
Polling behavior:
- Respects server-specified interval (default 5 s)
- Exponential backoff on
slow_downresponse (up to 60 s, per RFC 8628) - Device codes expire after 30 minutes
sequenceDiagram
participant Client as Client (CLI / Web / IoT)
participant Router as Gin Router + Middleware
participant Handler as Handlers
participant Service as Services
participant Store as Store (GORM)
participant DB as SQLite / PostgreSQL
participant Ext as External Auth (optional)
Client->>Router: HTTP Request
Router->>Router: Rate limiting, CSRF, Session check
Router->>Handler: Route matched
Handler->>Service: Business logic
Service->>Store: Data access
Store->>DB: Query / Write
DB-->>Store: Result
Store-->>Service: Data
opt External auth provider (GitHub / Microsoft / Gitea / HTTP API)
Service->>Ext: Authenticate or validate
Ext-->>Service: User info / Token
end
Service-->>Handler: Result
Handler-->>Client: HTTP Response
One binary, two flows, zero configuration — mirrors the strategy used by GitHub CLI, Azure CLI, and Google Cloud SDK.
sequenceDiagram
participant User as User
participant CLI as go-authgate/cli
participant Server as AuthGate Server
User->>CLI: Launch CLI
CLI->>CLI: Detect environment
alt Developer Workstation (browser available)
CLI->>Server: Auth Code + PKCE Flow
Server-->>CLI: access_token + refresh_token
else SSH / Headless (no display)
CLI->>Server: Device Code Flow
Server-->>CLI: access_token + refresh_token
end
CLI-->>User: Authenticated
No keyboard, no embedded secret — the user authorizes from any nearby device.
sequenceDiagram
participant TV as Smart TV / IoT
participant Server as AuthGate Server
participant Phone as User (Phone / Laptop)
TV->>Server: POST /oauth/device/code
Server-->>TV: user_code + verification_uri
Note over TV: Display short URL + user_code<br/>(or QR code)
Phone->>Server: Visit URL, enter user_code
Server-->>Phone: ✅ Approved
TV->>Server: Poll /oauth/token
Server-->>TV: access_token + refresh_token
Server-side backend holds the client secret; it is never exposed to the browser.
sequenceDiagram
participant User as User (Browser)
participant App as Backend Server
participant Server as AuthGate Server
User->>App: ① Visit app
App->>User: ② Redirect to /oauth/authorize
User->>Server: ③ Login + Consent
Server->>User: ④ 302 redirect_uri?code=XXXXX
User->>App: ⑤ code delivered to callback
App->>Server: ⑥ POST /oauth/token (code + client_secret)
Server-->>App: access_token + refresh_token
No client secret on device — PKCE binds the token exchange to the original requestor.
sequenceDiagram
participant App as SPA / Mobile App
participant Browser as Browser
participant Server as AuthGate Server
App->>App: Generate code_verifier + code_challenge (S256)
App->>Browser: Redirect to /oauth/authorize?code_challenge=...&method=S256
Browser->>Server: Login + Consent
Server->>Browser: 302 redirect_uri?code=XXXXX&state=...
Browser->>App: code delivered to callback
App->>App: Verify state (CSRF check)
App->>Server: POST /oauth/token (code + code_verifier)
Server->>Server: Verify SHA256(code_verifier) == code_challenge
Server-->>App: access_token + refresh_token
| Endpoint | Method | Purpose |
|---|---|---|
/oauth/device/code |
POST | Request device + user codes |
/oauth/authorize |
GET / POST | Authorization consent page |
/oauth/token |
POST | Exchange code / device_code / refresh_token |
/oauth/tokeninfo |
GET | Verify token validity |
/oauth/revoke |
POST | Revoke tokens (RFC 7009) |
/device |
GET | User code entry page (browser) |
/account/sessions |
GET | Manage active sessions |
/account/authorizations |
GET | Manage per-app consent grants |