OpenID Connect: auktorisering av interna applikationer från anpassade till standard

För några månader sedan implementerade jag en OpenID Connect-server för att hantera åtkomst för hundratals av våra interna applikationer. Från vår egen utveckling, bekvämt i mindre skala, har vi gått över till en allmänt accepterad standard. Åtkomst via den centrala tjänsten förenklar monotont arbete avsevärt, minskar kostnaderna för att implementera auktoriseringar, gör att du kan hitta många färdiga lösningar och inte racka ihop dina hjärnor när du utvecklar nya. I den här artikeln kommer jag att prata om denna övergång och de gupp som vi lyckades fylla.

OpenID Connect: auktorisering av interna applikationer från anpassade till standard

För länge sedan... Hur allt började

För några år sedan, när det fanns för många interna applikationer för manuell kontroll, skrev vi en applikation för att kontrollera åtkomsten inom företaget. Det var en enkel Rails-applikation som kopplade till en databas med information om anställda, där tillgång till olika funktioner konfigurerades. Samtidigt höjde vi den första SSO, som baserades på verifiering av tokens från sidan av klienten och auktoriseringsservern, token överfördes i krypterad form med flera parametrar och verifierades på auktoriseringsservern. Detta var inte det mest bekväma alternativet, eftersom varje intern applikation måste beskriva ett stort lager av logik, och personaldatabaserna var helt synkroniserade med auktoriseringsservern.

Efter en tid bestämde vi oss för att förenkla uppgiften med centraliserad auktorisering. SSO överfördes till balansören. Med hjälp av OpenResty lades en mall till Lua som kontrollerade tokens, visste vilken applikation förfrågan gick till och kunde kontrollera om det fanns åtkomst där. Detta tillvägagångssätt förenklade avsevärt uppgiften att kontrollera åtkomst till interna applikationer - i koden för varje applikation var det inte längre nödvändigt att beskriva ytterligare logik. Som ett resultat stängde vi trafiken externt, och själva applikationen visste ingenting om behörighet.

Ett problem förblev dock olöst. Hur är det med applikationer som behöver information om anställda? Det var möjligt att skriva ett API för auktoriseringstjänsten, men då skulle man behöva lägga till ytterligare logik för varje sådan applikation. Dessutom ville vi bli av med beroendet av en av våra egenskrivna applikationer, som senare skulle översättas till OpenSource, på vår interna auktoriseringsserver. Vi kommer att prata om det någon annan gång. Lösningen på båda problemen var OAuth.

till gemensamma standarder

OAuth är en begriplig, allmänt accepterad auktoriseringsstandard, men eftersom endast dess funktionalitet inte räcker, började de genast överväga OpenID Connect (OIDC). OIDC i sig är den tredje implementeringen av den öppna autentiseringsstandarden, som har flödat in i ett tillägg över OAuth 2.0-protokollet (ett öppet auktoriseringsprotokoll). Denna lösning stänger problemet med bristen på data om slutanvändaren och gör det också möjligt att byta behörighetsleverantör.

Vi valde dock inte en specifik leverantör och bestämde oss för att lägga till integration med OIDC för vår befintliga auktoriseringsserver. Till förmån för detta beslut var det faktum att OIDC är mycket flexibelt när det gäller auktorisering av slutanvändare. Således var det möjligt att implementera OIDC-stöd på din nuvarande auktoriseringsserver.

OpenID Connect: auktorisering av interna applikationer från anpassade till standard

Vårt sätt att implementera vår egen OIDC-server

1) Förde data till önskad form

För att integrera OIDC är det nödvändigt att föra den aktuella användardatan till en form som standarden förstår. I OIDC kallas detta Claims. Anspråk är i huvudsak sista fält i användardatabasen (namn, e-post, telefon, etc.). Existerar standardlista över frimärken, och allt som inte ingår i denna lista anses vara anpassat. Därför är den första punkten som du måste vara uppmärksam på om du vill välja en befintlig OIDC-leverantör möjligheten till bekväm anpassning av nya varumärken.

Gruppen av kännetecken kombineras i följande delmängd - Omfattning. Under auktorisering begärs åtkomst inte till specifika märken, utan till scopes, även om några av märkena från scopet inte behövs.

2) Genomfört nödvändiga bidrag

Nästa del av OIDC-integrationen är val och implementering av auktorisationstyper, de så kallade anslagen. Det ytterligare scenariot för interaktion mellan den valda applikationen och auktoriseringsservern kommer att bero på det valda beviljandet. Ett exemplariskt upplägg för att välja rätt bidrag visas i figuren nedan.

OpenID Connect: auktorisering av interna applikationer från anpassade till standard

För vår första ansökan använde vi det vanligaste bidraget, Auktorisationskoden. Dess skillnad mot andra är att det är ett tresteg, d.v.s. genomgår ytterligare tester. Först gör användaren en begäran om auktoriseringstillstånd, får en token - Auktoriseringskod, och begär sedan med denna token, som med en biljett för resa, en åtkomsttoken. All huvudinteraktion i detta auktoriseringsskript baseras på omdirigeringar mellan applikationen och auktoriseringsservern. Du kan läsa mer om detta bidrag här.

