Dies ist eine alte Version des Dokuments!
Shibboleth IdP als OpenID Connect - Provider
Danke
Der Dank für diese Dokumentation geht an Manuel Haim von der Philipps-Universität Marburg.Die OIDC-Login-Schnittstelle wird für Webanwendungen benötigt, die ausschließlich das OIDC- bzw. OAuth-2.0-Protokoll unterstützen.
Installation der Plugins
Plugins herunterladen
root@idp:~# cd /opt/install/ root@idp:~# curl -O https://shibboleth.net/downloads/identity-provider/plugins/oidc-common/1.1.0/oidc-common-dist-1.1.0.tar.gz root@idp:~# curl -O https://shibboleth.net/downloads/identity-provider/plugins/oidc-common/1.1.0/oidc-common-dist-1.1.0.tar.gz.asc root@idp:~# curl -O https://shibboleth.net/downloads/identity-provider/plugins/oidc-op/3.0.1/idp-plugin-oidc-op-distribution-3.0.1.tar.gz root@idp:~# curl -O https://shibboleth.net/downloads/identity-provider/plugins/oidc-op/3.0.1/idp-plugin-oidc-op-distribution-3.0.1.tar.gz.asc
Installation über HTTP-Proxy
Bei der Installation prüft der Plugin-Installer online die Kompatibilität der Plugin-Version zur Shibboleth-Version. Falls der Shibboleth-IdP nur über einen HTTP-Proxy Zugriff zum Internet erhält, muss für die Plugin-Installation zunächst ein HTTP-Proxy konfiguriert werden.
Im IdP <= 4.1.2 gibt es einen Bug (vgl. https://issues.shibboleth.net/jira/browse/IDP-1838), hier lässt sich die Kompatibilitäts-Prüfung mittels Parameter --nocheck
umgehen:
root@idp:~# /opt/shibboleth-idp/bin/plugin.sh --nocheck -i oidc-common-dist-1.1.0.tar.gz root@idp:~# /opt/shibboleth-idp/bin/plugin.sh --nocheck -i idp-plugin-oidc-op-distribution-3.0.1.tar.gz
Zur Konfiguration des HTTP-Proxy (IdP >= 4.1.3) müssen wir eine Datei /opt/install/beanfile.xml
mit eigenen HttpClient-Parametern anlegen:
- /opt/install/beanfile.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-init-method="initialize" default-destroy-method="destroy"> <!-- HttpClient bean for plugin installation. Use with /opt/shibboleth-idp/bin/plugin.sh -hc <BeanName> -i <plugin.tar.gz> <this-file.xml> --> <bean id="myHttpClient" parent="shibboleth.HttpClientFactory" p:connectionProxyHost="http-proxy.example.org" p:connectionProxyPort="3128" /> </beans>
Und dann mit folgenden Parametern installieren:
root@idp:~# /opt/shibboleth-idp/bin/plugin.sh -hc myHttpClient -i oidc-common-dist-1.1.0.tar.gz beanfile.xml root@idp:~# /opt/shibboleth-idp/bin/plugin.sh -hc myHttpClient -i idp-plugin-oidc-op-distribution-3.0.1.tar.gz beanfile.xml
Installation ohne HTTP-Proxy
root@idp:~# /opt/shibboleth-idp/bin/plugin.sh -i oidc-common-dist-1.1.0.tar.gz 2021-07-21 11:07:04,309 - INFO [net.shibboleth.idp.installer.plugin.impl.PluginInstaller:233] - Installing Plugin net.shibboleth.oidc.common version 1.1.0 Installing Plugin net.shibboleth.oidc.common version 1.1.0 2021-07-21 11:07:04,400 - INFO [net.shibboleth.idp.installer.BuildWar:225] - Rebuilding /opt/shibboleth-idp/war/idp.war, Version 4.1.2 Rebuilding /opt/shibboleth-idp/war/idp.war, Version 4.1.2 2021-07-21 11:07:04,445 - INFO [net.shibboleth.idp.installer.BuildWar:225] - Initial populate from /opt/shibboleth-idp/dist/webapp to /opt/shibboleth-idp/webpapp.tmp Initial populate from /opt/shibboleth-idp/dist/webapp to /opt/shibboleth-idp/webpapp.tmp 2021-07-21 11:07:05,614 - INFO [net.shibboleth.idp.installer.BuildWar:225] - Overlay from /opt/shibboleth-idp/dist/plugin-webapp to /opt/shibboleth-idp/webpapp.tmp Overlay from /opt/shibboleth-idp/dist/plugin-webapp to /opt/shibboleth-idp/webpapp.tmp 2021-07-21 11:07:05,670 - INFO [net.shibboleth.idp.installer.BuildWar:225] - Overlay from /opt/shibboleth-idp/edit-webapp to /opt/shibboleth-idp/webpapp.tmp Overlay from /opt/shibboleth-idp/edit-webapp to /opt/shibboleth-idp/webpapp.tmp 2021-07-21 11:07:05,736 - INFO [net.shibboleth.idp.installer.BuildWar:217] - Creating war file /opt/shibboleth-idp/war/idp.war Creating war file /opt/shibboleth-idp/war/idp.war
root@idp:~# /opt/shibboleth-idp/bin/plugin.sh -i idp-plugin-oidc-op-distribution-3.0.1.tar.gz Plugin net.shibboleth.idp.plugin.oidc.op: Trust store folder does not exist, creating Plugin net.shibboleth.idp.plugin.oidc.op: Trust store does not exist, creating TrustStore does not contain signature 0X26691839355EBCA Accept this key: Signature: 0X26691839355EBCA FingerPrint: 6D18FD63708FCCA079B68CCE026691839355EBCA Username: Henri Mikkonen <henri.mikkonen@iki.fi> [yN] y Installing Plugin net.shibboleth.idp.plugin.oidc.op version 3.0.1 Rebuilding /opt/shibboleth-idp/war/idp.war, Version 4.1.2 Initial populate from /opt/shibboleth-idp/dist/webapp to /opt/shibboleth-idp/webpapp.tmp Overlay from /opt/shibboleth-idp/dist/plugin-webapp to /opt/shibboleth-idp/webpapp.tmp Overlay from /opt/shibboleth-idp/edit-webapp to /opt/shibboleth-idp/webpapp.tmp Creating war file /opt/shibboleth-idp/war/idp.war Module file changes as a result of this install conf/oidc-clientinfo-resolvers.xml created static/openid-configuration.json created bin/lib/json-web-key-generator-0.8.2-jar-with-dependencies.jar created conf/oidc-credentials.xml created conf/attributes/oidc-claim-rules.xml created bin/jwtgen.sh created conf/examples/oidc-attribute-filter.xml created bin/jwtgen.bat created conf/oidc.properties created conf/examples/oidc-attribute-resolver.xml created
Konfiguration
Datei /opt/shibboleth-idp/conf/credentials.xml
anpassen:
- /opt/shibboleth-idp/conf/credentials.xml
... <!-- OIDC extension default credential definitions --> <import resource="oidc-credentials.xml" /> ...
Datei /opt/shibboleth-idp/conf/attributes/default-rules.xml anpassen:
- /opt/shibboleth-idp/conf/attributes/default-rules.xml
... <import resource="oidc-claim-rules.xml" /> ...
JSON Web Keys erzeugen:
root@idp:~# /opt/shibboleth-idp/bin/jwtgen.sh -t RSA -s 2048 -u sig -i defaultRSASign | tail -n +2 >/opt/shibboleth-idp/credentials/idp-signing-rs.jwk root@idp:~# /opt/shibboleth-idp/bin/jwtgen.sh -t EC -c P-256 -u sig -i defaultECSign | tail -n +2 >/opt/shibboleth-idp/credentials/idp-signing-es.jwk root@idp:~# /opt/shibboleth-idp/bin/jwtgen.sh -t RSA -s 2048 -u enc -i defaultRSAEnc | tail -n +2 >/opt/shibboleth-idp/credentials/idp-encryption-rsa.jwk
Datei /opt/shibboleth-idp/conf/oidc.properties
anpassen:
- /opt/shibboleth-idp/conf/oidc.properties
... idp.oidc.issuer = https://idp.example.org ...
Bereitstellen der Konfigurationsparameter für OIDC-RPs
Wir wollen unter https://idp.example.org/.well-known/openid-configuration die Konfigurationsparameter dynamisch bereitstellen, vgl. https://shibboleth.atlassian.net/wiki/spaces/IDPPLUGINS/pages/1376879256/OPDiscovery
In der Datei /opt/shibboleth-idp/static/openid-configuration.json
muss jeweils {{ service_name }}
durch Ihren Wert für idp.example.org
ausgetauscht werden.
Datei /opt/shibboleth-idp/conf/relying-party.xml
bearbeiten:
- /opt/shibboleth-idp/conf/relying-party.xml
... <bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <list> <bean parent="OIDC.Configuration" /> <!-- <bean parent="SAML2.SSO" p:encryptAssertions="false" /> --> </list> </property> </bean> ...
In unserem Fall wird alles unter dem URL-Pfad /idp/
vom Tomcat bereitgestellt, der Basispfad /
hingegen von Apache (Einrichtung weiter unten). Daher müssen wir das Redirect für /.well-known/openid-configuration
im Apache einrichten, wie nachfolgend beschrieben:
Datei /etc/apache2/sites-enabled/25-apache-443.conf
(oder ähnlich) bearbeiten:
... Redirect seeother /.well-known/openid-configuration https://idp.example.org/idp/profile/oidc/configuration ...
Alternativ können die Konfigurationsparameter wie folgt statisch bereitgestellt werden (erfordert a2enmod headers
):
Alias /.well-known/openid-configuration /opt/shibboleth-idp/static/openid-configuration.json <Location "/.well-known/openid-configuration"> ForceType application/json Header set Access-Control-Allow-Origin * </Location>
OIDC-Profile aktivieren
Schließlich müssen noch die entsprechenden OIDC-Profile in Shibboleth aktiviert werden. Wir wollen OIDC-Clients manuell hinzufügen und lassen das Profil „OIDC-Registration“ daher weg. Außerdem sollen auch beim OIDC-Login dieselben Flows wie beim Shibboleth-Login berücksichtigt werden.
Datei /opt/shibboleth-idp/conf/relying-party.xml
bearbeiten:
- /opt/shibboleth-idp/conf/relying-party.xml
... <bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <list> <bean parent="OIDC.Configuration" /> <bean parent="OIDC.Keyset" /> <!-- <bean parent="SAML2.SSO" p:encryptAssertions="false" /> --> </list> </property> </bean> ... <!-- Default configuration, with default settings applied for all profiles. --> <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <list> ... <bean parent="OIDC.SSO" p:postAuthenticationFlows="#{ {'terms-of-use', 'context-check', 'attribute-release'} }" /> <ref bean="OIDC.UserInfo" /> <ref bean="OAUTH2.Revocation" /> <ref bean="OAUTH2.Introspection" /> </list> </property> </bean> ...
Tomcat und Apache neustarten:
root@idp:~# systemctl restart tomcat9 root@idp:~# systemctl restart apache2
Wenn soweit alles ohne Fehler läuft (vgl. Shibboleth-Logs), können wir die Attribute konfigurieren.
Attribute
Für OIDC sollten eine globale subject-id und/oder eine anwendungsbezogene pairwise-id definiert werden. Nachfolgend ein Beispiel basierend auf uid und persistentId:
In der Datei /opt/shibboleth-idp/conf/attribute-resolver.xml
weitere Attribute analog zu /opt/shibboleth-idp/conf/examples/oidc-attribute-resolver.xml
ergänzen:
- /opt/shibboleth-idp/conf/attribute-resolver.xml
<?xml version="1.0" encoding="UTF-8"?> <AttributeResolver xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oidc="urn:mace:shibboleth:2.0:resolver:oidc" xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd urn:mace:shibboleth:2.0:resolver:oidc http://shibboleth.net/schema/oidc/shibboleth-attribute-encoder-oidc.xsd"> ... <!-- OIDC subjects --> <AttributeDefinition id="subject-public" xsi:type="Scoped" scope="%{idp.scope}" activationConditionRef="shibboleth.oidc.Conditions.PublicRequired"> <InputDataConnector ref="myLDAP_account" attributeNames="uid" /> <AttributeEncoder xsi:type="oidc:OIDCScopedString" name="sub" /> </AttributeDefinition> <AttributeDefinition id="subject-pairwise" xsi:type="Scoped" scope="%{idp.scope}" activationConditionRef="shibboleth.oidc.Conditions.PairwiseRequired"> <InputDataConnector ref="myStoredId" attributeNames="persistentId"/> <AttributeEncoder xsi:type="oidc:OIDCScopedString" name="sub" /> </AttributeDefinition> <!-- gender --> <AttributeDefinition id="gender" xsi:type="Mapped"> <InputDataConnector ref="myLDAP_people" attributeNames="UniMrAnrede" /> <DefaultValue></DefaultValue> <ValueMap> <ReturnValue>male</ReturnValue> <SourceValue>Herr</SourceValue> </ValueMap> <ValueMap> <ReturnValue>female</ReturnValue> <SourceValue>Frau</SourceValue> </ValueMap> </AttributeDefinition> ...
In Datei /opt/shibboleth-idp/conf/attribute-filter.xml
weitere Attribute analog zu /opt/shibboleth-idp/conf/examples/oidc-attribute-filter.xml
ergänzen:
- /opt/shibboleth-idp/conf/attribute-filter.xml
... <!-- OIDC scopes --> <AttributeFilterPolicy id="OPENID_SCOPE"> <PolicyRequirementRule xsi:type="oidc:OIDCScope" value="openid" /> <AttributeRule attributeID="subject-public"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="subject-pairwise"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy> <AttributeFilterPolicy id="OPENID_SCOPE_EMAIL"> <PolicyRequirementRule xsi:type="oidc:OIDCScope" value="email" /> <AttributeRule attributeID="mail"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="email_verified"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy> <AttributeFilterPolicy id="OPENID_SCOPE_PROFILE"> <PolicyRequirementRule xsi:type="oidc:OIDCScope" value="profile" /> <AttributeRule attributeID="displayName"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="sn"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="givenName"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="uid"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="gender"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="eduPersonPrincipalName"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy> ...
OIDC-RPs anbinden
OIDC-Clients (Relying Party, RP) können am besten über XML-Metadaten hinzugefügt werden, vgl. https://shibboleth.atlassian.net/wiki/spaces/SC/pages/1912406916/OAuthRPMetadataProfile.
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:oidcmd="urn:mace:shibboleth:metadata:oidc:1.0" entityID="rp.example.org"> <md:SPSSODescriptor protocolSupportEnumeration="http://openid.net/specs/openid-connect-core-1_0.html"> <md:Extensions> <oidcmd:OAuthRPExtensions grant_types="authorization_code" response_types="code" token_endpoint_auth_method="client_secret_basic" scopes="openid profile email" /> <mdui:UIInfo xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui"> <mdui:DisplayName xml:lang="de">Beispiel-OIDC-RP</mdui:DisplayName> <mdui:DisplayName xml:lang="en">Example OIDC RP</mdui:DisplayName> <mdui:Description xml:lang="de">Beispiel-OIDC-RP der Hochschule XY.</mdui:Description> <mdui:Description xml:lang="en">Example OIDC RP of University XY.</mdui:Description> <mdui:InformationURL xml:lang="de">https://rp.example.org</mdui:InformationURL> <mdui:InformationURL xml:lang="en">https://rp.example.org</mdui:InformationURL> <mdui:Logo height="93" width="260">https://rp.example.org/logo.png</mdui:Logo> </mdui:UIInfo> </md:Extensions> <md:KeyDescriptor> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <oidcmd:ClientSecret>HIER-STEHT-EIN-GEHEIMES-SECRET</oidcmd:ClientSecret> </ds:KeyInfo> </md:KeyDescriptor> <md:NameIDFormat>urn:mace:shibboleth:metadata:oidc:1.0:nameid-format:public</md:NameIDFormat> <md:AssertionConsumerService Binding="https://tools.ietf.org/html/rfc6749#section-3.1.2" Location="https://rp.example.org/OIDC-ODER-OAUTH-ENDPOINT" index="1"/> </md:SPSSODescriptor> <md:Organization> <md:OrganizationDisplayName xml:lang="de">Hochschule XY</md:OrganizationDisplayName> <md:OrganizationDisplayName xml:lang="en">University XY</md:OrganizationDisplayName> <md:OrganizationURL xml:lang="de">https://www.example.org</md:OrganizationURL> <md:OrganizationURL xml:lang="en">https://www.example.org</md:OrganizationURL> </md:Organization> </md:EntityDescriptor>
Für jeden OIDC-Client muss eine client_id festgelegt werden (z.B. 32 Hex-Zeichen langer Zufallswert oder ein FQDN, aber keine URL) sowie ein client_secret (z.B. per makepasswd --chars=32
) und die redirect_uri.
Die für die Client-Konfiguration nötigen Parameter können per https://idp.example.org/.well-known/openid-configuration
abgefragt werden. Nicht unterstützte Scopes sollten in /opt/shibboleth-idp/static/openid-configuration.json
entfernt werden.
Die freigegebenen Shibboleth-Attribute werden gemäß /opt/shibboleth-idp/conf/attributes/oidc-claim-rules.xml
in OIDC-Attribute übersetzt.
Weitere Hinweise
Das OIDC-Plugin unterstützt bislang noch kein Logout, und die OIDC-RPs werden auch nicht auf der Logout-Seite angezeigt: https://issues.shibboleth.net/jira/browse/JOIDC-13
Die OIDC-Attribute werden im Attribute Release bislang nur mit englischen Beschreibungstexten angezeigt. Zur Korrektur müssen die entsprechenden deutschen Beschreibungstexte unter /opt/shibboleth-idp/conf/attributes/oidc-claim-rules.xml
ergänzt werden.