Hvordan får jeg SSO mellom en tykk klient og andre applikasjoner?

Single sign-on mellom en tykk klient og andre applikasjoner

Single Sign-On mellom tykke klienter og andre applikasjoner er utfordrende, spesielt i en verden hvor applikasjonene ikke nødvendigvis befinner seg innenfor samme lokale sikkerhetsdomene.

Nettleserbasert autentisering

I OpenId Connect er SSO mekanismene basert på nettleserteknologi. Vi bruker cookies i nettleser for å lagre informasjon om selve påloggingen og sesjonen som oppstår mellom HelseID og applikasjonen.

Dette gjelder også for tykke klienter og mobile applikasjoner som ikke er bygd på nettleserteknologi.

Anbefalinger fra IETF

Standardiseringsorganet IETF (Internet Engineering Task Force) som forvalter både OpenId Connect og OAuth 2.0 spesifikasjonene har lagd en anbefaling om hvordan vi kan ta i bruk OpenId Connect og OAuth 2.0 for autentisering i tykke klienter. Dette er "work-in-progress", og vil antagelig endre seg over tid - men prinsippet denne spesifikasjonen beskriver er det nærmeste vi kommer en standardisert måte å håndtere utfordringen på i dag.

Du kan lese spesifikasjonen her.

Microsoft .NET WPF applikasjoner og SSO

I en WPF applikasjon som kjører på fullt rammeverk vil du vanligvis starte autentiseringsprosessen ved å benytte disse to klassene:

System.Diagnostics.Process System.Net.HttpListener

 

var client = new OidcClient(new OidcClientOptions() { Authority = "https://helseid.nhn.no", ClientId = "min-client-id", RedirectUri = "https://min-redirect-uri/", Scope = "openid profile", ClientSecret = "min ikke så hemmelige hemmelighet" }; }); var state = await client.PrepareLoginAsync(); var httpListener = new HttpListener(); //her forteller vi at HttpListener skal lytte til min angitte redirect uri httpListener.Prefixes.Add("https://min-redirect-uri/"); //starter lytting på vår redirect url httpListener.Start(); //start systemnettleser - pek på autorisasjonsendepunktet som er gitt av state var process = Process.Start(state.StartUrl); var httpContext = await httpListener.GetContextAsync(); if (!httpContext.Request.HasEntityBody) { string formData; using (var body = httpContext.Request.InputStream) { using (var reader = new System.IO.StreamReader(body, httpContext.Request.ContentEncoding)) { formData = reader.ReadToEnd(); var result = await client.ProcessResponseAsync(formData, state); if (result.User != null) { var claims = new StringBuilder(); foreach (var claim in result.User.Claims) { claims.AppendLine($"{claim.Type}: {claim.Value}"); } } } } }