Overview
Rhombus supports OAuth 2.0 with PKCE so you can build applications that sign users in with their existing Rhombus credentials. When a user clicks Sign in with Rhombus in your app, they’re redirected to the Rhombus Console to authenticate, then bounced back to your redirect URI with a short-lived authorization code. You exchange that code for an access token and call the Rhombus API on the user’s behalf. This is the same flow used by the official Rhombus CLI —rhombus login is a working reference implementation in Go that you can read end to end.
Use this guide to build:
- CLI tools that authenticate via browser login (like the Rhombus CLI itself)
- Web applications that let Rhombus users sign in to your service
- Admin dashboards and internal integrations for customers that manage many Rhombus orgs
- Desktop applications using a local-loopback redirect
What this guide isn’t. This is for third-party developers building apps that sign in Rhombus users. If you’re a Rhombus customer trying to configure SAML SSO for your employees (Okta, Azure AD, Google Workspace) or SCIM for user provisioning, see SAML SSO & SCIM Provisioning instead — that’s a separate surface from the OAuth flow described here.
How the flow works
The Rhombus OAuth surface spans three hosts. This is a common source of confusion — your app talks to all three at different stages of the flow.| Host | Role |
|---|---|
console.rhombussystems.com | Where the user signs in and approves your app |
auth-web.rhombussystems.com | Token exchange endpoint |
api2.rhombussystems.com | API calls made with the resulting access token |
Before you begin
Before you start, make sure you have:
- A Rhombus account with an API key (generated in the Rhombus Console under Settings → API Management)
- A redirect URI your app controls — a public HTTPS URL in production, or
http://localhost:<port>/callbackfor CLI and desktop apps - Basic familiarity with OAuth 2.0 Authorization Code flow and PKCE (RFC 7636)
Step 1: Register your application
Before you can start an OAuth flow, Rhombus needs to know about your application. Registration gives you aclientId and clientSecret pair.
There are two paths to a clientId, depending on where you are in your build:
Prototyping & development
Call the
submitApplication API directly with your existing API key. Fastest path to a working flow on localhost. Self-serve, immediate.Production & distribution
Apps that will be shipped to customers or accept logins from users outside your own organization must be reviewed by Rhombus. Contact your Rhombus representative or post in the Developer Community to start review.
Register with the API
POST /api/oauth/submitApplication returns a fresh clientId and clientSecret. Store the clientSecret securely — it is not retrievable later.
Step 2: Build the authorization URL
Rhombus uses PKCE (Proof Key for Code Exchange) to protect against authorization code interception. For every login attempt, generate:- A code verifier — a 43–128 character URL-safe random string
- A code challenge — the SHA-256 hash of the verifier, base64url-encoded (without padding)
- A state parameter — an unguessable random value used to prevent CSRF
codeVerifier and state alongside the user’s session (or, for CLI tools, in process memory) until the callback lands. You’ll need both.
Step 3: Handle the redirect callback
After the user authenticates, Rhombus redirects to yourredirectUri with query parameters:
On success, the callback carries:
| Parameter | Description |
|---|---|
code | Authorization code to exchange for an access token. Short-lived. |
state | The state value you sent — you must verify it matches. |
iss | (when configured) The issuer identifier (RFC 9207). If present, validate it matches the expected authorization server. |
error (e.g., access_denied) and error_description (human-readable detail) instead of code.
Step 4: Exchange the code for an access token
CallPOST https://auth-web.rhombussystems.com/oauth/token with the authorization code and your PKCE verifier. This is a standard OAuth 2.0 token request: send the parameters form-encoded (application/x-www-form-urlencoded), not as JSON, and authenticate your client with its clientId/clientSecret — either via HTTP Basic auth (client_secret_basic) or in the request body (client_secret_post, shown below). This is a different host from the main API — the /oauth/token endpoint lives on auth-web.rhombussystems.com.
Step 5: Call the Rhombus API
Use the access token with two headers on every Rhombus API call:x-auth-scheme: api-oauth-tokenx-auth-access-token: <accessToken>
api-token + x-auth-apikey) — OAuth access tokens use their own scheme identifier so Rhombus can apply OAuth-specific authorization.
If this call returns a list of users, your OAuth flow is working end to end. The user has authenticated, you have an access token, and you’re calling the API on their behalf.
Access token lifetime
Theexpires_in field on the token response tells you how long (in seconds) the access token is valid (typically one hour). When it expires, the Rhombus API will return an authentication error.
For long-lived access — background services, daemons, scheduled jobs, or any client that cannot re-prompt the user — mint a durable API key using the OAuth access token (see next section) rather than trying to maintain a refreshed OAuth session. This is the pattern the Rhombus CLI uses.
A
refresh_token is returned alongside the access token. You can exchange it for a new access token by calling the same /oauth/token endpoint with grant_type=refresh_token and refresh_token=<token> (plus your client authentication). For long-lived, non-interactive access — background services, daemons, scheduled jobs — prefer minting a durable API key (see below) rather than maintaining a refreshed OAuth session. This is the pattern the Rhombus CLI uses.Mint a long-lived API key
Once a user has signed in with OAuth, you can trade the short-lived access token for a permanent API key. This is whatrhombus login does so the CLI can continue making API calls after the browser session ends.
Call POST /api/integrations/org/submitApiTokenApplication with x-auth-scheme: api-oauth-token and x-auth-access-token: <accessToken>:
x-auth-scheme: api-token + x-auth-apikey headers — no further OAuth calls required. The CLI also supports a certificate-based (mTLS) variant of this flow for higher-security deployments; see cmd/login.go for the full implementation.
Working with partner accounts
“Sign in with Rhombus” issues user-scoped OAuth tokens — they act within the organization the user belongs to. The OAuth flow does not distinguish partner accounts, and the callback does not tell you whether the user is a partner. For partner/MSP scenarios — where you need to act across multiple client organizations — use the Partner API instead of OAuth. It relies on a partner-scoped API key:- Send
x-auth-scheme: partner-api-tokenwith your partner API key - Target a specific client organization by adding its UUID in the
x-auth-orgheader on each call
Reference implementation
The Rhombus CLI is a production reference for everything in this guide.cmd/login.go walks the full flow end to end: PKCE generation, local callback server, authorization URL construction, token exchange, mTLS API-key minting, and credential persistence.
If something in your implementation isn’t working, diff your behavior against the CLI — it’s the canonical example.
Troubleshooting
state mismatch on callback
state mismatch on callback
Your callback received a
state value different from what you sent. Verify you’re persisting the state you generated in Step 2 alongside the user’s session (or in memory for CLI tools) and comparing it on the callback. A persistent mismatch can indicate a CSRF attempt — abort the flow rather than retrying silently.Token exchange returns HTTP 400 or an `error` response
Token exchange returns HTTP 400 or an `error` response
Common causes:
redirect_urimismatch — theredirect_uriin the token exchange body must match exactly (including scheme, host, port, and path) theredirect_uriyou sent in Step 2 and the URI registered with your OAuth application.- Expired
code— authorization codes are short-lived (seconds, not minutes). Exchange them immediately on callback. code_verifierdoesn’t hash tocode_challenge— verify you’re using SHA-256 and base64url encoding without=padding on both the challenge generation and the verifier transmission.- Wrong content type or client auth — the token endpoint expects
application/x-www-form-urlencoded(not JSON), and yourclientId/clientSecretmust be sent via HTTP Basic auth or in the form body (client_secret_post). The token request does not use anx-auth-schemeheader.
API calls return 401 with a valid access token
API calls return 401 with a valid access token
Check the headers. OAuth access tokens use
x-auth-scheme: api-oauth-token and x-auth-access-token: <token>. Using x-auth-apikey (the API key header) with an OAuth access token will fail — those are different schemes with different header names.Redirect lands on the console login page again with no code
Redirect lands on the console login page again with no code
The
client_id you’re sending may be unrecognized. Double-check you’re using the clientId returned from submitApplication, not the application UUID from a different response. If you rotated applications, the old clientId is no longer valid.Next steps
Rhombus CLI
Read how the official CLI uses this flow end to end
API Reference
Browse all endpoints available once you have an access token
Rate Limits
Understand request limits before you ship
Developer Community
Request production OAuth review and ask questions