Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,117 @@ bootstrapApplication(AppComponent, {
});
```

## Online Access (Online Refresh Tokens)

> [!NOTE]
> Online Access (Online Refresh Tokens) support via SDKs is currently in Early Access. To request access to this feature, contact your Auth0 representative.

**Online Refresh Tokens (ORTs)** are a refresh token type bound to the lifetime of the user's Auth0 session, unlike rotating offline refresh tokens. An ORT is:

- **Session-bound** — valid only while the underlying Auth0 session is active. When the session ends (logout, idle/absolute session expiry, or an admin revoking the session), the ORT stops working.
- **Non-rotating** — refreshing an access token with an ORT does **not** issue a new refresh token; the same ORT is reused for the life of the session.

Read more about [Online Refresh Tokens](https://auth0.com/docs/secure/tokens/refresh-tokens/online-refresh-tokens/online-refresh-tokens) to decide whether this fits your application.

> [!IMPORTANT]
> Online access requires DPoP. Sender-constraining the token via [DPoP](#device-bound-tokens-with-dpop) is mandatory because the ORT is non-rotating — binding it to the browser's key pair is what mitigates token replay if it is exfiltrated. You must set `useDpop: true` explicitly; the SDK does not enable it for you.
>
> This also requires the `online_refresh_tokens` flag to be enabled for your Auth0 tenant, and `allow_online_access` to be enabled on the resource server you log in with (on by default).

### Enabling Online Access

Set `refreshTokenMode` to `RefreshTokenMode.Online` together with `useRefreshTokens: true` and `useDpop: true`:

```ts
import { NgModule } from '@angular/core';
import { AuthModule, RefreshTokenMode } from '@auth0/auth0-angular';

@NgModule({
imports: [
AuthModule.forRoot({
domain: 'YOUR_AUTH0_DOMAIN',
clientId: 'YOUR_AUTH0_CLIENT_ID',
useRefreshTokens: true, // required — online access is a refresh-token grant
refreshTokenMode: RefreshTokenMode.Online, // 👈
useDpop: true, // required — DPoP is mandatory for online access
authorizationParams: {
redirect_uri: window.location.origin,
},
}),
],
})
export class AppModule {}
```

Or with standalone components via `provideAuth0`:

```ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAuth0, RefreshTokenMode } from '@auth0/auth0-angular';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
providers: [
provideAuth0({
domain: 'YOUR_AUTH0_DOMAIN',
clientId: 'YOUR_AUTH0_CLIENT_ID',
useRefreshTokens: true,
refreshTokenMode: RefreshTokenMode.Online,
useDpop: true,
authorizationParams: {
redirect_uri: window.location.origin,
},
}),
],
});
```

`refreshTokenMode` defaults to `RefreshTokenMode.Offline` (rotating refresh tokens). Enabling online mode causes the underlying SDK to:

- Send the `online_access` scope to the authorization server (instead of `offline_access`) — you do **not** need to add it to `authorizationParams.scope` yourself.
- Route token renewal through the `refresh_token` grant against `/oauth/token` rather than a hidden iframe.
- Store the non-rotating ORT in the existing cache and reuse it on every refresh, never replacing it.

### Configuration validation

If `refreshTokenMode: RefreshTokenMode.Online` is set without `useRefreshTokens: true` and `useDpop: true`, the underlying `Auth0Client` constructor throws an `InvalidConfigurationError`:

```ts
import { InvalidConfigurationError } from '@auth0/auth0-angular';

try {
// AuthModule.forRoot / provideAuth0 constructs the client during app bootstrap.
// Wrap it, or validate your configuration up front, to catch misconfiguration.
} catch (e) {
if (e instanceof InvalidConfigurationError) {
console.error(e.error_description); // includes the suggested fix
}
}
```

### Using Online Access with MRRT

Online access is compatible with Multi-Resource Refresh Tokens (MRRT): a single ORT can be exchanged for access tokens across the audiences allowed by your refresh-token policies. The ORT remains non-rotating throughout.

```ts
AuthModule.forRoot({
domain: 'YOUR_AUTH0_DOMAIN',
clientId: 'YOUR_AUTH0_CLIENT_ID',
useRefreshTokens: true,
refreshTokenMode: RefreshTokenMode.Online,
useDpop: true,
useMrrt: true, // 👈
authorizationParams: {
redirect_uri: window.location.origin,
audience: 'https://api.example.com',
},
});
```

> [!IMPORTANT]
> In order for MRRT to work, it needs a previous configuration setting the refresh token policies.
> Visit [configure and implement MRRT](https://auth0.com/docs/secure/tokens/refresh-tokens/multi-resource-refresh-token/configure-and-implement-multi-resource-refresh-token).

## Standalone components and a more functional approach

As of Angular 15, the Angular team is putting standalone components, as well as a more functional approach, in favor of the traditional use of NgModules and class-based approach.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@angular/platform-browser": "^19.2.21",
"@angular/platform-browser-dynamic": "^19.2.21",
"@angular/router": "^19.2.21",
"@auth0/auth0-spa-js": "^2.21.0",
"@auth0/auth0-spa-js": "^2.23.0",
"rxjs": "^6.6.7",
"tslib": "^2.8.1",
"zone.js": "~0.15.1"
Expand Down
3 changes: 3 additions & 0 deletions projects/auth0-angular/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export {
AuthenticationError,
PopupCancelledError,
MissingRefreshTokenError,
MissingScopesError,
InvalidConfigurationError,
ConnectError,
Fetcher,
FetcherConfig,
Expand All @@ -44,6 +46,7 @@ export {
CustomTokenExchangeOptions,
TokenEndpointResponse,
ResponseType,
RefreshTokenMode,
MfaError,
MfaListAuthenticatorsError,
MfaEnrollmentError,
Expand Down
Loading