Identity Provider (IDP)
Der CMI STS kann externe Identity Provider (IDP) anbinden, um den Login-Prozess an diesen zu delegieren. Dazu muss der IDP ein vom CMI STS unterstütztes Protokoll verwenden.
IDPs werden pro Mandanten in einer benannten Liste in ExternalIdps
konfiguriert. Der Name, bzw. die ID eines IDP kann frei gewählt werden. Für jeden IDP muss die Eigenschaft Type
gesetzt werden um anzugeben, welches Protokoll der IDP verwendet. Es werden weitere Eigenschaften benötigt, die vom Protokoll abhängig sind.
"tenants": {
"mandant": {
"ExternalIdps": {
"auth0": { // "auth0" ist die frei gewaehlte ID des ersten IDPs
"Type": "Oidc", // Protokoll des IDPs
// ... weitere Eigenschaften
},
"adfs": { // "adfs" ist die frei gewaehlte ID des zweiten IDPs
"Type": "Wsfed", // Protokoll des IDPs
// ... weitere Eigenschaften
}
}
}
}
Home Realm Discovery (HRD)
Das HRD ist ein Prozess mit dem ein Security Token Service entscheidet, mit welchem IDP ein Benutzer authentifiziert werden soll. Diese Bezeichnung wird vor allem von Microsoft verwendet. Im Kontext des CMI STS sind dies die Selektoren (siehe "Automatische Wahl der Identity Provider"). Standardmässig werden einem Benutzer alle externen Identity Provider angezeigt.
Anforderungen
Damit der CMI STS mit einem IDP zusammen arbeiten kann, muss er folgende Anforderungen erfüllen:
OIDC, WSFed: Der Identity-Provider muss mindestens einen dieser beiden Claim-Typen liefern. Der Claim-Wert wird vom CMI STS als eindeutige Benutzer-ID verwendet:
- sub (Subject)
- http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
OIDC: Der Identity-Provider sollte den Claim-Typen sid (Session Id) liefern, um einen sauberen Logout-Prozess zu ermöglichen.
WS Federation Provider
Hinweis: CMI empfiehlt die Verwendung des OIDC-Protokolls, wann immer das möglich ist.
Zur Konfiguration eines WS Federation Providers stehen grundsätzlich alle Optionen zur Verfügung, die das ASP.NET Core Framework bereitstellt.
Die folgende Konfiguration zeigt eine beispielhafte minimale Konfiguration, die für die meisten Provider ausreichend ist.
"o365": {
"Type": "WsFed",
"MetadataAddress": "https://login.microsoftonline.com/[...]/2007-06/federationmetadata.xml",
"Wtrealm": "https://schwerzenwil.ch/00000000-0000-0000-0000-000000000000",
"IdClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
}
Type
(erforderlich): Die Type-ID für WsFederation lautetWsFed
.MetadataAddress
(erforderlich): Die URL unter der Metadaten abgerufen werden können, wird durch den IDP festgelegt und wird hierhin übertragen.Wtrealm
(erforderlich): Eine URI die durch den IDP festgelegt und hierhin übertragen wird. Anhand des Wtrealms identifiziert der IDP den CMI STS.CallbackPath
(optional, Standardwert:/signin-wsfed-{Mandanten Id}-{IDP Id}
): Eine (relative) URL, auf die der IDP den Benutzer zurück auf den CMI STS umleiten soll, nach dem die Anmeldung am IDP erfolgreich durchgeführt wurde (Wreply).- Wenn der Pfad konfiguriert wird, muss dieser eindeutig für alle konfigurierten IDPs sein.
- Der CallbackPath wird automatisch generiert, wenn keine Konfiguration vorhanden ist. Wenn die Mandanten-ID schwerzenwil und die IDP-ID o365 lautet, wird der Pfad /signin-wsfed-schwerzenwil-o365 erzeugt.
- Bei einigen IDPs muss der CallbackPath zu den erlaubten Redirect-/Umleitungs-URLs hinzugefügt werden:
https://<CMI STS Basis Url>/<Mandant>/identity/<CallbackPath>
Beispiel: https://sts.gemeinde.ch/schwerzenwil/identity/signin-wsfed-schwerzenwil-o365
IdClaimType
: Der Claim der für das Mapping des externen Benutzers auf einen CMI Benutzer verwendet wird. Der Debug-Log-Level schreibt die empfangenen Claims auf das Log. So lässt sich erkennen, wie der vom IDP ausgestellte Claim-Type lautet.
OpenID Connect Provider
Zur Konfiguration eines OpenID Connect Providers stehen grundsätzlich alle Optionen zur Verfügung, die das ASP.NET Core Framework bereitstellt.
Die folgende Konfiguration zeigt eine beispielhafte minimale Konfiguration, die für die meisten Provider ausreichend ist.
"auth0": {
"Type": "Oidc",
"ResponseType": "code",
"ClientId": "...",
"ClientSecret": "...",
"Authority": "https://cmiag.eu.auth0.com",
"MetadataAddress": "https://login.microsoftonline.com/xxx.xxx.xx.x/v2.0/.well-known/openid-configuration",
"CallbackPath": "/signin-oidc-auth0",
"SignedOutCallbackPath": "/signout-callback-oidc-auth0",
"Scope": [ "openid", "profile", "email", "phone", "address" ],
"IdClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"GetClaimsFromUserInfoEndpoint": "false"
}
-
Type
(erforderlich): Die Type-ID für OpenID Connect Provider lautetOidc
. -
ResponseType
(optional, Standardwert:id_token
): Legt den Response Type fest, den der CMI STS beim IDP anfordert. Es gibt folgende Optionen:code
: Ein Authorization Code wird angefordert. Für die Kommunikation mit dem IDP empfiehlt CMI wenn immer möglich den AuthorizationCode-Flow. Dieser Flow benötigt ein Client Secret.id_token
: Ein ID-Token wird angefordert. Standardmässig wird der Implicit Flow verwendet. Dieser Flow hat Schwächen und sollte nicht verwendet werden.token
: Ein Access-Token wird angefordert. Siehe auchGetClaimsFromUserInfoEndpoint
.- Eine Set der oben genannten Optionen, getrennt durch ein Leerzeichen. Beispielsweise fordert
token id_token
ein Access- und eine ID-Token an.
ClientId
(erforderlich): Die Client ID wird durch den IDP festgelegt und wird hierhin übertragen.ClientSecret
- Wenn
ResponseType=code
(erforderlich): Das Secret wird durch den IDP festgelegt und wird für den Authorization Code Flow benötigt. Mit diesem Secret authentifiziert sich der CMI STS gegenüber dem IDP. - Wenn
ResponseType=id_token
(ohne Wirkung): Der Implicit Flow verwendet kein Secret.
- Wenn
- *
Authority
(optional): Die Authority wird durch den IDP festgelegt und legt fest, unter welcher URL der CMI STS den IDP kontaktieren kann. - *
MetadataAddress
(optional): Die Meta-Daten-Adresse wird durch den IDP festgelegt und legt fest, unter welcher URL der CMI STS den IDP kontaktieren kann. CallbackPath
(optional, Standardwert:/signin-oidc
): Der Callback-Path teilt dem IDP mit, auf welche CMI STS URL er den Benutzer weiterleiten soll, nach dem der IDP den Benutzer authentifiziert hat. Der Callback-Path kann beliebig festgelegt werden, solange der Callback-Path eindeutig ist. Somit muss, wenn mehr als ein Oidc-IDP verwendet wird, der Callback-Path in jedem Fall festgelegt werden.SignedOutCallbackPath
(optional, Standardwert:/signout-callback-oidc
): Der Callback-Path teilt dem IDP mit, auf welche CMI STS URL er den Benutzer weiterleiten soll, nach dem der IDP den Benutzer abgemeldet hat. Der Callback-Path kann beliebig festgelegt werden, solange der Callback-Path eindeutig ist. Somit muss, wenn mehr als ein Oidc-IDP verwendet wird, der Callback-Path in jedem Fall festgelegt werden.Scopes
(optional, Standardwert:openid, profile
): Liste der Scopes aufgrund dessen der IDP Claims für den Benutzer ausstellt. Der IDP wird den Benutzer möglicherweise nach einem Einverständnis (Consent) fragen, bevor die Claims ausgestellt und an den CMI STS übertragen werden. Siehe hierzu auch Scopes und Ressourcen. Die Scopesopenid
undprofile
sind in jedem Fall erforderlich.IdClaimType
: Der Claim der für das Mapping des externen Benutzers auf einen CMI Benutzer verwendet wird. Der Debug-Log-Level schreibt die empfangenen Claims auf das Log. So lässt sich erkennen, wie der vom IDP ausgestellte Claim-Type lautet.GetClaimsFromUserInfoEndpoint
(optional, Standardwert:false
): Legt fest, ob neben den Claims, die im ID Token enthalten sind, weitere Claims vom UserInfo-Endpunkt des IDPs abgerufen werden sollen. Dieser Endpunkt erfordert die Angabe eines Access-Tokens. Somit muss sichergestellt werden, dass der CMI STS ein Access-Token vom IDP anfordert, in dem derResponseType
entsprechend konfiguriert wird. ** FolgendeResponseType
wurden erfolgreich mit dieser Option getestet:code
,token id_token
. Je nach IDP kann es ausserdem möglich sein, dass auf Seiten IDP weitere Konfigurationen erforderlich sind. Im Falle von Azure AD benötigt die App Registrierung bspw.User.Read
Delegated Permissions auf die Graph API. Die Berechtigung muss im AbschnittAPI-permissions
der App Registrierung hinzugefügt werden. Nachdem die Berechtigung hinzugefügt wurde, muss mit einem Azure AD Administrator noch der Consent bestätigt werden.
* Entweder eine Authority
oder eine MetadataAddress
muss spezifiziert werden. Eine der beiden Informationen muss bekannt sein, damit der IDP verwendet werden kann.
** Um zu prüfen, ob der CMI STS den UserInfo-Endpunkt aufgerufen hat, kann der Log-Level für den Namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
auf Verbose
eingestellt werden. Im Log werden folgende Nachrichten Retrieving claims from the user info endpoint. und User information received: System.Text.Json.JsonDocument aufgezeichnet. Werden die Nachrichten nicht aufgezeichnet, kann dies folgende Ursachen haben:
- Der IDP stellt keinen UserInfo-Endpunkt bereits oder dieser wird nicht im Discovery-Dokument (/.well-known/openid-configuration) durch den IDP bekannt gegeben.
- Der CMI STS hat kein Access-Token vom IDP erhalten. Siehe auch
ResponseType
.
Mehrere Issuer / OpenID Multitenant Azure AD
Wird ein IDP verwendet der mehrere Issuer unterstützt, wie z.B. Azure AD mit Gastbenutzern, muss die Authority
auf einen "wildcard" Tenant wie organizations gestellt werden. Die einzelnen Issuer werden als separate Liste in ValidIssuers
gepfleg
"azuread": {
// ... weitere Eigenschaften
"Authority": "https://login.microsoftonline.com/organizations/v2.0",
"TokenValidationParameters": {
"ValidIssuers": ["https://login.microsoftonline.com/{tenantid1}/v2.0", "https://login.microsoftonline.com/{tenantid2}/v2.0"]
// ... weitere Eigenschaften
}
}
Logos
Stehen mehrere Login-Möglichkeiten zur Verfügung, werden die IDP mit ihrem Namen aufgelistet. Wenn eine Grafik im SVG-Format verfügbar ist, wird diese Grafik anstatt dem IDP-Namen verwendet.
Die Grafik wird im Verzeichnis wwwroot/img/idp/\<provider name>.svg gesucht. Die Provider-Name entspricht dem Namen, der in der Konfiguration verwendet wird.
Beispiel:
wwwroot/img/idp/azure.svg
{
"Tenants": {
"mandant": {
"ExternalIdps": {
"azure": {}
}
}
}
}
Ein alternatives Verzeichnis kann konfiguriert werden, aus dem Logos geladen werden sollen. Die Konfiguration kann global für alle Mandanten oder pro Mandant festgelegt werden. Das Logo wird mit folgender Priorität ausgewählt:
- Aus dem mandanten-spezifischen alternativen Logo-Verzeichnis
- Aus dem global konfigurierten alternativen Logo-Verzeichnis
- Aus dem Verzeichnis wwwroot/img/idp/
- Wird keine SVG-Datei mit dem IDP-Namen gefunden, wird kein Logo angezeigt
{
"UiCustomization": {
"IdpLogoDirectory": "C:\\idp\\global"
},
"Tenants": {
"mandant": {
"UiCustomization": {
"IdpLogoDirectory": "C:\\idp\\mandant"
},
"ExternalIdps": {
"azure": {}
}
}
}
}
UiCustomization.IdpLogoDirectory
(optional, Standardwert:null
): Verzeichnis in dem nach SVG-Dateien für einen IDP gesucht werden soll. Unterverzeichnisse werden nicht berücksichtigt. Nicht existierende Verzeichnisse werden ignoriert. Es wird empfohlen einen absoluten Pfad zu verwenden.
Alternativer ID-Claim
Einen Benutzer im CMI werden sog. Externe Benutzer zugeordnet. Ein externer Benutzer besitzt die Eigenschaften Provider ID und Benutzer Id. Um einen Benutzer vom IDP einem CMI Benutzer zuzuordnen, wird ein ID-Claim der vom IDP ausgestellt wurde, mit der Benutzer Id verglichen.
Standardmässig wird der Claim sub oder http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier als ID-Claim verwendet, um den Benutzer im CMI zu identifizieren.
OIDC, WSFed: Ein alternativer ID-Claim kann mit der Option IdClaimType
festgelegt werden. Hat der IDP keinen Claim mit dem angegebenen Typen ausgestellt, wird der Login-Prozess abgebrochen.
Achtung: Es ist möglich, einen Claim anzugeben, der nicht eindeutig ist. Hat mehr als ein Benutzer für den angegeben Claim den selben Wert, werden diese Benutzer im CMI als der selbe Benutzer erkannt.
Das folgende Beispiel konfiguriert den IDP mit der Provider-ID openid und den ID-Claim name. Im CMI ist ein passender externer Benutzer hinterlegt.
"openid": {
"Type": "Oidc",
"IdClaimType": "name"
...
}
Provider SignOut
Wenn sich ein Benutzer abmeldet, wird er zum CMI STS umgeleitet, der die Abmeldung vornimmt. Hat sich der Benutzer über einen IDP angemeldet, wird der Benutzer nur vom CMI STS abgemeldet, jedoch nicht beim IDP.
Web Client: Wenn "Automatische Wahl der Identity Provider" verwendet wird, hat dies zur Folge, dass der Benutzer nach der Abmeldung möglicherweise sofort wieder angemeldet wird. Nach der Abmeldung wird der Benutzer zurück zur ursprünglichen Anwendung umgeleitet. Die Anwendung bemerkt, dass der Benutzer nicht mehr angemeldet ist und leitet auf den CMI STS um, der wiederum eine automatische Weiterleitung am dem IDP durchführt. Da der Benutzer beim IDP nicht abgemeldet ist, erhält der CMI STS ein ID Token, ohne dass der Benutzer selbst eine Aktion tätigen muss und der Benutzer wird wieder angemeldet.
Wenn eine Abmeldung auch beim IDP erfolgen soll, kann dies explizit für den IDP aktiviert werden.
Achtung: Wenn sich der Benutzer bei anderen Anwendungen mit dem selben IDP angemeldet hat, wird er möglicherweise auch bei diesen Anwendungen abgemeldet.
WsFed:
- Die Option
UseProviderSignOut
muss den Werttrue
haben. - Der IDP muss die Redirect-Uri
https://<CMI STS Basis Url>/<Mandant>/identity/Account/Logout
akzeptieren.
"wsfed": {
"Type": "Wsfed",
"UseProviderSignOut": "true"
...
}
OIDC:
- Die Option
UseProviderSignOut
muss den Werttrue
haben. - Die Option
SignedOutRedirectUri
muss auf eine Logout-Uri konfiguriert werden, die durch den IDP bestimmt wird. Der Benutzer wird nach der Abmeldung am CMI STS auf diese Url umgeleitet.
"openid": {
"Type": "Oidc",
"UseProviderSignOut": "true",
"SignedOutRedirectUri": "<IDP spezifische Logout-Url>"
...
}
Automatisches Benutzer anlegen
Benutzer aus dem IDP können automatisch im CMI angelegt werden. Dazu muss das Feld "Neue Benutzer:in automatisch anlegen" im Desktop Client in den Servereinstellungen aktiviert werden. Das automatische Anlegen sollte immer in Kombination mit dem Gruppen- und Feldmapping verwendet werden.
Gruppen- und Feldmapping
Wenn der CMI Server den CMI STS 3 erkennt, werden im Desktop Client in den Servereinstellungen Mapping-Dialoge freigeschaltet. Darüber können Claims, die der IDP ausstellt, in CMI übernommen werden.
Release 23: SSO mit WebView2
Die unten aufgeführte Option wird spezifisch für den Login-Prozess ab Release >=24.0.9 und >=25.0 automatisch aktiviert. Die Startoption ist für den SSO-Login-Prozess nicht mehr erforderlich. Wenn andere Funktionen des Desktop Clients die
WebView2
-Komponente verwenden, ist diese Option nicht automatisch aktiviert. In diesem Fall kann bei Bedarf die Startoption gesetzt werden.
Ab Release 23 des CMI Servers (R23) wird die sog. WebView2
als Browser-Engine im Desktop Client verwendet, über die auch das Login am CMI STS erfolgt. Um weniger Angriffsfläche, z.B. für Cookie-Stealing, zu bieten, sind einige Funktionen in dieser Engine deaktiviert, was ein Single Sign-On am Identity Provider verhindern kann.
Dieses Verhalten kann ab Release 23.0.11 beim Start der CMI.Client.Main.exe
übersteuert werden. Das zusätzliche Startargument hierfür lautet:
CMI.Client.Main.exe --WebView2EnableSso true