Vårt delingshjørne

Fra gammelt til nytt med Authorization Code Flow og BFF

Fra gammelt til nytt med Authorization Code Flow og BFF

Pål

Bøckmann

Utvikler

Utvikler

12. mars 2026

Utvikling

Sikkerhet er ofte et aspekt av systemutvkling som kan være forvirrende, vanskelig og skummelt å gjøre feil. Man vil jo tross alt ikke la noen uvedkommende få tilgang til systemet sitt. Noen ganger har man dog ikke noe valg, og nå nylig var vi nødt til å skrive om innloggingsflyten i et av våre interne systemer. Der vi tidligere hadde brukt en slags Frankensteins monster av implicit grant flow og noen andre småting fra andre flyter, flyttet vi over til cookie-basert BFF pattern med authorization code flow og proof key for code exchange (PKCE). I denne artikkelen skal vi fortelle litt om bakgrunnen for denne omskrivingen, hva de ulike flytene er og hvordan det gjøres i praksis i et .NET-prosjekt. 

Hvorfor valgte vi å skrive om? 

Vi har flere internprosjekter hos Alv som vi bruker både til kompetansebygging og til ting vi faktisk trenger, deriblant vårt eget timeføringssystem: Alvtime. Alvtime ble skrevet i Alvs spede begynnelse for nærmere 7 år siden og kan tidvis bære preg av å være skrevet som et hobbyprosjekt hvor målet er å lære seg noe ny teknologi og gjort på frivillig basis etter arbeidstid. Det ble i sin tid implementert autentisering og autorisering ved bruk av implicit grant flow som i senere tid har blitt frarådet av Microsoft å bruke og de anbefaler heller å gå over til authorization code flow. Vi har også valgt å ta det ett steg lenger å implementere BFF på toppen av dette. 

Hva er implicit flow, BFF pattern og authorization code flow? 

For å skjønne hvorfor BFF med authorization code flow er en mer sikker innloggingsflyt er det best å starte med å forklare hvordan implicit flow fungerer. Hovedkonseptet med implicit flow er at tokens (tilgangstoken eller ID token) returneres fra /authorize endepunktet til authorization server (f.eks. Azure e.l.) direkte til klienten. Problemet med denne flyten er at siden tokens flyter direkte mellom klienten og authorization server så er det sårbart for lekkasje, altså at noen kan få tak i tokens under transport. 

Authorization code flow løser dette ved at authorization serveren i stedet returnerer en kortlevd autoriseringskode fra /authorize. Denne koden i seg selv gir ingen tilgang, den må byttes inn i tokens ved å kalle /token-endepunktet med en klienthemmelighet. Siden klienthemmeligheten ikke kan oppbevares trygt i en nettleser, er det her BFF-mønsteret kommer inn. 

BFF, eller backend-for-frontend, er et serverside-mellomlag som sitter mellom nettleseren og authorization server. Se figur 1 nedenfor for å følge flyten som ser omtrent slik ut: brukeren klikker på "Logg inn" i GUI og blir sendt til /login-endepunktet i backend (1) som så tar kontakt med authorization server for innlogging (2) → authorization server redirecter tilbake til BFF med autoriseringskoden (3) → BFF tar imot koden og bytter den mot tokens (access, id og refresh token). BFF lagrer deretter tokens på serveren og utsteder en httpOnly-cookie til nettleseren (4). Cookien sendes automatisk med alle HTTP-forespørsler (5), men den kan ikke leses av JavaScript – tokens er altså aldri eksponert for klientsidekoden. Dersom API og BFF er forskjellige servere legger BFF på access token på alle forespørsler som sendes til APIet (6) som så returnerer responsen til BFF og videre til klienten (7 + 8). 

I Alvtime er BFF og Web API-et på samme server. BFF-laget håndterer all autentiseringslogikk og videreformidler API-kall internt i samme applikasjon, noe som forenkler arkitekturen betraktelig i kontrast til om man implementerer BFF serveren som sin egen applikasjon. Dette kan ha fordeler i form av isolering og enkapsulering av ansvarsområder, men vi har valgt å holde det enkelt i denne omgang. 