OAuth följer konceptet att åtkomsttokens som erhålls efter auktorisering bör vara tillfälliga och bör ändras, helst var tionde minut i genomsnitt. Auktoriseringskoden är en verifiering i tre steg genom omdirigeringar, var tionde minut att vända ett sådant steg, ärligt talat, är inte den mest trevliga uppgiften för ögonen. För att lösa detta problem finns det ett annat bidrag - Refresh Token, som vi också använde i vårt land. Allt är lättare här. Under verifiering från ett annat anslag, utöver huvudåtkomsttokenet, utfärdas ytterligare en - Refresh Token, som bara kan användas en gång och dess livslängd är vanligtvis mycket längre. Med denna Refresh Token, när TTL (Time to Live) för huvudåtkomsttoken slutar, kommer begäran om en ny åtkomsttoken att komma till slutpunkten för ett annat beviljande. Den använda Refresh Token återställs omedelbart till noll. Denna kontroll är tvåstegs och kan utföras i bakgrunden, omärkligt för användaren.

3) Ställ in anpassade datautdataformat

Efter att de utvalda bidragen är implementerade fungerar auktorisering, det är värt att nämna att få data om slutanvändaren. OIDC har en separat slutpunkt för detta, där du kan begära användardata med din nuvarande åtkomsttoken och om den är uppdaterad. Och om användarens data inte ändras så ofta, och du behöver följa de nuvarande många gånger, kan du komma till en sådan lösning som JWT-tokens. Dessa tokens stöds också av standarden. Själva JWT-tokenet består av tre delar: header (information om token), nyttolast (alla nödvändiga data) och signatur (signatur, token är signerad av servern och du kan senare kontrollera källan till dess signatur).

I OIDC-implementeringen kallas JWT-token id_token. Det kan begäras tillsammans med en vanlig åtkomsttoken och allt som återstår är att verifiera signaturen. Auktoriseringsservern har en separat slutpunkt för detta med ett gäng publika nycklar i formatet J.W.K.. Och på tal om detta är det värt att nämna att det finns en annan slutpunkt, som, baserat på standarden RFC5785 återspeglar den aktuella konfigurationen av OIDC-servern. Den innehåller alla slutpunktsadresser (inklusive adressen till den offentliga nyckelringen som används för signering), varumärken och omfattningar som stöds, använda krypteringsalgoritmer, stödda anslag, etc.

Till exempel på Google:

{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}

Med hjälp av id_token kan du alltså överföra alla nödvändiga kännetecken till tokens nyttolast och inte kontakta behörighetsservern varje gång för att begära användardata. Nackdelen med detta tillvägagångssätt är att förändringen i användardata från servern inte kommer direkt, utan tillsammans med en ny åtkomsttoken.

Implementeringsresultat

Så efter att ha implementerat vår egen OIDC-server och konfigurerat anslutningar till den på applikationssidan löste vi problemet med att överföra information om användare.
Eftersom OIDC är en öppen standard har vi möjlighet att välja en befintlig leverantör eller serverimplementering. Vi provade Keycloak, vilket visade sig vara väldigt bekvämt att konfigurera, efter att ha ställt in och ändrat anslutningskonfigurationer på applikationssidan är den redo att gå. På applikationssidan återstår bara att ändra anslutningskonfigurationerna.

Pratar om befintliga lösningar

Inom vår organisation, som den första OIDC-servern, satte vi ihop vår egen implementering, som kompletterades vid behov. Efter en detaljerad genomgång av andra färdiga lösningar kan vi säga att detta är en omtvistad fråga. Till förmån för beslutet att implementera sin egen server fanns det oro från leverantörernas sida i avsaknad av nödvändig funktionalitet, liksom närvaron av ett gammalt system där det fanns olika anpassade auktoriseringar för vissa tjänster och en hel del uppgifter om anställda redan lagrats. Men i färdiga implementeringar finns det bekvämligheter för integration. Keycloak har till exempel ett eget användarhanteringssystem och data lagras direkt i det, och det blir inte svårt att köra om dina användare där. För att göra detta har Keycloak ett API som låter dig utföra alla nödvändiga överföringsåtgärder.

Ett annat exempel på en certifierad, intressant, enligt mig, implementering är Ory Hydra. Det är intressant eftersom det består av olika komponenter. För att integrera måste du länka din användarhanteringstjänst till deras auktoriseringstjänst och utöka efter behov.

Keycloak och Ory Hydra är inte de enda färdiga lösningarna. Det är bäst att välja en implementering som är certifierad av OpenID Foundation. Dessa lösningar har vanligtvis ett OpenID-certifikat.

OpenID Connect: auktorisering av interna applikationer från anpassade till standard

Glöm inte heller befintliga betalleverantörer om du inte vill behålla din OIDC-server. Idag finns det många bra alternativ.

Vad är nästa

Inom en snar framtid kommer vi att stänga trafiken till interna tjänster på ett annat sätt. Vi planerar att överföra vår nuvarande SSO på balanseringsenheten med OpenResty till en proxy baserad på OAuth. Det finns redan många färdiga lösningar här, till exempel:
github.com/bitly/oauth2_proxy
github.com/ory/oathkeeper
github.com/keycloak/keycloak-gatekeeper

Ytterligare material

jwt.io – bra service för validering av JWT-tokens
openid.net/developers/certified - Lista över certifierade OIDC-implementeringar

Källa: will.com

Lägg en kommentar