Integrationsunderlag
Det här dokumentet är självbärande. Det hänvisar inte vidare, och innehåller allt som behövs för att koppla en applikation till Aegis Central ID.
Är du en människa och vill ha en guide att läsa i ordning, börja på Kom igång. Är du ett verktyg som ska generera kod, läs vidare här.
Fasta värden
De här ändras inte och kan skrivas in direkt.
| Namn | Värde |
|---|---|
Utfärdare (issuer, authority) |
https://login.aegiscentralid.se/ |
| Upptäcktsdokument | https://login.aegiscentralid.se/.well-known/openid-configuration |
| Publika nycklar (JWKS) | https://login.aegiscentralid.se/.well-known/jwks |
| Auktoriseringsändpunkt | https://login.aegiscentralid.se/connect/authorize |
| Tokenändpunkt | https://login.aegiscentralid.se/connect/token |
| UserInfo | https://login.aegiscentralid.se/connect/userinfo |
| Utloggning | https://login.aegiscentralid.se/connect/logout |
Föredra alltid upptäcktsdokumentet framför att skriva in enskilda adresser. Biblioteket hämtar dem självt, och de kan ändras utan att integrationen går sönder.
Det enda som ska bytas ut
DITT-CLIENT-ID — hämtas från arbetsytan på
https://login.aegiscentralid.se/workspace/clients.
Är klienten konfidentiell finns också DIN-CLIENT-SECRET, som visas en enda
gång när klienten skapas. Den ska läsas ur en miljövariabel, aldrig skrivas in i
kod.
Allt annat i exemplen nedan kan lämnas som det står.
Så bestäms callback-adressen
Callback-adressen är en adress på applikationens egen sajt dit användaren skickas tillbaka efter inloggning. Aegis bestämmer den inte — applikationen väljer den, och registrerar den sedan i arbetsytan.
Regler som gäller alltid:
- Absolut adress.
https://din-sajt.se/callback, inte/callback. httpskrävs. Enda undantaget ärlocalhost, för utveckling.- Inget fragment. Adressen får inte innehålla
#. - Exakt matchning. Adressen i auktoriseringsanropet måste vara tecken för
tecken identisk med den registrerade.
…/callbackoch…/callback/är två olika adresser. - Registrera varje miljö för sig. Utveckling och drift är olika adresser och måste båda läggas in.
Konventionell sökväg per ramverk
Välj den som ramverket redan förväntar sig — då behöver ingenting konfigureras om.
| Ramverk | Konventionell sökväg | Registrera alltså |
|---|---|---|
| ASP.NET Core | /signin-oidc |
https://din-sajt.se/signin-oidc |
Node, openid-client |
valfri, ofta /callback |
https://din-sajt.se/callback |
PHP, openid-connect-php |
filens egen adress | https://din-sajt.se/callback.php |
| Python, Authlib | valfri, ofta /callback |
https://din-sajt.se/callback |
Ren webbsida, embed.js |
valfri sida som anropar Aegis.completeLogin() |
https://din-sajt.se/callback |
För lokal utveckling: samma sökväg men mot http://localhost:<port>.
Regler som Aegis upprätthåller
En integration som bryter mot något av det här får ett fel, inte en tyst avvikelse.
- Authorization Code Flow.
response_type=code. Implicit flow finns inte. - PKCE krävs av alla klienter, även konfidentiella. Endast
S256;plainavvisas. stateska skickas och jämföras vid återkomsten.- En kod kan bara lösas in en gång. Löses samma kod in två gånger återkallas hela kedjan, inklusive refresh token.
- MFA är obligatoriskt för alla konton. Applikationen behöver inte hantera det.
Scopes
| Scope | Ger |
|---|---|
openid |
Obligatoriskt. Ger sub. |
profile |
name, preferred_username |
email |
email, email_verified |
tenant.role |
tenant, tenant_id, tenant_role |
offline_access |
Refresh token |
Klienten måste ha fått scopet tilldelat i arbetsytan för att kunna begära det.
Anspråk i ID-token
{
"iss": "https://login.aegiscentralid.se/",
"aud": "DITT-CLIENT-ID",
"sub": "ba9715c3-7638-45b4-dd64-08df0232cc27",
"exp": 1787617406,
"iat": 1787615606,
"name": "Anna Lindqvist",
"preferred_username": "anna@exempel.se",
"email": "anna@exempel.se",
"email_verified": "true",
"tenant": "assethub",
"tenant_id": "01a035fc-6e64-705d-bcb2-28a85e446ed4",
"tenant_role": "Owner"
}
sub är användarens permanenta id. Använd det som nyckel i din databas, inte
e-postadressen — adressen kan bytas, sub ändras aldrig.
tenant_role är Owner, Admin eller Member, och gäller den valda arbetsytan.
Vad koden måste verifiera
Biblioteket gör det åt dig. Stäng inte av något av det:
issärhttps://login.aegiscentralid.se/audär ditt eget klient-id- Signaturen validerar mot JWKS
exphar inte passeratstatematchar det som skickades
ASP.NET Core
// Program.cs
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "aegis";
})
.AddCookie()
.AddOpenIdConnect("aegis", options =>
{
options.Authority = "https://login.aegiscentralid.se/";
options.ClientId = "DITT-CLIENT-ID";
options.ClientSecret = builder.Configuration["Aegis:ClientSecret"];
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("tenant.role");
// Motsvarar den registrerade adressen https://din-sajt.se/signin-oidc
options.CallbackPath = "/signin-oidc";
// false: tokens hålls utanför kakan. Med true blir svaret från callbacken
// större än de 4 kB huvuden många omvända proxyer buffrar → 502.
options.SaveTokens = false;
});
Har applikationen redan ASP.NET Core Identity ska Aegis i stället registreras
som extern inloggning med SignInScheme = IdentityConstants.ExternalScheme,
utan att röra Identitys förvalda scheman, och en ExternalLogin-sida ska koppla
sub till ett konto i AspNetUsers via AddLoginAsync. Har applikationen en
egen kakinloggning utan Identity tas resultatet i stället över i
Events.OnTicketReceived med context.HandleResponse() och applikationens
egen SignInAsync. Fullständig kod för båda:
https://docs.aegiscentralid.se/aspnet-core.md.
Står applikationen bakom en TLS-avslutande proxy krävs UseForwardedHeaders
med proxyns adress i KnownProxies, annars byggs redirect_uri med http://
och avvisas.
Node
// npm i openid-client
import * as client from "openid-client";
const config = await client.discovery(
new URL("https://login.aegiscentralid.se/"),
"DITT-CLIENT-ID",
process.env.AEGIS_CLIENT_SECRET);
const verifier = client.randomPKCECodeVerifier();
const challenge = await client.calculatePKCECodeChallenge(verifier);
req.session.verifier = verifier;
res.redirect(client.buildAuthorizationUrl(config, {
redirect_uri: "https://din-sajt.se/callback",
scope: "openid profile email tenant.role",
code_challenge: challenge,
code_challenge_method: "S256"
}).href);
// På /callback
const tokens = await client.authorizationCodeGrant(
config,
new URL(req.url, "https://din-sajt.se"),
{ pkceCodeVerifier: req.session.verifier });
const claims = tokens.claims();
PHP
<?php
// composer require jumbojett/openid-connect-php
use Jumbojett\OpenIDConnectClient;
$oidc = new OpenIDConnectClient(
'https://login.aegiscentralid.se/',
'DITT-CLIENT-ID',
getenv('AEGIS_CLIENT_SECRET'));
$oidc->setRedirectURL('https://din-sajt.se/callback.php');
$oidc->addScope(['openid', 'profile', 'email', 'tenant.role']);
$oidc->setCodeChallengeMethod('S256');
$oidc->authenticate();
$sub = $oidc->getVerifiedClaims('sub');
$roll = $oidc->getVerifiedClaims('tenant_role');
Python
# pip install authlib flask
from authlib.integrations.flask_client import OAuth
oauth = OAuth(app)
oauth.register(
name="aegis",
server_metadata_url="https://login.aegiscentralid.se/.well-known/openid-configuration",
client_id="DITT-CLIENT-ID",
client_secret=os.environ["AEGIS_CLIENT_SECRET"],
client_kwargs={
"scope": "openid profile email tenant.role",
"code_challenge_method": "S256",
})
@app.route("/login")
def login():
return oauth.aegis.authorize_redirect("https://din-sajt.se/callback")
@app.route("/callback")
def callback():
token = oauth.aegis.authorize_access_token()
anvandare = token["userinfo"]
return anvandare["sub"]
Ren webbsida utan backend
<script src="https://login.aegiscentralid.se/embed.js"
data-client-id="DITT-CLIENT-ID"
data-redirect="https://din-sajt.se/callback"
data-scope="openid profile email"></script>
<div class="aegis-signin"></div>
På callback-sidan:
<script src="https://login.aegiscentralid.se/embed.js"
data-client-id="DITT-CLIENT-ID"
data-redirect="https://din-sajt.se/callback"></script>
<script>
Aegis.completeLogin()
.then(function (tokens) { /* tokens.id_token, tokens.access_token */ })
.catch(function (fel) { console.error(fel.message); });
</script>
Har applikationen en server ska servern göra tokenutbytet. Tokens i webbläsaren kan läsas av varje skript på sidan.
Andra språk
Aegis följer OpenID Connect Discovery. Vilket certifierat bibliotek som helst fungerar med tre inställningar:
- Utfärdare eller metadata-adress enligt tabellen överst.
response_type=code.- PKCE med
S256.
Vanliga fel
| Fel | Betyder |
|---|---|
invalid_request, client_id saknas |
Frågesträngen tappades på vägen |
invalid_client |
Fel klient-id, eller fel miljö |
invalid_grant vid inlösen |
Fel code_verifier, koden redan använd, utgången, eller redirect_uri som inte matchar |
invalid_grant vid förnyelse |
Refresh token återkallad. Användaren måste logga in igen |
| Redirect-adressen godtas inte | Matchar inte tecken för tecken, eller använder http |