Lösning på OIDC tyst tokenförnyelse, CSP Iframe-problem & API-anropsloopar i React

Creative Software logomark
Iyani Kalupahana
January 9, 2026

Om du använder OpenID Connect (OIDC) med ett React-frontend och har kämpat med tyst tokenförnyelse, utgångna tokens som utlöser oändliga API-anrop, eller Content Security Policy (CSP) som blockerar iframes, är den här artikeln för dig.

Efter att ha brottats med alla dessa problem lyckades jag äntligen bygga en stabil och säker lösning, och här är en genomgång av resan och hur du kan tillämpa den i din egen app.

Problemen jag stötte på när jag använde OpenID Connect (OIDC) med ett React-frontend

1. Tyst tokenförnyelse fungerade inte

OIDC erbjuder ett sätt att tyst förnya åtkomsttokens via en iframe, men denna metod misslyckas med applikationer som har en strikt CSP, särskilt med frame-ancestors ‘none’.

Som en konsekvens går tokens ut obemärkt och användare loggas ut utan någon avisering.

2. Oändliga API-slingor efter att token gått ut

Utgångna tokens upptäcktes inte tillräckligt tidigt. När frontend gjorde API-anrop med en utgången token svarade servern med 401:or och vår interceptor-logik försökte göra om samma förfrågan om och om igen. Detta ledde till en oändlig slinga av misslyckade förfrågningar, försämrad prestanda och förvirrade användare.

3. Förlorad omdirigeringsväg efter inloggning

Efter att ha omdirigerats till inloggningssidan på grund av en utgången token, återfördes användarna inte till den ursprungliga sidan de befann sig på.

Den slutgiltiga lösningen för problem som uppstår vid användning av OIDC

För att åtgärda dessa problem gjorde jag följande strukturella ändringar:

  • Problem: Implementerad tyst förnyelse fungerar inte
    Lösning: Lade till en dedikerad silentrenew.html -sida och åtgärdade CSP-problemet
  • Problem: API-slinga vid tokenutgång
    Lösning: Flyttade tokenvalidering utanför interceptorer
  • Problem: CSP-iframe blockerad
    Lösning: Uppdaterade serverns CSP-policy för att tillåta 'self' för iframes
  • Problem: Förlorad omdirigeringsväg
    Lösning: Använde state parameter eller redirectTo query i inloggningsflödet

Viktiga lösningar på OIDC-problem förklaras

1. silentrenew.html:

Tysta tokenförnyelser sker i en dold iframe. För detta behöver du en statisk HTML-fil som exekverar den tysta callbacken:

<!-- silentrenew.html -->
<script src="https://unpkg.com/oidc-client-ts/dist/umd/oidc-client-ts.min.js"></script>
<script>
  new Oidc.UserManager().signinSilentCallback();
</script>

Se till att lägga till URL:en för denna sida till din identitetsleverantörs omdirigerings-URI:er och uppdatera din CSP:

Omdirigerings-URI:er:

https://your-app-url/login-redirect
https://your-app-url/silentrenew.html

Omdirigerings-URI efter utloggning:

https://your-app-url/login

Aktivera offlineåtkomst:

AllowOfflineAccess: true

Konfigurera Content Security Policy (CSP) i identitetsserverprojektet:

Content-Security-Policy: frame-ancestors 'self'

2. Validera tokens innan API-anrop görs

Ett vanligt misstag är att utföra tokenförnyelse inuti dina axios förfrågnings- eller svarsinterceptorer.

Även om det verkar bekvämt, orsakar detta stora problem:

  • Tokenförnyelse kan utlösas parallellt av flera förfrågningar.
  • Utgångna tokens kan fortfarande skickas innan förnyelsen är klar.
  • 401-svar kan utlösa oändliga omförsöksslingor.

Lösning:
Flytta logiken för tokenvalidering utanför interceptorn, till en centraliserad plats som körs innan något API-anrop görs.

function getValidAccessToken() {
  const user = userManager.configuration.getUser() //Calls to get the new token
  if (!user || user.expired) {
    return null
  }
  return user.access_token
}

const token = await getValidAccessToken()
if (!token) {
  redirectToLoginWithState()
} else {
  axios.defaults.headers.Authorization = `Bearer ${token}`
}

Varför jag tog bort tokenlogik från Axios-interceptorer

Interceptors är bra men inte för tokenförnyelse.

Före:

axios.interceptors.response.use(async (response) => {
  if (response.status === 401) {
    await renewToken()
    return axios(response.config) // ❌ Risk of loops
  }
})

Problem:

  • Om många API-anrop görs samtidigt med en utgången token, utlöser alla renewToken().
  • Initiala förfrågningar görs igen innan den nya token blir tillgänglig.

3. Hantera utgång med händelser

Livscykelhändelser som addUserLoaded och addSilentRenewError tillhandahålls av OIDC-klienten, vilket gör dem användbara för uppgifter som tokenunderhåll.

import { User, UserManager, UserManagerSettings, WebStorageStateStore } from 'oidc-client-ts'

const configuration = new UserManager(config)

configuration.events.addUserLoaded(user => {
  storeTokenGlobally(user.access_token, user.expires_at)
})

configuration.events.addSilentRenewError(() => {
  // Fallback: maybe trigger login redirect after some time
})

4. Hantera inloggningsomdirigeringar på ett snyggt sätt

När jag omdirigerar till inloggning bevarar jag nu användarens nuvarande rutt med hjälp av query-parametrar eller state:

const targetPath = window.location.pathname + window.location.search
const loginUrl = `/login?redirectTo=${encodeURIComponent(targetPath)}`
window.location.replace(loginUrl)

Efter lyckad inloggning läser appen redirectTo -värdet och skickar tillbaka användaren dit de var.

Bonus: Miljöinställningar

Se till att inkludera offline_access -scope om du vill använda refresh tokens eller utökade tysta förnyelsefunktioner:

REACT_APP_IDENTITY_SERVER_SCOPE='openid offline_access'

Se även till att ha följande standardinställningar.

const config: UserManagerSettings = {
  authority: appConfig.identityServer.authority,
  client_id: appConfig.identityServer.client_id,
  redirect_uri: `${window.location.origin}/login-redirect`,
  client_secret: appConfig.identityServer.clientSecret,
  scope: appConfig.identityServer.scope,
  response_type: 'code',
  post_logout_redirect_uri: `${window.location.origin}/login`,
  automaticSilentRenew: true,
  silent_redirect_uri: `${window.location.origin}/silentrenew.html`,
  accessTokenExpiringNotificationTimeInSeconds: 120,
  includeIdTokenInSilentRenew: true,
  revokeTokensOnSignout: false,
}


Resultat

Med dessa ändringar:

✅ Tyst tokenförnyelse fungerar konsekvent
✅ Oändliga API-loopar elimineras
✅ Omdirigeringar hanteras smidigt
✅ CSP respekteras och är säkert

Share this post
Creative Software logomark
Iyani Kalupahana
January 9, 2026
5 min read