Skip to content

OAuth: Redirect & Silent Auth

Overview

The redirect flow navigates the user to the Authrim authorization endpoint for authentication. After completing login, the user is redirected back to your application with an authorization code. This is the standard OAuth 2.0 Authorization Code Flow with PKCE.

Silent authentication checks for an existing IdP session without user interaction, using a hidden iframe.

Both features require enableOAuth: true.

Redirect Flow

Step 1: Build Authorization URL and Redirect

const auth = await createAuthrim({
issuer: 'https://auth.example.com',
clientId: 'my-app',
enableOAuth: true,
});
const result = await auth.oauth.buildAuthorizationUrl({
redirectUri: 'https://myapp.com/callback',
scopes: ['openid', 'profile', 'email'],
});
// Redirect to IdP
window.location.href = result.url;

Step 2: Handle Callback

In your callback page (/callback):

const auth = await createAuthrim({
issuer: 'https://auth.example.com',
clientId: 'my-app',
enableOAuth: true,
});
const { data, error } = await auth.oauth.handleCallback(window.location.href);
if (error) {
console.error('OAuth callback failed:', error.message);
return;
}
console.log('Access Token:', data.accessToken);
console.log('ID Token:', data.idToken);
// Redirect to application
window.location.href = '/dashboard';

Authorization URL Options

interface OAuthBuildAuthorizationUrlOptions {
/** Redirect URI (must be registered in Admin panel) */
redirectUri: string;
/** OAuth scopes */
scopes?: string[];
/** Authentication prompt behavior */
prompt?: 'none' | 'login' | 'consent' | 'select_account';
/** Pre-fill the login hint (e.g., email) */
loginHint?: string;
}
Prompt ValueBehavior
noneNo UI — fail if not already authenticated (used by silent auth)
loginForce re-authentication even if session exists
consentForce consent screen
select_accountShow account picker

Silent Authentication

Silent auth checks if the user has an active IdP session using a hidden iframe. If the session exists, tokens are returned without user interaction.

Iframe-Based Silent Auth

const { data, error } = await auth.oauth.silentAuth.check({
redirectUri: 'https://myapp.com/silent-callback',
timeoutMs: 5000, // Timeout after 5 seconds (default)
});
if (error) {
// No active session or silent auth failed
console.log('Silent auth failed:', error.message);
// Show login button
} else {
// User is authenticated
console.log('Access Token:', data.accessToken);
}

Silent Auth Flow

sequenceDiagram
    participant App as Your App
    participant Iframe as Hidden Iframe
    participant IdP as Authrim IdP

    App->>Iframe: Load auth URL (prompt=none)
    Iframe->>IdP: Authorization request
    alt IdP has active session
        IdP->>Iframe: Redirect with auth code
        Iframe->>App: postMessage(code)
        App->>IdP: Exchange code for tokens
        IdP->>App: Token response
    else No session
        IdP->>Iframe: Redirect with error=login_required
        Iframe->>App: postMessage(error)
        App->>App: Show login UI
    end

Combining Redirect + Silent Auth

A common pattern is to try silent auth first, then fall back to full redirect:

async function authenticate() {
// 1. Try silent auth
const { data, error } = await auth.oauth.silentAuth.check({
redirectUri: 'https://myapp.com/silent-callback',
timeoutMs: 5000,
});
if (!error) {
// Already authenticated
return data;
}
// 2. Fall back to redirect
const result = await auth.oauth.buildAuthorizationUrl({
redirectUri: 'https://myapp.com/callback',
scopes: ['openid', 'profile', 'email'],
});
window.location.href = result.url;
}

Silent Callback Page

For iframe-based silent auth, you need a lightweight callback page that only handles the iframe response:

silent-callback.html
<!DOCTYPE html>
<html>
<head><title>Silent Callback</title></head>
<body>
<script src="https://unpkg.com/@authrim/web@latest/dist/authrim-web.umd.global.js"></script>
<script>
// This page is loaded inside the hidden iframe.
// It passes the authorization code back to the parent window.
const params = new URLSearchParams(window.location.search);
window.parent.postMessage({
type: 'authorization_response',
response: Object.fromEntries(params),
}, window.location.origin);
</script>
</body>
</html>

Token Response

Both redirect and silent auth return the same token set:

interface OAuthTokenSet {
accessToken: string;
idToken?: string;
refreshToken?: string;
expiresAt: number; // Unix timestamp (seconds)
scope?: string;
}

Error Handling

Error CodeMeaningSuggested Action
AR005001OAuth callback errorCheck redirect URI configuration
AR005002Silent auth failedFall back to redirect or popup
AR005003No tokens receivedRetry or re-authenticate
const { data, error } = await auth.oauth.silentAuth.check({
redirectUri: 'https://myapp.com/silent-callback',
});
if (error) {
if (error.error === 'login_required') {
// No IdP session — show login button
showLoginButton();
} else {
// Other error — may want to retry or show error
console.error('Silent auth error:', error.message);
}
}

Next Steps