PKCE 

PKCE, uttalt "pixy", står for Proof Key for Code Exchange og ble opprinnelig laget for å sikre såkalte public clients, SPA-er og mobilapper som ikke kan oppbevare klienthemmeligheter trygt. Problemet PKCE løser er authorization code interception: hva skjer hvis noen klarer å snappe opp autoriseringskoden underveis? Med bare koden kan en angriper i prinsippet bytte den mot tokens. 

PKCE løser dette med en enkel men effektiv mekanisme. Klienten genererer en tilfeldig streng kalt code verifier og hasher den med SHA-256 til en code challenge. Når klienten starter innloggingsflyten, sendes code challenge med /authorize-forespørselen. Når autoriseringskoden siden skal byttes mot tokens, sendes den originale code verifier med og authorization server sjekker at code verifier matcher med code challenge den fikk tidligere. En stjålet autoriseringskode er dermed verdiløs uten den originale verifier-en. 

Selv om PKCE opprinnelig var ment for public clients, anbefales det nå for alle klienter, inkludert konfidensielle klienter som bruker klienthemmeligheter. Det er med andre ord ingen god grunn til å la være. 

Hvordan gjøres det i .NET? 

I et ASP.NET Core-prosjekt er det heldigvis ikke mye som skal til for å sette opp dette. Man kan bruke biblioteker fra leverandører som Duende, men det er nesten like greit å implementere det selv så man slipper vendor lock-in. Microsoft har innebygd støtte for OIDC og OAuth via et par NuGet-pakker: 

  • Microsoft.AspNetCore.Authentication.OpenIdConnect – håndterer OIDC/OAuth-flyten 

  • Microsoft.AspNetCore.Authentication.Cookies – for å holde på sesjonen med en kryptert cookie 

Oppsettet i Program.cs ser omtrent slik ut: 

var authentication = new OAuthOptions(); 
configuration.Bind("AzureAd", authentication); 
 
