# FAQ (Frequently Asked Questions) ## Why is the Bearer token not injected when `allowMultiTabLogin: true`? When `allowMultiTabLogin: true` is set in `OidcTrustedDomains.js`, each browser tab stores its own access token in the service worker, keyed by a unique tab identifier (e.g. `default#tabId=8d903cd1-...`). The service worker identifies which tab's token to inject by reading a tab-specific placeholder value from the incoming request's `Authorization` header. This placeholder is automatically set by the **OIDC fetch** wrapper (`useOidcFetch` / `withOidcFetch` in React, or `oidcClient.fetchWithTokens(fetch)` in vanilla JS). If you use a plain `fetch` call or a library like **axios** without configuring it to use the OIDC fetch, requests will arrive at the service worker with no `Authorization` header. The service worker has no way to determine which tab's token to use, so no token is injected and your API calls return 401 errors. **Solution**: always use the OIDC fetch wrapper for API requests when `allowMultiTabLogin: true`. ### React example ```javascript import { useOidcFetch } from '@axa-fr/react-oidc'; const MyComponent = () => { const { fetch } = useOidcFetch(); const callApi = async () => { const res = await fetch('https://my-api.example.com/data'); return res.json(); }; // ... }; ``` ### Vanilla JS example ```javascript const oidcFetch = oidcClient.fetchWithTokens(fetch); const res = await oidcFetch('https://my-api.example.com/data'); ``` ### Using axios Axios can be configured to use a custom fetch adapter or you can wrap axios calls to use the OIDC fetch instead: ```javascript import { useOidcFetch } from '@axa-fr/react-oidc'; const MyComponent = () => { const { fetch } = useOidcFetch(); const callApi = async () => { // Use the OIDC fetch directly instead of axios when allowMultiTabLogin is true const res = await fetch('https://my-api.example.com/data', { method: 'GET', headers: { 'Content-Type': 'application/json' }, }); return res.json(); }; // ... }; ``` ## Condition to make silent signing work Third-party cookies are blocked by default on Safari and will be blocked on all browsers soon. Today, silent signing works on Safari only if the OIDC provider and the client application are on the same domain. To guarantee that silent signing functions on all browsers, place your OIDC provider on the same domain as your client application. Example domains that work: https://oidc-provider.axa.fr https://my-app.axa.fr Silent signing uses cookies from your OIDC provider to restore the session and retrieve tokens. It opens an IFrame in the background, directed to a specific page on your OIDC provider. ## Condition to make Single Logout to work The same domain constraint for "silent signing" applies to Single Logout. Single Logout allows you to disconnect from multiple OIDC Client sessions in one action, even if you are connected to different applications. ## Condition to make Monitor Session to work Same domain constraint for "silent signing" applies to "monitorSession". Monitor session notifies you when your session expires or when you are disconnected from your OIDC provider. ## Does Service Worker is mandatory ? Service Worker can be disable. You can use classic mode without Service Worker. Just comment "service_worker_relative_url" like bellow: ```javascript export const configuration = { client_id: 'interactive.public.short', redirect_uri: window.location.origin + '/#/authentication/callback', silent_redirect_uri: window.location.origin + '/#/authentication/silent-callback', scope: 'openid profile email api offline_access', authority: 'https://demo.duendesoftware.com', // service_worker_relative_url: '/OidcServiceWorker.js', service_worker_only: false, }; ``` If your Service Worker file is already registered on your browser, your need to unregister it. For example from chrome dev tool. ## Two tabs race condition during login with localStorage When `storage: localStorage` is used without a service worker and two tabs initiate the login flow at the same time, they write the authorization state (`state`, `code_verifier`, `nonce`, login params) to the same `localStorage` keys. Each tab can overwrite the other's values, causing the callback in one tab to fail with a state mismatch error. The recommended fix is to use the `login_state_storage` option to store authorization flow state in `sessionStorage` (which is isolated per tab) while keeping tokens in `localStorage` so they persist across tabs: ```javascript export const configuration = { client_id: 'interactive.public.short', redirect_uri: window.location.origin + '/authentication/callback', scope: 'openid profile email api offline_access', authority: 'https://demo.duendesoftware.com', service_worker_only: false, storage: localStorage, // tokens persist across tabs login_state_storage: sessionStorage, // authorization state is isolated per tab }; ``` This option has no effect when using a service worker, which already handles multi-tab isolation internally. ## Tokens are always refreshed in background every seconds The @axa-fr/oidc-client automatically refreshes tokens in the background. It refreshes tokens before expiration to maintain valid tokens at all times. If your token session lifetime is too short, frequent refreshes will occur. Token refreshing starts 120 seconds before expiration. Setting a session validity longer than 3 minutes is advisable. By default, @axa-fr/oidc-client chooses the shorter lifetime between access_token and id_token. Use the "token_renew_mode" option to change this behavior. - **token_renew_mode**: String, // Optional, update tokens based on the selected token(s) lifetime: "access_token_or_id_token_invalid" (default), "access_token_invalid", "id_token_invalid" ## window.crypto.subtle is unavailable over HTTP The library doesn't work over HTTP. Use HTTPS. Setting up HTTPS is relatively easy, even for local development. https://github.com/AxaFrance/react-oidc/issues/1028 ## Why OIDC at Client side instead of BFF (Backend for Frontend) ? We recommend @axa-fr/oidc-client for these reasons: Secure by default: Uses Service Worker. Server-side OIDC can be insecure if poorly configured. Client-side reuses server-side configurations, usually set by experts. Fine-grained scope control: Easier to tailor token scope and lifetime for specific scenarios when using client-side OIDC. No server needed: Client-side OIDC eliminates the need for a separate authentication server, saving money. Quick time-to-market: Start with client-side OIDC, migrate to server-side if needed. Both are compatible.
@axa-fr/oidc-client is one of the securest way to Authenticate.
Service Worker lifetime drawback.
@axa-fr/oidc-client is the simplest and cheapest.