Custom Login Flow & Context Check Interceptor

Archiv

Dieser Artikel ist ein Community-Beitrag für Shibboleth IdP 3.x. Es ist unklar, ob er für Shibboleth IdP 4.x so noch gilt.

Was ist das:
Unter den Begriffen versteht man Modelle, mit deren Hilfe man das Nutzererfahren beim Login an individuelle Vorgaben anpassen kann.
Dabei kann der Ablauf durch beliebige Schritte und Prüfungen erweitert werden.
Analog ist dies z.B. mit den Terms-Of-Use oder dem Attribute-Release gleichzusetzen.
Der Gestaltung sind hierbei keine Grenzen gesetzt, da man auf alle Informationen zugreifen kann, die innerhalb des normalen Login-Vorgangs vorhanden sind.

Beispiele für Anwendungsszenarien:

In das Installationsverzeichnis wechseln.
Neue Config-File samt Conditions anlegen wie im Abschnitt Activation Conditions beschrieben.

conf/activation-conditions.xml
<!-- ... -->
	<bean id="user-is-functional" class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate" p:useUnfilteredAttributes="true">
		<property name="attributeValueMap">
			<map>
				<entry key="groupmemberOf">
					<list>
						<value>cn=idmgrp-functions-org-10000000,ou=groups,dc=yourdomain,dc=de</value>
					</list>
				</entry>
			</map>
		</property>
	</bean>
 
	<bean id="SP-is-in-DFNAAI" parent="shibboleth.Conditions.EntityDescriptor">
		<constructor-arg name="pred">
			<bean class="org.opensaml.saml.common.profile.logic.RegistrationAuthorityPredicate"
				<constructor-arg>
					<list>
						<value>https://www.aai.dfn.de</value>
					</list>
				</constructor-arg>
			</bean>
		</constructor-arg>
	</bean>
 
	<bean id="SP-allow-functional-user" parent="shibboleth.Conditions.RelyingPartyId">
		<constructor-arg name="candidates">
			<list>
				<value>https://your.sp.de/shibboleth</value>
			</list>
		</constructor-arg>
	</bean>
 
	<bean id="login-proceed" parent="shibboleth.Conditions.OR">
		<constructor-arg>
			<list>
				<bean parent="shibboleth.Conditions.NOT">
					<constructor-arg>
						<list>
							<ref bean="user-is-functional" />
						</list>
					</constructor-arg>
				</bean>
				<bean parent="shibboleth.Conditions.NOT">
					<constructor-arg>
						<list>
							<ref bean="SP-is-in-DFNAAI" />
						</list>
					</constructor-arg>
				</bean>
				<ref bean="SP-allow-functional-user" />
			</list>
		</constructor-arg>
	</bean>
<!-- ... -->

Den Standard Check-Interceptor kopieren und an die eingenen Bedürfnisse anpassen.

# mkdir -p flows/intercept/functional-user-check
# cp system/flows/intercept/context-check-flow.xml flows/intercept/functional-user-check/functional-user-check-flow.xml
# cp system/flows/intercept/context-check-beans.xml flows/intercept/functional-user-check/functional-user-check-beans.xml

Neuen Interceptor-Flow definieren.

flows/intercept/functional-user-check/functional-user-check-flow.xml
<!--...-->
	<bean-import resource="functional-user-check-beans.xml" />
<!--...-->

Datei mit den nötigen Conditions verlinken.

flows/intercept/functional-user-check/functional-user-check-beans.xml
<!--...-->
	<import resource="../../../conf/activation-conditions.xml" />
	<alias name="login-proceed" alias="ContextCheckPredicate"/>
<!--...-->

Interceptor-Flow bekannt machen.

conf/intercept/profile-intercept.xml
<!--...-->
	<bean id="intercept/functional-user-check" parent="shibboleth.InterceptFlow"/>
<!--...-->

Abbruch-Event überschreiben, falls eigene Fehlermeldungen ausgegeben werden möchten.

flows/intercept/functional-user-check/functional-user-check-flow.xml
<!--...-->
	then="proceed" else="FunctionalUserCheckDenied" />
<!--...-->

Abbruch-Event definieren und mit gewünschten Error-Messages verlinken.

conf/intercept/intercept-events-flow.xml
<!--...-->
	<end-state id="FunctionalUserCheckDenied" />
	<global-transitions>
		<transition on="FunctionalUserCheckDenied" to="FunctionalUserCheckDenied" />
	</global-transitions>
<!--...-->

Event als lokales Event definieren, so dass der Login-Vorgang abgebrochen wird und der Nutzer am IdP verweilt, statt eine Antwort an den SP zu senden.

conf/errors.xml
<!--...-->
	<util:map id="shibboleth.LocalEventMap">
		<entry key="FunctionalUserCheckDenied" value="true" />
<!--...-->

Zu verwendende Fehlermeldungen definieren.

messages/error-messages_de.properties (error-messages.properties)
<!--...-->
	FunctionalUserCheckDenied                       = functional
	functional.title                                = Zugang verweigert
	functional.message                              = Funktionsaccounts sind für diesen Dienst nicht zul\u00E4ssig.
<!--...-->

Neuen Interceptor-Flow für die gewünschten Relying-Parties aktivieren.

conf/relying-party.xml
<!--...-->
	<bean parent="SAML2.SSO" p:postAuthenticationFlows="#{{'functional-user-check', 'attribute-release'}}"
<!--...-->

Links / Dokumentation: