Welcome to the Atlas Rig integration guide. This document explains how third-party and internal applications can connect to the Atlas Rig system to authenticate users via the Authorization Code Flow with PKCE.
Atlas Rig Auth acts as a central Identity Provider (IdP) following OAuth 2.0 and OpenID Connect (OIDC) standards.
Base URL: https://auth.adolfrey.com
| Endpoint | Path | Method | Description |
|---|---|---|---|
| Discovery | /api/.well-known/openid-configuration |
GET | Returns the OIDC metadata document. |
| Authorization | /api/authorize |
GET | Initiates the login flow and redirects the user to the login UI. |
| Token | /api/token |
POST | Exchanges an authorization code for an ID token, access token, and refresh token. |
| UserInfo | /api/userinfo |
GET/POST | Returns profile information about the authenticated user. |
| JWKS | /.well-known/jwks.json |
GET | JSON Web Key Set used to verify the signature of JWTs. |
The easiest way to integrate is by using a standard OIDC library, which handles the complex tasks of state management, PKCE generation, and token rotation automatically.
For React/TypeScript applications, we recommend oidc-client-ts.
npm install oidc-client-tsimport { UserManager, WebStorageStateStore } from 'oidc-client-ts';
const userManager = new UserManager({
authority: 'https://auth.adolfrey.com/api', // Discovery URL base
client_id: 'your-client-id',
redirect_uri: window.location.origin + '/auth/callback',
popup_redirect_uri: window.location.origin + '/auth/popup-callback',
response_type: 'code',
scope: 'openid profile email', // Add other scopes as needed
userStore: new WebStorageStateStore({ store: window.sessionStorage }),
monitorSession: false // Turn off if iframe session monitoring isn't fully supported
});This will redirect the user entirely to the auth domain and back.
const login = () => {
userManager.signinRedirect();
};On the route corresponding to your redirect_uri (e.g., /auth/callback):
const handleCallback = async () => {
try {
const user = await userManager.signinRedirectCallback();
console.log("Logged in user:", user);
// Redirect to dashboard
} catch (e) {
console.error("Login failed", e);
}
};Alternatively, you can open a popup window for login, keeping your main application state intact.
const loginWithPopup = async () => {
try {
const user = await userManager.signinPopup();
console.log("Logged in user:", user);
} catch (e) {
console.error("Popup login failed", e);
}
};On the route corresponding to your popup_redirect_uri (e.g., /auth/popup-callback):
// The library handles this automatically when called on the popup page
userManager.signinPopupCallback();For the most streamlined experience in React/TypeScript applications, use our official wrapper library which provides a useAuth hook and simplified state management.
import { AuthProvider } from 'ar-auth-client';
const config = {
authority: 'https://auth.adolfrey.com',
clientId: 'my-app-id',
redirectUri: window.location.origin + '/callback',
scope: 'openid profile email'
};
root.render(
<AuthProvider config={config}>
<App />
</AuthProvider>
);import { useAuth } from 'ar-auth-client';
export const Navbar = () => {
const { user, login, logout, loginState, isLoading } = useAuth();
if (isLoading) return <span>...</span>;
return user ? (
<div>
<span>{user.name}</span>
<button onClick={logout}>Logout</button>
</div>
) : (
<button onClick={() => login({ state: { from: 'navbar' } })}>Login</button>
);
};The login function resolves with a result object (for popup flows) containing the OIDC state, the user, and the tokens. For redirect flows, the state is available via the loginState property in the context.
const handleLogin = async () => {
const result = await login({
state: { returnUrl: '/dashboard' }
});
if (result) {
console.log("Flow state:", result.state);
console.log("ID Token:", result.idToken);
}
};If you cannot use a library, you must implement the Authorization Code Flow with PKCE manually.
Before redirecting the user, cryptographically generate a high-entropy code_verifier and use SHA-256 to hash it into a code_challenge.
// Pseudo-code for Browser APIs
const verifier = generateRandomString(43); // Ensure it's between 43-128 chars
const challenge = base64URLEncode(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier)));
sessionStorage.setItem('pkce_verifier', verifier); // Store temporarilyConstruct the URL and redirect the user's browser.
Endpoint: GET https://auth.adolfrey.com/api/authorize
Parameters:
client_id: Your registered Client ID.redirect_uri: Whitelisted redirect URI for your app.response_type: Must becode.state: Random string to prevent CSRF attacks. Verify this on callback.code_challenge: The hashed string generated in Step 1.code_challenge_method: Must beS256.scope: E.g.,openid profile. For cross-app access, useapi://{target-client-id}/{scope}.
Example URL with Cross-App Scope:
https://auth.adolfrey.com/api/authorize?client_id=my-app&redirect_uri=https://myapp.com/callback&response_type=code&state=xyz123&code_challenge=AbCdEf1234&code_challenge_method=S256&scope=openid%20profile%20api://inventory-service/read:stock
The user will be redirected back to your redirect_uri with the parameters:
?code=AUTH_CODE_HERE&state=xyz123
Verify that the state matches the one you sent in Step 2. If it does, extract the code.
Make a POST request to the Token endpoint, passing the code and the original code_verifier.
Endpoint: POST https://auth.adolfrey.com/api/token
Content-Type: application/x-www-form-urlencoded or application/json
Payload:
grant_type:authorization_codeclient_id: Your Client ID.redirect_uri: Must match the redirect URI from Step 2.code: The code extracted from the URL.code_verifier: The original random string you stored in Step 1.client_secret: (Only required if your application is a backend/confidential client).
Response:
{
"access_token": "eyJhb...",
"refresh_token": "dj9a...",
"token_type": "Bearer",
"expires_in": 300,
"scope": "openid profile api://inventory-service/read:stock"
}The access_token is a Signed JWT. Use it in the Authorization: Bearer <token> header of subsequent API requests. The Backend will validate the signature against the public key found at /.well-known/jwks.json.
Atlas Rig supports Cross-App Trust, allowing one application (App A) to request access to resources/scopes owned by another application (App B).
Cross-app scopes must use the following URI format:
api://{target-client-id}/{scope-name}
Example: api://inventory-service/read:stock
For a cross-app scope to be granted in an access token, the following conditions must be met:
- Trust Relationship: An administrator must create a "Cross-App Trust" record in the Admin UI authorizing
App A(Requesting Client) to request a specific scope fromApp B(Target Client). - Authorization Rule:
- For User Sessions: The user must have been manually assigned the scope for
App B. - For App Principal Sessions: The scope must be marked as Client-Only (App Principal).
- OR, the scope must be marked as Admin Approved (Auto-grant) for
App B(applies to user sessions).
- For User Sessions: The user must have been manually assigned the scope for
Applications can request tokens directly using their own credentials to access trusted cross-app scopes.
Token Request:
POST https://auth.adolfrey.com/api/token
Payload:
grant_type:client_credentialsclient_id:app-aclient_secret:secret-ascope:api://app-b/read:data
Add the qualified scope to your authorization or token request alongside standard OIDC scopes.
const userManager = new UserManager({
// ... other config
scope: 'openid profile email api://inventory-service/read:stock'
});https://auth.adolfrey.com/api/authorize?client_id=my-app&...&scope=openid%20profile%20api://inventory-service/read:stock
When granted, these scopes appear in the scope claim of the access token and are also mapped to the role claim to simplify integration with standard authorization middleware.
{
"sub": "user_123",
"client_id": "my-app",
"scope": "openid profile api://inventory-service/read:stock",
"role": ["api://inventory-service/read:stock"]
}