services 
    .AddAuthentication(options => 
    { 
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
        options.DefaultChallengeScheme = "AzureAd"; 
    }) 
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => 
    { 
        options.Cookie.Name = "AuthorizationCookie"; 
        options.Cookie.HttpOnly = true; 
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always; 
        options.Cookie.SameSite = SameSiteMode.Strict; 
 
        options.ExpireTimeSpan = TimeSpan.FromHours(1); 
        options.SlidingExpiration = true; 
 
        options.Events.OnRedirectToLogin = context => 
        { 
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
            return Task.CompletedTask; 
        }; 
    }) 
    .AddOpenIdConnect("AzureAd", options => 
    { 
        options.Events.OnTokenValidated = _ => Task.CompletedTask; 
        options.Authority = $"{authentication.Instance}{authentication.TenantId}"; 
        options.ClientId = authentication.ClientId;
        options.ClientSecret = authentication.AuthCodeFlowSecret; 
        options.ResponseType = "code"; 
        options.CallbackPath = "/signin-oidc"; 
        options.UsePkce = true

ResponseType = "code" forteller biblioteket at vi ønsker å bruke authorization code flow, og UsePkce = true aktiverer PKCE. I nyere versjoner av pakken er PKCE på som standard, men det er greit å være eksplisitt. Tokens lagres kryptert i cookien og er aldri tilgjengelig for JavaScript. 

I tillegg trenger man en controller som tar seg av innlogging, utlogging og eventuelt også eksponerer et endepunkt for brukerinfo som kan brukes til å sjekke om en bruker er logget inn og hvilke roller og tilganger de har: 

[Authorize] 
[Route("api/auth")] 
public class AuthController : Controller 
{ 
    [AllowAnonymous] 
    [HttpGet("login")] 
    public async Task Login(string returnUrl = "/") 
    { 
        await HttpContext.ChallengeAsync(new AuthenticationProperties 
        { 
            RedirectUri = returnUrl 
        }); 
    } 
 
    [HttpGet("logout")] 
    public async Task Logout(string returnUrl = "/") 
    { 
        await HttpContext.SignOutAsync("AzureAd", new AuthenticationProperties 
        { 
            RedirectUri = returnUrl 
        }); 
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); 
    } 
     
   [AllowAnonymous] 
    [HttpGet("userinfo")] 
    public async Task<UserInfo> GetUserInfo() 
    { 
        var user = await HttpContext.AuthenticateAsync(); 
        return new UserInfo 
        { 
            IsAuthenticated = user.Succeeded, 
            Name = user.Principal?.FindFirst("name")?.Value, 
            Roles = user.Principal?.FindAll(ClaimTypes.Role) 
                .Select(c => c.Value) 
                .ToList

Merk at userinfo-endepunktet har [AllowAnonymous]-attributtet. Dette er fordi at det er dette endepunktet som forteller klienten om brukeren er logget inn eller ikke, så vi er nødt til å kunne få ut info om brukeren selv om de ikke er autentisert enda. 

I Alvtime bruker vi dette mønsteret slik at frontend-appene kaller BFF-endepunkter, og BFF håndterer alt av token-logikk. Frontend-koden vet dermed knapt at det eksisterer tokens. 

CORS og CSRF 

Når sessions håndteres med cookies, dukker det opp en ny trussel: CSRF (Cross-Site Request Forgery). Tenk deg at du er innlogget i Alvtime og besøker en annen nettside. Den nettsiden kan i prinsippet sende en skjult POST-forespørsel til BFF-et ditt og nettleseren vil automatisk inkludere session-cookien. BFF-et ser en autentisert forespørsel og vet ikke at den egentlig kom fra en ondsinnet kilde. 

Det er to mekanismer vi bruker for å beskytte mot dette. 

SameSite på cookien er den enkleste. SameSite=Strict betyr at nettleseren rett og slett nekter å sende cookien ved cross-origin-forespørsler. En forespørsel fra evil.example.com til alvtime.no vil aldri ha med cookien og problemet er løst på nettlesernivå. 

CORS med egendefinert header er den andre mekanismen. Enkle HTTP-forespørsler (GET/POST uten spesielle headere) trigger ikke en CORS preflight-forespørsel, og kan dermed snike seg gjennom uten at nettleseren sjekker opprinnelsen. Men hvis serveren krever at alle forespørsel har en CSRF-header, for eksempel X-CSRF: 1, er nettleseren tvunget til å sende en preflight OPTIONS-forespørsel først. BFF-et har en CORS-policy som bare tillater forespørsler fra den legitime frontend-opprinnelsen. Prøver en ondsinnet nettside på en annen origin å kalle BFF-et, vil preflight bli avvist av CORS-policyen og forespørselen stopper der. 

Verdien av headeren er fullstendig uviktig, 1 holder fint. Det eneste som betyr noe er at headeren eksisterer, fordi det er det som tvinger frem preflight-sjekken. 

Oppsettet for CORS ser slik ut: 

var AllowedOrigins = configuration["AllowedOrigins"].Split(","); 
 
services.AddCors(options => 
{ 
    options.AddDefaultPolicy(builder => 
        { 
            builder.WithOrigins(AllowedOrigins) 
                .WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization, "X-CSRF") 
                .AllowAnyMethod() 
                .AllowCredentials

En ting å merke seg: AllowCredentials() krever at man bruker WithOrigins(...) med en eksplisitt origin. Wildcard * er ikke tillatt når cookies er involvert. 

Krav om CSRF-header kan implementeres i en middleware slik som dette: 

app.Use(async (context, next) => 
{ 
    if (context.Request.Method != HttpMethods.Options &&  
       !context.Request.Headers.ContainsKey("X-CSRF")) 
    { 
        context.Response.StatusCode = 400; 
        await context.Response.WriteAsync("Missing X-CSRF header"); 
        return; 
    } 
    await next

Frontend-koden sender headeren med alle kall: 

fetch("/api/endpoint", { 
  headers: { "X-CSRF": "1" } 
}); 

Kombinasjonen av SameSite=Strict og CORS-policyen med egendefinert header gir to uavhengige lag med CSRF-beskyttelse. Ingen tradisjonell CSRF-token med tilfeldig verdi per request er nødvendig, selv om dette så klart vil øke sikkerheten (og kompleksiteten) enda et hakk. 

Konklusjon 

Autentisering og autorisering er en jungel av forskjellige anbefalinger og metoder, så det gjelder å holde tunga rett i munnen. Vi gikk fra et Frankensteins monster av implicit grant til en moderne, sikker authorization code flow + BFF + PKCE og det viste seg å være overraskende rett frem med de verktøyene som allerede finnes i .NET-økosystemet. Sikkerheten er nå lagdelt på tvers av flere mekanismer, der hver enkelt for seg selv gir god beskyttelse og til sammen gjør angrepsoverflaten svært liten. 

Sikkerhet er ofte et aspekt av systemutvkling som kan være forvirrende, vanskelig og skummelt å gjøre feil. Man vil jo tross alt ikke la noen uvedkommende få tilgang til systemet sitt. Noen ganger har man dog ikke noe valg, og nå nylig var vi nødt til å skrive om innloggingsflyten i et av våre interne systemer. Der vi tidligere hadde brukt en slags Frankensteins monster av implicit grant flow og noen andre småting fra andre flyter, flyttet vi over til cookie-basert BFF pattern med authorization code flow og proof key for code exchange (PKCE). I denne artikkelen skal vi fortelle litt om bakgrunnen for denne omskrivingen, hva de ulike flytene er og hvordan det gjøres i praksis i et .NET-prosjekt. 

Hvorfor valgte vi å skrive om? 

Vi har flere internprosjekter hos Alv som vi bruker både til kompetansebygging og til ting vi faktisk trenger, deriblant vårt eget timeføringssystem: Alvtime. Alvtime ble skrevet i Alvs spede begynnelse for nærmere 7 år siden og kan tidvis bære preg av å være skrevet som et hobbyprosjekt hvor målet er å lære seg noe ny teknologi og gjort på frivillig basis etter arbeidstid. Det ble i sin tid implementert autentisering og autorisering ved bruk av implicit grant flow som i senere tid har blitt frarådet av Microsoft å bruke og de anbefaler heller å gå over til authorization code flow. Vi har også valgt å ta det ett steg lenger å implementere BFF på toppen av dette. 

Hva er implicit flow, BFF pattern og authorization code flow? 

For å skjønne hvorfor BFF med authorization code flow er en mer sikker innloggingsflyt er det best å starte med å forklare hvordan implicit flow fungerer. Hovedkonseptet med implicit flow er at tokens (tilgangstoken eller ID token) returneres fra /authorize endepunktet til authorization server (f.eks. Azure e.l.) direkte til klienten. Problemet med denne flyten er at siden tokens flyter direkte mellom klienten og authorization server så er det sårbart for lekkasje, altså at noen kan få tak i tokens under transport. 

Authorization code flow løser dette ved at authorization serveren i stedet returnerer en kortlevd autoriseringskode fra /authorize. Denne koden i seg selv gir ingen tilgang, den må byttes inn i tokens ved å kalle /token-endepunktet med en klienthemmelighet. Siden klienthemmeligheten ikke kan oppbevares trygt i en nettleser, er det her BFF-mønsteret kommer inn. 

BFF, eller backend-for-frontend, er et serverside-mellomlag som sitter mellom nettleseren og authorization server. Se figur 1 nedenfor for å følge flyten som ser omtrent slik ut: brukeren klikker på "Logg inn" i GUI og blir sendt til /login-endepunktet i backend (1) som så tar kontakt med authorization server for innlogging (2) → authorization server redirecter tilbake til BFF med autoriseringskoden (3) → BFF tar imot koden og bytter den mot tokens (access, id og refresh token). BFF lagrer deretter tokens på serveren og utsteder en httpOnly-cookie til nettleseren (4). Cookien sendes automatisk med alle HTTP-forespørsler (5), men den kan ikke leses av JavaScript – tokens er altså aldri eksponert for klientsidekoden. Dersom API og BFF er forskjellige servere legger BFF på access token på alle forespørsler som sendes til APIet (6) som så returnerer responsen til BFF og videre til klienten (7 + 8). 

I Alvtime er BFF og Web API-et på samme server. BFF-laget håndterer all autentiseringslogikk og videreformidler API-kall internt i samme applikasjon, noe som forenkler arkitekturen betraktelig i kontrast til om man implementerer BFF serveren som sin egen applikasjon. Dette kan ha fordeler i form av isolering og enkapsulering av ansvarsområder, men vi har valgt å holde det enkelt i denne omgang. 

PKCE 

PKCE, uttalt "pixy", står for Proof Key for Code Exchange og ble opprinnelig laget for å sikre såkalte public clients, SPA-er og mobilapper som ikke kan oppbevare klienthemmeligheter trygt. Problemet PKCE løser er authorization code interception: hva skjer hvis noen klarer å snappe opp autoriseringskoden underveis? Med bare koden kan en angriper i prinsippet bytte den mot tokens. 

PKCE løser dette med en enkel men effektiv mekanisme. Klienten genererer en tilfeldig streng kalt code verifier og hasher den med SHA-256 til en code challenge. Når klienten starter innloggingsflyten, sendes code challenge med /authorize-forespørselen. Når autoriseringskoden siden skal byttes mot tokens, sendes den originale code verifier med og authorization server sjekker at code verifier matcher med code challenge den fikk tidligere. En stjålet autoriseringskode er dermed verdiløs uten den originale verifier-en. 

Selv om PKCE opprinnelig var ment for public clients, anbefales det nå for alle klienter, inkludert konfidensielle klienter som bruker klienthemmeligheter. Det er med andre ord ingen god grunn til å la være. 

Hvordan gjøres det i .NET? 

I et ASP.NET Core-prosjekt er det heldigvis ikke mye som skal til for å sette opp dette. Man kan bruke biblioteker fra leverandører som Duende, men det er nesten like greit å implementere det selv så man slipper vendor lock-in. Microsoft har innebygd støtte for OIDC og OAuth via et par NuGet-pakker: 

  • Microsoft.AspNetCore.Authentication.OpenIdConnect – håndterer OIDC/OAuth-flyten 

  • Microsoft.AspNetCore.Authentication.Cookies – for å holde på sesjonen med en kryptert cookie 

Oppsettet i Program.cs ser omtrent slik ut: 

var authentication = new OAuthOptions(); 
configuration.Bind("AzureAd", authentication); 
 
services 
    .AddAuthentication(options => 
    { 
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
        options.DefaultChallengeScheme = "AzureAd"; 
    }) 
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => 
    { 
        options.Cookie.Name = "AuthorizationCookie"; 
        options.Cookie.HttpOnly = true; 
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always; 
        options.Cookie.SameSite = SameSiteMode.Strict; 
 
        options.ExpireTimeSpan = TimeSpan.FromHours(1); 
        options.SlidingExpiration = true; 
 
        options.Events.OnRedirectToLogin = context => 
        { 
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
            return Task.CompletedTask; 
        }; 
    }) 
    .AddOpenIdConnect("AzureAd", options => 
    { 
        options.Events.OnTokenValidated = _ => Task.CompletedTask; 
        options.Authority = $"{authentication.Instance}{authentication.TenantId}"; 
        options.ClientId = authentication.ClientId;
        options.ClientSecret = authentication.AuthCodeFlowSecret; 
        options.ResponseType = "code"; 
        options.CallbackPath = "/signin-oidc"; 
        options.UsePkce = true

ResponseType = "code" forteller biblioteket at vi ønsker å bruke authorization code flow, og UsePkce = true aktiverer PKCE. I nyere versjoner av pakken er PKCE på som standard, men det er greit å være eksplisitt. Tokens lagres kryptert i cookien og er aldri tilgjengelig for JavaScript. 

I tillegg trenger man en controller som tar seg av innlogging, utlogging og eventuelt også eksponerer et endepunkt for brukerinfo som kan brukes til å sjekke om en bruker er logget inn og hvilke roller og tilganger de har: 

[Authorize] 
[Route("api/auth")] 
public class AuthController : Controller 
{ 
    [AllowAnonymous] 
    [HttpGet("login")] 
    public async Task Login(string returnUrl = "/") 
    { 
        await HttpContext.ChallengeAsync(new AuthenticationProperties 
        { 
            RedirectUri = returnUrl 
        }); 
    } 
 
    [HttpGet("logout")] 
    public async Task Logout(string returnUrl = "/") 
    { 
        await HttpContext.SignOutAsync("AzureAd", new AuthenticationProperties 
        { 
            RedirectUri = returnUrl 
        }); 
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); 
    } 
     
   [AllowAnonymous] 
    [HttpGet("userinfo")] 
    public async Task<UserInfo> GetUserInfo() 
    { 
        var user = await HttpContext.AuthenticateAsync(); 
        return new UserInfo 
        { 
            IsAuthenticated = user.Succeeded, 
            Name = user.Principal?.FindFirst("name")?.Value, 
            Roles = user.Principal?.FindAll(ClaimTypes.Role) 
                .Select(c => c.Value) 
                .ToList

Merk at userinfo-endepunktet har [AllowAnonymous]-attributtet. Dette er fordi at det er dette endepunktet som forteller klienten om brukeren er logget inn eller ikke, så vi er nødt til å kunne få ut info om brukeren selv om de ikke er autentisert enda. 

I Alvtime bruker vi dette mønsteret slik at frontend-appene kaller BFF-endepunkter, og BFF håndterer alt av token-logikk. Frontend-koden vet dermed knapt at det eksisterer tokens. 

CORS og CSRF 

Når sessions håndteres med cookies, dukker det opp en ny trussel: CSRF (Cross-Site Request Forgery). Tenk deg at du er innlogget i Alvtime og besøker en annen nettside. Den nettsiden kan i prinsippet sende en skjult POST-forespørsel til BFF-et ditt og nettleseren vil automatisk inkludere session-cookien. BFF-et ser en autentisert forespørsel og vet ikke at den egentlig kom fra en ondsinnet kilde. 

Det er to mekanismer vi bruker for å beskytte mot dette. 

SameSite på cookien er den enkleste. SameSite=Strict betyr at nettleseren rett og slett nekter å sende cookien ved cross-origin-forespørsler. En forespørsel fra evil.example.com til alvtime.no vil aldri ha med cookien og problemet er løst på nettlesernivå. 

CORS med egendefinert header er den andre mekanismen. Enkle HTTP-forespørsler (GET/POST uten spesielle headere) trigger ikke en CORS preflight-forespørsel, og kan dermed snike seg gjennom uten at nettleseren sjekker opprinnelsen. Men hvis serveren krever at alle forespørsel har en CSRF-header, for eksempel X-CSRF: 1, er nettleseren tvunget til å sende en preflight OPTIONS-forespørsel først. BFF-et har en CORS-policy som bare tillater forespørsler fra den legitime frontend-opprinnelsen. Prøver en ondsinnet nettside på en annen origin å kalle BFF-et, vil preflight bli avvist av CORS-policyen og forespørselen stopper der. 

Verdien av headeren er fullstendig uviktig, 1 holder fint. Det eneste som betyr noe er at headeren eksisterer, fordi det er det som tvinger frem preflight-sjekken. 

Oppsettet for CORS ser slik ut: 

var AllowedOrigins = configuration["AllowedOrigins"].Split(","); 
 
services.AddCors(options => 
{ 
    options.AddDefaultPolicy(builder => 
        { 
            builder.WithOrigins(AllowedOrigins) 
                .WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization, "X-CSRF") 
                .AllowAnyMethod() 
                .AllowCredentials

En ting å merke seg: AllowCredentials() krever at man bruker WithOrigins(...) med en eksplisitt origin. Wildcard * er ikke tillatt når cookies er involvert. 

Krav om CSRF-header kan implementeres i en middleware slik som dette: 

app.Use(async (context, next) => 
{ 
    if (context.Request.Method != HttpMethods.Options &&  
       !context.Request.Headers.ContainsKey("X-CSRF")) 
    { 
        context.Response.StatusCode = 400; 
        await context.Response.WriteAsync("Missing X-CSRF header"); 
        return; 
    } 
    await next

Frontend-koden sender headeren med alle kall: 

fetch("/api/endpoint", { 
  headers: { "X-CSRF": "1" } 
}); 

Kombinasjonen av SameSite=Strict og CORS-policyen med egendefinert header gir to uavhengige lag med CSRF-beskyttelse. Ingen tradisjonell CSRF-token med tilfeldig verdi per request er nødvendig, selv om dette så klart vil øke sikkerheten (og kompleksiteten) enda et hakk. 

Konklusjon 

Autentisering og autorisering er en jungel av forskjellige anbefalinger og metoder, så det gjelder å holde tunga rett i munnen. Vi gikk fra et Frankensteins monster av implicit grant til en moderne, sikker authorization code flow + BFF + PKCE og det viste seg å være overraskende rett frem med de verktøyene som allerede finnes i .NET-økosystemet. Sikkerheten er nå lagdelt på tvers av flere mekanismer, der hver enkelt for seg selv gir god beskyttelse og til sammen gjør angrepsoverflaten svært liten. 

Kanskje du liker:

Kanskje du liker:

Utvikling

12. mars 2026

Nylig var vi nødt til å skrive om innloggingsflyten i et av våre interne systemer. Der vi tidligere hadde brukt en slags Frankensteins monster av implicit grant flow og noen andre småting fra andre flyter, flyttet vi over til cookie-basert BFF pattern med authorization code flow og proof key for code exchange (PKCE).

Utvikling

12. mars 2026

Nylig var vi nødt til å skrive om innloggingsflyten i et av våre interne systemer. Der vi tidligere hadde brukt en slags Frankensteins monster av implicit grant flow og noen andre småting fra andre flyter, flyttet vi over til cookie-basert BFF pattern med authorization code flow og proof key for code exchange (PKCE).

Utvikling

12. februar 2026

Kodebaser blir sjelden komplekse over natten. Det skjer gradvis, gjennom små valg vi tar hver dag. Litt ekstra abstraksjon her, et interface der, en pakke som virker fornuftig i øyeblikket.

Utvikling

12. februar 2026

Kodebaser blir sjelden komplekse over natten. Det skjer gradvis, gjennom små valg vi tar hver dag. Litt ekstra abstraksjon her, et interface der, en pakke som virker fornuftig i øyeblikket.

Utvikling

4. februar 2026

Sondre tok oss gjennom hvordan OAuth og OpenID Connect fungerer når man skal implementere Authorization Code Flow.

Utvikling

4. februar 2026

Sondre tok oss gjennom hvordan OAuth og OpenID Connect fungerer når man skal implementere Authorization Code Flow.

Utvikling

12. mars 2026

Nylig var vi nødt til å skrive om innloggingsflyten i et av våre interne systemer. Der vi tidligere hadde brukt en slags Frankensteins monster av implicit grant flow og noen andre småting fra andre flyter, flyttet vi over til cookie-basert BFF pattern med authorization code flow og proof key for code exchange (PKCE).

Utvikling

12. februar 2026

Kodebaser blir sjelden komplekse over natten. Det skjer gradvis, gjennom små valg vi tar hver dag. Litt ekstra abstraksjon her, et interface der, en pakke som virker fornuftig i øyeblikket.

Utvikling

12. mars 2026

Nylig var vi nødt til å skrive om innloggingsflyten i et av våre interne systemer. Der vi tidligere hadde brukt en slags Frankensteins monster av implicit grant flow og noen andre småting fra andre flyter, flyttet vi over til cookie-basert BFF pattern med authorization code flow og proof key for code exchange (PKCE).

Utvikling

12. februar 2026

Kodebaser blir sjelden komplekse over natten. Det skjer gradvis, gjennom små valg vi tar hver dag. Litt ekstra abstraksjon her, et interface der, en pakke som virker fornuftig i øyeblikket.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2026. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2026. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2026. All rights reserved.

Footer Logo

Når riktig partner utgjør all forskjell



822 704 042

Pløens gate 7

0181 Oslo

hei@alv.no

+47 91 92 92 18

Copyright ©2026. All rights reserved.