Hosted Login (Authorization Code + PKCE)
Auris Hosted Login is the recommended authentication method for web and mobile applications. It uses the OAuth2 Authorization Code flow with PKCE (Proof Key for Code Exchange, RFC 7636) to securely authenticate users without exposing client secrets in frontend code.
The hosted login page is fully managed by Auris and includes email/password authentication, social login, magic links, SMS OTP, and WebAuthn — all in a single flow. It respects your tenant branding configuration and supports multiple locales.
PKCE protection is enforced by default on all Auris authorization code flows. The plain challenge method is not permitted — only S256 is accepted.
How It Works
Generate PKCE parameters
Your application generates a cryptographically random code_verifier (43-128 characters) and derives a code_challenge from it using SHA-256 hashing: code_challenge = BASE64URL(SHA256(code_verifier)).
Redirect to the hosted login page
Your application redirects the user’s browser to the Auris authorization endpoint with the code_challenge, client_id, redirect_uri, state, and optionally scope, locale, login_hint, prompt, and screen_hint.
User authenticates
The user completes authentication on the Auris hosted page. If multi-factor authentication is required (by role, risk score, or tenant policy), the user is prompted for a second factor within the same hosted flow.
Receive the authorization code
On successful authentication, Auris redirects back to your redirect_uri with a short-lived authorization code and the original state parameter for CSRF validation.
Exchange the code for tokens
Your application sends the code and code_verifier (not the challenge) to the Auris token endpoint. Auris verifies that SHA256(code_verifier) matches the stored code_challenge and issues an access_token, refresh_token, and id_token.
Prerequisites
Before implementing hosted login, you need an application registered in the Auris Console:
- Go to Console → Applications and click Create Application
- Select the Web application type
- Under Allowed Callback URLs, add your
redirect_uri(e.g.,http://localhost:3000/callback) - Note your Client ID — you will use this in SDK configuration
- Do not use a Client Secret in frontend applications — PKCE replaces it
The redirect_uri used at runtime must exactly match one of the URIs registered in the Console. Auris rejects any redirect to an unregistered URI.
Implementation
React
import { AurisProvider, useAuris } from '@auris/react'
// Wrap your app root with AurisProvider
function App() {
return (
<AurisProvider
domain="auth.yourdomain.com"
clientId="your-client-id"
redirectUri="http://localhost:3000/callback"
>
<MyApp />
</AurisProvider>
)
}
// Login button component
function LoginButton() {
const { loginWithRedirect, logout, isAuthenticated, user, isLoading } = useAuris()
if (isLoading) return <p>Loading...</p>
if (isAuthenticated) {
return (
<div>
<p>Welcome, {user.name}</p>
<button onClick={() => logout({ returnTo: window.location.origin })}>
Log out
</button>
</div>
)
}
return <button onClick={loginWithRedirect}>Log in</button>
}
// Callback page — handles the redirect back from Auris
// Place this at your redirectUri path
import { useEffect } from 'react'
import { useAuris } from '@auris/react'
import { useNavigate } from 'react-router-dom'
function CallbackPage() {
const { handleRedirectCallback } = useAuris()
const navigate = useNavigate()
useEffect(() => {
handleRedirectCallback().then(() => {
navigate('/dashboard')
})
}, [])
return <p>Completing sign in...</p>
}
// AuthGuard — protect routes that require authentication
import { AuthGuard } from '@auris/react'
function ProtectedPage() {
return (
<AuthGuard>
<h1>This page requires authentication</h1>
</AuthGuard>
)
}Customization Options
The following query parameters can be passed to loginWithRedirect() to customize the hosted login experience:
| Parameter | Type | Description |
|---|---|---|
locale | string | Override the UI locale. Supported: en, it, de, fr, es |
login_hint | string | Pre-fill the email field with a known address |
prompt | login | none | login forces re-authentication. none returns an error if no active session |
screen_hint | signup | Opens the registration form directly instead of the login form |
connection | string | Force a specific SSO connection alias (bypasses login form) |
// Examples
await auris.loginWithRedirect({
login_hint: '[email protected]',
screen_hint: 'signup',
locale: 'it',
})
// Force re-authentication (ignore existing session)
await auris.loginWithRedirect({ prompt: 'login' })
// Silently check session (returns error if not authenticated)
await auris.loginWithRedirect({ prompt: 'none' })Token Handling
Access Token
The access token is a JWT signed with RS256 (or HS256 if configured). It contains standard claims (iss, sub, exp, iat) plus Auris-specific claims (roles, type, and any custom claims configured for the application).
Access tokens are valid for the duration configured on your tenant (default: 60 minutes).
Refresh Token
Refresh tokens are long-lived and allow obtaining new access tokens without user interaction. The SDK handles refresh automatically when autoRefresh: true is set.
// Manual token refresh
const newToken = await auris.refreshToken()
// Get access token — auto-refreshes if expired (when autoRefresh: true)
const accessToken = await auris.getAccessToken()Token Storage
By default, the SDK stores tokens in localStorage. For applications requiring higher security, you can use a cookie-based storage adapter:
import { AurisClient, CookieStorage } from '@auris/js'
const auris = new AurisClient({
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:3000/callback',
storage: new CookieStorage({ secure: true, sameSite: 'Lax' }),
})Security Considerations
PKCE S256 enforcement — Auris only accepts S256 as the code challenge method. The plain method is rejected at the authorization endpoint.
Redirect URI validation — The redirect_uri in the token exchange request must exactly match the URI registered in the Console. Partial matches and wildcards are not permitted.
State parameter — The SDK generates a cryptographically random state value for every authorization request and validates it on callback. This prevents CSRF attacks. Do not disable state validation.
Short-lived authorization codes — Authorization codes expire after 5 minutes and can only be used once. Any attempt to reuse a code results in a rejection and invalidation of any tokens already issued for that session.
Single-use codes — Code exchange is performed in an atomic transaction. If a code is exchanged twice (e.g., due to a double-submit), the second request is rejected and the issued tokens from the first exchange are revoked.
API Endpoints
/api/oauth/authorizeInitiates the authorization code flow. Validates client_id, redirect_uri, PKCE parameters, and creates an OAuth session. Returns the hosted login page URL.
/api/auth/tokenExchanges an authorization code for tokens (grant_type=authorization_code). Also handles client_credentials and refresh_token grant types.
/.well-known/openid-configurationOIDC Discovery document. Contains all endpoint URLs, supported grant types, signing algorithms, and claim types.
/.well-known/jwks.jsonJSON Web Key Set (JWKS). Contains public keys for verifying access token signatures. Cached for 1 hour.
Environment Variables
# Required for Next.js integration
NEXT_PUBLIC_AURIS_DOMAIN=auth.yourdomain.com
NEXT_PUBLIC_AURIS_CLIENT_ID=your-client-id
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Optional — for server-side JWT verification without network call
AURIS_JWKS_URL=https://auth.yourdomain.com/.well-known/jwks.jsonRelated Guides
- Social Login — Add Google, GitHub, and other providers
- Magic Links — Passwordless email authentication
- SMS OTP — Phone-based authentication and 2FA
- Passkeys / WebAuthn — Biometric and hardware key authentication
- Enterprise SSO — SAML 2.0 and OIDC federation
- M2M Client Credentials — Server-to-server authentication