Skip to Content
GuidesAuthenticationHosted Login (PKCE)

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:

  1. Go to ConsoleApplications and click Create Application
  2. Select the Web application type
  3. Under Allowed Callback URLs, add your redirect_uri (e.g., http://localhost:3000/callback)
  4. Note your Client ID — you will use this in SDK configuration
  5. 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

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:

ParameterTypeDescription
localestringOverride the UI locale. Supported: en, it, de, fr, es
login_hintstringPre-fill the email field with a known address
promptlogin | nonelogin forces re-authentication. none returns an error if no active session
screen_hintsignupOpens the registration form directly instead of the login form
connectionstringForce 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

POST/api/oauth/authorize

Initiates the authorization code flow. Validates client_id, redirect_uri, PKCE parameters, and creates an OAuth session. Returns the hosted login page URL.

POST/api/auth/token

Exchanges an authorization code for tokens (grant_type=authorization_code). Also handles client_credentials and refresh_token grant types.

GET/.well-known/openid-configuration

OIDC Discovery document. Contains all endpoint URLs, supported grant types, signing algorithms, and claim types.

GET/.well-known/jwks.json

JSON 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.json