[java-oidc-common] 01/01: JCOMOIDC-48 - Move OIDC.SSO profile bean to commons
Phil Smart
philip.smart at jisc.ac.uk
Thu Feb 2 14:53:34 UTC 2023
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch dev/JCOMOIDC-48
in repository java-oidc-common.
View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=4b0f057bfbe7a9b85925382d5f3ad1ba7941c9f1
commit 4b0f057bfbe7a9b85925382d5f3ad1ba7941c9f1
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Tue Jan 31 09:57:54 2023 +0000
JCOMOIDC-48 - Move OIDC.SSO profile bean to commons
- Move profile beans, related classes, and related config to commons
https://shibboleth.atlassian.net/browse/JCOMOIDC-48
---
.../common/conf/attributes/oidc-claim-rules.xml | 428 +++++++++++++++++++++
.../oidc/common/conf/authn/oidc-credentials.xml | 75 ++++
.../net/shibboleth/oidc/common/module.properties | 9 +
.../config/AbstractOIDCSSOConfiguration.java | 44 ++-
.../profile/config/CredentialsListFactory.java | 65 ++++
.../config/OIDCAuthorizationConfiguration.java | 148 +------
...nticationContextClassRequestLookupFunction.java | 114 ++++++
...ticationContextClassResponseLookupFunction.java | 115 ++++++
...th2ClientAuthenticableProfileConfiguration.java | 131 ++++++-
.../META-INF/net.shibboleth.idp/postconfig.xml | 28 ++
.../idp/service/attribute/registry/postconfig.xml | 25 ++
.../idp/service/relying-party/postconfig.xml | 328 ++++++++++++++++
.../profile/config/CredentialsListFactoryTest.java | 83 ++++
...thenticationContextClassLookupFunctionTest.java | 134 +++++++
...tionContextClassResponseLookupFunctionTest.java | 127 ++++++
15 files changed, 1705 insertions(+), 149 deletions(-)
diff --git a/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/conf/attributes/oidc-claim-rules.xml b/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/conf/attributes/oidc-claim-rules.xml
new file mode 100644
index 0000000..9de853b
--- /dev/null
+++ b/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/conf/attributes/oidc-claim-rules.xml
@@ -0,0 +1,428 @@
+<?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">
+
+ <!-- https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims -->
+
+ <bean parent="shibboleth.TranscodingRuleLoader">
+ <constructor-arg>
+ <list>
+
+ <!-- Typical inetOrgPerson attributes that map to standard claims. -->
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">displayName</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">name</prop>
+ <prop key="displayName.en">Display name</prop>
+ <prop key="displayName.de">Anzeigename</prop>
+ <prop key="displayName.fr">Nom</prop>
+ <prop key="displayName.it">Nome</prop>
+ <prop key="displayName.ja">表示名</prop>
+ <prop key="description.en">The name that should appear in white-pages-like applications for this person.</prop>
+ <prop key="description.de">Anzeigename</prop>
+ <prop key="description.fr">Nom complet d'affichage</prop>
+ <prop key="description.it">Nome</prop>
+ <prop key="description.ja">アプリケーションでの表示に用いられる英字氏名</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">givenName</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">given_name</prop>
+ <prop key="displayName.en">Given name</prop>
+ <prop key="displayName.de">Vorname</prop>
+ <prop key="displayName.fr">Prénom</prop>
+ <prop key="displayName.it">Nome</prop>
+ <prop key="displayName.ja">名</prop>
+ <prop key="description.en">Given name of a person</prop>
+ <prop key="description.de">Vorname</prop>
+ <prop key="description.fr">Prénom de l'utilisateur</prop>
+ <prop key="description.it">Nome</prop>
+ <prop key="description.ja">氏名(名)の英語表記</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">homePhone</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">phone_number</prop>
+ <prop key="displayName.en">Private phone number</prop>
+ <prop key="displayName.de">Telefon Privat</prop>
+ <prop key="displayName.fr">Teléphone personnel</prop>
+ <prop key="displayName.it">Numero di telefono privato</prop>
+ <prop key="displayName.ja">自宅電話番号</prop>
+ <prop key="description.en">Private phone number</prop>
+ <prop key="description.de">Private Telefonnummer</prop>
+ <prop key="description.fr">Numéro de téléphone de domicile de la personne</prop>
+ <prop key="description.it">Numero di telefono privato</prop>
+ <prop key="description.ja">自宅の電話番号</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">mail</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">email</prop>
+ <prop key="displayName.en">E-mail</prop>
+ <prop key="displayName.de">E-Mail</prop>
+ <prop key="displayName.fr">Email</prop>
+ <prop key="displayName.it">E-mail</prop>
+ <prop key="displayName.ja">メールアドレス</prop>
+ <prop key="description.en">E-Mail: Preferred address for e-mail to be sent to this person</prop>
+ <prop key="description.de">E-Mail-Adresse</prop>
+ <prop key="description.de-ch">E-Mail Adresse</prop>
+ <prop key="description.fr">Adresse de courrier électronique</prop>
+ <prop key="description.it">E-Mail: l'indirizzo e-mail preferito dall'utente</prop>
+ <prop key="description.ja">メールアドレス</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">preferredLanguage</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">locale</prop>
+ <prop key="displayName.en">Preferred Language</prop>
+ <prop key="displayName.de">Bevorzugte Sprache</prop>
+ <prop key="displayName.fr">Langue préférée</prop>
+ <prop key="displayName.it">Lingua preferita</prop>
+ <prop key="displayName.ja">希望言語</prop>
+ <prop key="description.en">Preferred language: Users preferred language (see RFC1766)</prop>
+ <prop key="description.de">Bevorzugte Sprache (siehe RFC1766)</prop>
+ <prop key="description.fr">Exemple: fr, de, it, en, ... (voir RFC1766)</prop>
+ <prop key="description.it">Lingua preferita: la lingua preferita dall'utente (cfr. RFC1766)</prop>
+ <prop key="description.ja">利用者が希望する言語(RFC1766 を参照)</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">sn</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">family_name</prop>
+ <prop key="displayName.en">Surname</prop>
+ <prop key="displayName.de">Nachname</prop>
+ <prop key="displayName.fr">Nom de famille</prop>
+ <prop key="displayName.it">Cognome</prop>
+ <prop key="displayName.ja">姓</prop>
+ <prop key="description.en">Surname or family name</prop>
+ <prop key="description.de">Familienname</prop>
+ <prop key="description.fr">Nom de famille de l'utilisateur.</prop>
+ <prop key="description.it">Cognome dell'utilizzatore</prop>
+ <prop key="description.ja">氏名(姓)の英語表記</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">telephoneNumber</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">phone_number</prop>
+ <prop key="displayName.en">Business phone number</prop>
+ <prop key="displayName.de">Telefon Geschäft</prop>
+ <prop key="displayName.fr">Teléphone professionnel</prop>
+ <prop key="displayName.it">Numero di telefono dell'ufficio</prop>
+ <prop key="displayName.ja">所属機関内電話番号</prop>
+ <prop key="description.en">Business phone number: Office or campus phone number</prop>
+ <prop key="description.de">Telefonnummer am Arbeitsplatz</prop>
+ <prop key="description.fr">Teléphone de l'institut, de l'université</prop>
+ <prop key="description.it">Numero di telefono dell'ufficio</prop>
+ <prop key="description.ja">所属機関での利用者の電話番号</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">uid</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">preferred_username</prop>
+ <prop key="displayName.en">User ID</prop>
+ <prop key="displayName.de">Benutzer-ID</prop>
+ <prop key="displayName.fr">ID utilisateur</prop>
+ <prop key="displayName.it">ID dell'utente</prop>
+ <prop key="displayName.ja">ユーザID</prop>
+ <prop key="description.en">A unique identifier for a person, mainly used for user identification within the user's home organization.</prop>
+ <prop key="description.de">Eine eindeutige Nummer für eine Person, welche hauptsächlich zur Identifikation innerhalb der Organisation benutzt wird.</prop>
+ <prop key="description.fr">Identifiant de connexion d'une personnes sur les systèmes informatiques.</prop>
+ <prop key="description.it">Identificativo unico della persona, usato per l'identificazione dell'utente all'interno della organizzazione di appartenenza.</prop>
+ <prop key="description.ja">所属機関内で一意の利用者識別子</prop>
+ </props>
+ </property>
+ </bean>
+
+ <!-- eduPerson attributes that map to standard claims. -->
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">eduPersonNickname</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">nickname</prop>
+ <prop key="displayName.en">Nickname</prop>
+ <prop key="displayName.de">Kurzname</prop>
+ <prop key="displayName.de-ch">Übername</prop>
+ <prop key="displayName.fr">Surnom</prop>
+ <prop key="displayName.it">Diminutivo</prop>
+ <prop key="displayName.ja">ニックネーム</prop>
+ <prop key="description.en">Person's nickname, or the informal name by which they are accustomed to be hailed.</prop>
+ <prop key="description.de">Kurzname einer Person, oder üblicher Rufname zur Begrüßung.</prop>
+ <prop key="description.de-ch">Übername einer Person, oder üblicher Rufname zur Begrüssung.</prop>
+ <prop key="description.fr">Nom personnalisable pour un usage informel.</prop>
+ <prop key="description.it">Diminutivo della persona, o soprannome.</prop>
+ <prop key="description.ja">利用者のニックネームもしくは通称</prop>
+ </props>
+ </property>
+ </bean>
+
+ <!-- A subset of the major eduPerson attributes that have no standard claim mapping. -->
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">eduPersonAssurance</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">eduPersonAssurance</prop>
+ <prop key="displayName.en">Assurance level</prop>
+ <prop key="displayName.de">Vertrauensgrad</prop>
+ <prop key="displayName.fr">Niveau de confiance</prop>
+ <prop key="displayName.it">Livello di sicurezza</prop>
+ <prop key="displayName.ja">保証レベル</prop>
+ <prop key="description.en">Set of URIs that assert compliance with specific standards for identity assurance.</prop>
+ <prop key="description.de">URIs die eine gewisse Zusicherung für spezifische Standards des Vertrauens beinhalten</prop>
+ <prop key="description.fr">Un ensemble d'URI qui attestent la conformité selon un standard pour les niveaux d'assurance d'identités</prop>
+ <prop key="description.it">Un insieme di URI che asseriscono l'osservanza dei livelli di sicurezza richiesti</prop>
+ <prop key="description.ja">IDの保証レベルに関して特定の基準に準拠していることを示すURI</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">eduPersonEntitlement</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">eduPersonEntitlement</prop>
+ <prop key="displayName.en">Entitlement</prop>
+ <prop key="displayName.de">Berechtigung</prop>
+ <prop key="displayName.fr">Entitlement</prop>
+ <prop key="displayName.it">Prerogativa</prop>
+ <prop key="displayName.ja">資格情報</prop>
+ <prop key="description.en">Member of: URI (either URL or URN) that indicates a set of rights to specific resources based on an agreement across the releavant community</prop>
+ <prop key="description.de">Zeichenkette, die Rechte für spezifische Ressourcen beschreibt</prop>
+ <prop key="description.fr">Membre de: URI (soit une URL ou une URN) décrivant un droit spécific d'accès.</prop>
+ <prop key="description.it">Membro delle seguenti URI (sia URL o URN) che rappresentano diritti specifici d'accesso validi in tutta la communità</prop>
+ <prop key="description.ja">特定のアプリケーションもしくはコミュニティ内の複数リソースへのアクセス権限を持つことを示すURI(URLもしくはURN)</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">eduPersonPrincipalName</prop>
+ <prop key="transcoder">OIDCScopedStringTranscoder</prop>
+ <prop key="oidc.name">eduPersonPrincipalName</prop>
+ <prop key="displayName.en">Principal name</prop>
+ <prop key="displayName.de">Persönliche ID</prop>
+ <prop key="displayName.fr">Principal Name</prop>
+ <prop key="displayName.it">Principal Name</prop>
+ <prop key="displayName.ja">プリンシパルID</prop>
+ <prop key="description.en">A unique identifier for a person, mainly for inter-institutional user identification.</prop>
+ <prop key="description.de">Eindeutige Benutzeridentifikation</prop>
+ <prop key="description.de-ch">Eindeutige Benützeridentifikation</prop>
+ <prop key="description.fr">L'identifiant unique de l'utilisateur</prop>
+ <prop key="description.it">Un ID personale che identifica chiaramente l'utente in seno alla sua organizzazione</prop>
+ <prop key="description.ja">フェデレーション内で一意かつ永続的な利用者識別子</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">eduPersonScopedAffiliation</prop>
+ <prop key="transcoder">OIDCScopedStringTranscoder</prop>
+ <prop key="oidc.name">eduPersonScopedAffiliation</prop>
+ <prop key="displayName.en">Scoped affiliation</prop>
+ <prop key="displayName.de">Zugehörigkeit</prop>
+ <prop key="displayName.fr">Affiliation</prop>
+ <prop key="displayName.it">Tipo di membro</prop>
+ <prop key="displayName.ja">スコープ付き職位</prop>
+ <prop key="description.en">Specifies the person's affiliation within a particular security domain</prop>
+ <prop key="description.de">Art der Zugehörigkeit zur Heimatorganisation</prop>
+ <prop key="description.de-ch">Art der Zugehörigkeit zur Heimorganisation</prop>
+ <prop key="description.fr">Type d'affiliation dans l'organisation</prop>
+ <prop key="description.it">Tipo di membro: Tipo di lavoro svolto per l'organizzazione</prop>
+ <prop key="description.ja">セキュリティドメインのスコープが付いた所属機関における職位</prop>
+ </props>
+ </property>
+ </bean>
+
+ <!-- The remainder are standard OIDC claims, which we map based on the actual claim name. -->
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">address</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.asObject">true</prop>
+ <prop key="oidc.name">address</prop>
+ <prop key="displayName.en">Postal address</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">birthdate</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">birthdate</prop>
+ <prop key="displayName.en">Date of birth</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">email_verified</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">email_verified</prop>
+ <prop key="oidc.asBoolean">true</prop>
+ <prop key="displayName.en">E-mail verification status</prop>
+ <prop key="description.en">Indicates whether e-mail address has been verified by the issuer</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">gender</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">gender</prop>
+ <prop key="displayName.en">Gender</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">middle_name</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">middle_name</prop>
+ <prop key="displayName.en">Middle name</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">phone_number_verified</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">phone_number_verified</prop>
+ <prop key="oidc.asBoolean">true</prop>
+ <prop key="displayName.en">Phone number verification status</prop>
+ <prop key="description.en">Indicates whether phone number has been verified by the issuer</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">picture</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">picture</prop>
+ <prop key="displayName.en">Picture</prop>
+ <prop key="description.en">URL of personal photo</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">profile</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">profile</prop>
+ <prop key="displayName.en">Profile page</prop>
+ <prop key="description.en">URL of personal profile page</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">website</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">website</prop>
+ <prop key="displayName.en">Web site</prop>
+ <prop key="description.en">URL to personal web site</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">updated_at</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">updated_at</prop>
+ <prop key="oidc.asInteger">true</prop>
+ <prop key="displayName.en">Last update of information</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean parent="shibboleth.TranscodingProperties">
+ <property name="properties">
+ <props merge="true">
+ <prop key="id">zoneinfo</prop>
+ <prop key="transcoder">OIDCStringTranscoder</prop>
+ <prop key="oidc.name">zoneinfo</prop>
+ <prop key="displayName.en">Time zone</prop>
+ </props>
+ </property>
+ </bean>
+
+ </list>
+ </constructor-arg>
+ </bean>
+
+</beans>
diff --git a/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/conf/authn/oidc-credentials.xml b/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/conf/authn/oidc-credentials.xml
new file mode 100644
index 0000000..f38eb9a
--- /dev/null
+++ b/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/conf/authn/oidc-credentials.xml
@@ -0,0 +1,75 @@
+<?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">
+
+ <!--
+ This file contains default OIDC signing credentials. This file should be imported into credentials.xml.
+ -->
+
+ <bean id="shibboleth.oidc.DefaultRSSigningCredential" parent="shibboleth.oidc.JWKCredential"
+ p:resource="%{idp.signing.oidc.rs.key:#{null}}" p:failIfResourceIsNull="false" />
+
+ <bean id="shibboleth.oidc.DefaultESSigningCredential" parent="shibboleth.oidc.JWKCredential"
+ p:resource="%{idp.signing.oidc.es.key:#{null}}" p:failIfResourceIsNull="false" />
+
+ <bean id="shibboleth.oidc.DefaultRSAEncryptionCredential" parent="shibboleth.oidc.JWKCredential"
+ p:resource="%{idp.signing.oidc.rsa.enc.key:#{null}}" p:failIfResourceIsNull="false" />
+
+
+ <!--
+ The default credential is based on the client_secret, and will be the only used credential in most cases.
+ -->
+ <bean id="shibboleth.authn.oidc.rp.DefaultCredential" parent="shibboleth.oidc.ClientSecretCredential"
+ p:secret="%{idp.authn.oidc.rp.client.clientSecret:#{null}}"/>
+
+ <!--
+ Lists ALL of your OP's response signing credentials for the default security configuration.
+ If you define additional signing credentials make sure to include them within this list.
+ -->
+ <util:list id="shibboleth.oidc.SigningCredentials">
+ <ref bean="shibboleth.oidc.DefaultRSSigningCredential" />
+ <ref bean="shibboleth.oidc.DefaultESSigningCredential" />
+ </util:list>
+
+ <!--
+ Lists ALL of your OP's request decryption credentials for the default security configuration.
+ If you define additional decryption credentials make sure to include them within this list.
+ -->
+ <util:list id="shibboleth.oidc.EncryptionCredentials">
+ <ref bean="shibboleth.oidc.DefaultRSAEncryptionCredential" />
+ </util:list>
+
+ <!--
+ If you need to publish a key set different from shibboleth.oidc.EncryptionCredentials, define
+ a list bean named "shibboleth.oidc.EncryptionCredentialsToPublish".
+ -->
+
+ <!-- Example of two active encryption credentials, but only publishing the second before removing from use. -->
+ <!--
+ <util:list id="shibboleth.oidc.EncryptionCredentialsToPublish">
+ <ref bean="shibboleth.oidc.OnlyNewDefaultRSAEncryptionCredential" />
+ </util:list>
+ -->
+
+ <!--
+ If you need to publish a key set different from shibboleth.oidc.SigningCredentials, define
+ a list bean named "shibboleth.oidc.SigningCredentialsToPublish".
+ -->
+
+ <!-- Example of publishing two signing credentials, before active use. -->
+ <!--
+ <util:list id="shibboleth.oidc.SigningCredentialsToPublish">
+ <ref bean="shibboleth.oidc.DefaultRSSigningCredential" />
+ <ref bean="shibboleth.oidc.DefaultESSigningCredential" />
+ <ref bean="shibboleth.oidc.UpcomingDefaultRSSigningCredential" />
+ </util:list>
+ -->
+
+</beans>
diff --git a/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/module.properties b/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/module.properties
index bfea30c..3aaeacc 100644
--- a/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/module.properties
+++ b/oidc-common-plugin/src/main/resources/net/shibboleth/oidc/common/module.properties
@@ -9,3 +9,12 @@ idp.oidc.common.3.plugin = net.shibboleth.oidc.common
idp.oidc.common.3.name = Module to provide common OIDC processing
idp.oidc.common.3.desc = Module that provides common OIDC processing functions for other plugins to use
idp.oidc.common.3.url = /OIDCCommon
+
+idp.oidc.common.3.1.src = /net/shibboleth/oidc/common/conf/authn/oidc-credentials.xml
+idp.oidc.common.3.1.dest = conf/oidc-credentials.xml
+idp.oidc.common.3.1.replace = false
+
+idp.oidc.common.3.2.src = /net/shibboleth/oidc/common/conf/attributes/oidc-claim-rules.xml
+idp.oidc.common.3.2.dest = conf/attributes/oidc-claim-rules.xml
+idp.oidc.common.3.2.replace = false
+
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/AbstractOIDCSSOConfiguration.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/AbstractOIDCSSOConfiguration.java
index c38c42f..93615f8 100644
--- a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/AbstractOIDCSSOConfiguration.java
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/AbstractOIDCSSOConfiguration.java
@@ -96,7 +96,10 @@ public abstract class AbstractOIDCSSOConfiguration extends AbstractOAuth2FlowAwa
/** Lookup function to supply strategy bi-function for manipulating access token claims set. */
@Nonnull
private Function<ProfileRequestContext,BiFunction<ProfileRequestContext,Map<String,Object>,Map<String,Object>>>
- accessTokenClaimsSetManipulationStrategyLookupStrategy;
+ accessTokenClaimsSetManipulationStrategyLookupStrategy;
+
+ /** Lookup function to override the default response_mode for a given response_type.*/
+ @Nonnull private Function<ProfileRequestContext, String> responseModeLookupStrategy;
/**
* Creates a new configuration instance.
@@ -122,9 +125,12 @@ public abstract class AbstractOIDCSSOConfiguration extends AbstractOAuth2FlowAwa
idTokenManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
accessTokenClaimsSetManipulationStrategyLookupStrategy = FunctionSupport.constant(null);
+
+ responseModeLookupStrategy = FunctionSupport.constant(null);
}
/** {@inheritDoc} */
+ @Override
@Nullable @NotEmpty public String getIssuer(@Nullable final ProfileRequestContext profileRequestContext) {
return issuerLookupStrategy.apply(profileRequestContext);
}
@@ -148,6 +154,7 @@ public abstract class AbstractOIDCSSOConfiguration extends AbstractOAuth2FlowAwa
}
/** {@inheritDoc} */
+ @Override
public boolean isResolveAttributes(@Nullable final ProfileRequestContext profileRequestContext) {
return resolveAttributesPredicate.test(profileRequestContext);
}
@@ -590,5 +597,40 @@ public abstract class AbstractOIDCSSOConfiguration extends AbstractOAuth2FlowAwa
accessTokenClaimsSetManipulationStrategyLookupStrategy = Constraint.isNotNull(strategy,
"Lookup strategy cannot be null");
}
+
+ /**
+ * Set the lookup strategy to determine the response_mode for authorization requests.
+ *
+ * @param strategy the strategy to use
+ *
+ * @since 2.2.0
+ */
+ public void setResponseModeLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
+ responseModeLookupStrategy = Constraint.isNotNull(strategy, "ResponseMode lookup strategy can not be null");
+ }
+
+ /**
+ * Get the response_mode to use for authorization requests.
+ *
+ * @param profileRequestContext the profile request context
+ *
+ * @return the response_mode
+ *
+ * @since 2.2.0
+ */
+ public String getResponseMode(@Nullable final ProfileRequestContext profileRequestContext) {
+ return responseModeLookupStrategy.apply(profileRequestContext);
+ }
+
+ /**
+ * Set the response_mode to use for authorization requests.
+ *
+ * @param responseMode the response_mode to use
+ *
+ * @since 2.2.0
+ */
+ public void setResponseMode(@Nonnull final String responseMode) {
+ responseModeLookupStrategy = FunctionSupport.constant(responseMode);
+ }
}
\ No newline at end of file
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/CredentialsListFactory.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/CredentialsListFactory.java
new file mode 100644
index 0000000..b081ac8
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/CredentialsListFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.oidc.profile.config;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.security.credential.Credential;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+
+/**
+ * A factory that returns a list of credentials which does not contain any {@literal null} elements.
+ *
+ * <p>Primarily created to support signature credential injection into the {@link BasicSignatureSigningConfiguration}
+ * when the credential list may contain, in its raw state, {@literal null} elements.</p>
+ */
+public class CredentialsListFactory extends AbstractFactoryBean<List<Credential>> {
+
+ /** The credentials which may contain {@literal null} elements. */
+ @Nonnull private List<Credential> credentials;
+
+ /**
+ * Constructor.
+ *
+ * @param creds the credentials, which can be {@literal null} and may contain {@literal null} elements.
+ */
+ public CredentialsListFactory(@Nullable final List<Credential> creds){
+ if (creds == null) {
+ credentials = Collections.emptyList();
+ } else {
+ credentials = creds;
+ }
+ }
+
+ @Override
+ public Class<?> getObjectType() {
+ return List.class;
+ }
+
+ @Override
+ protected List<Credential> createInstance() throws Exception {
+ return credentials.stream().filter(Objects::nonNull).collect(Collectors.toList());
+ }
+
+}
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/OIDCAuthorizationConfiguration.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/OIDCAuthorizationConfiguration.java
index 6b1f6b0..6ab3c85 100644
--- a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/OIDCAuthorizationConfiguration.java
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/OIDCAuthorizationConfiguration.java
@@ -36,7 +36,6 @@ import com.google.common.base.Predicates;
import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
import net.shibboleth.idp.profile.config.OverriddenIssuerProfileConfiguration;
-import net.shibboleth.oidc.security.credential.ClientSecretCredential;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
@@ -102,22 +101,6 @@ public class OIDCAuthorizationConfiguration extends AbstractOIDCSSOConfiguration
/** An override to specify a specific redirect_uri to use over the normally computed one.*/
@Nonnull private Function<ProfileRequestContext, String> redirectUriOverrideLookupStrategy;
- /** Lookup function to retrieve the client_id from the given profile request context.*/
- //TODO this is the same as the issuer in the proxy context?
- @Nonnull private Function<ProfileRequestContext, String> clientIdLookupStrategy;
-
- /**
- * Lookup function to retrieve a client credential from the given profile request context.
- */
- @Nonnull private Function<ProfileRequestContext, ClientSecretCredential> clientCredentialLookupStrategy;
-
- /** Lookup function to determine the client_authentication method. */
- //TODO same as tokenEndpointAuthMethodsLookupStrategy?
- @Nonnull private Function<ProfileRequestContext, String> clientAuthenticationMethodLookupStrategy;
-
- /** Lookup function to override the default response_mode for a given response_type.*/
- @Nonnull private Function<ProfileRequestContext, String> responseModeLookupStrategy;
-
/** Lookup function to retrieve the response_type.*/
@Nonnull private Function<ProfileRequestContext, String> responseTypeLookupStrategy;
@@ -165,10 +148,7 @@ public class OIDCAuthorizationConfiguration extends AbstractOIDCSSOConfiguration
public OIDCAuthorizationConfiguration(@Nonnull @NotEmpty final String profileId) {
super(profileId);
- redirectUriOverrideLookupStrategy = FunctionSupport.constant(null);
- clientIdLookupStrategy = FunctionSupport.constant(null);
- clientCredentialLookupStrategy = FunctionSupport.constant(null);
- responseModeLookupStrategy = FunctionSupport.constant(null);
+ redirectUriOverrideLookupStrategy = FunctionSupport.constant(null);
responseTypeLookupStrategy = FunctionSupport.constant("code");
scopesLookupStrategy = FunctionSupport.constant(Set.of("openid"));
signRequestObjectPredicate = Predicates.alwaysTrue();
@@ -369,103 +349,6 @@ public class OIDCAuthorizationConfiguration extends AbstractOIDCSSOConfiguration
encryptRequestObjectPredicate = Constraint.isNotNull(condition, "Condition cannot be null");
}
- /**
- * Set the strategy to locate a client_id.
- *
- * @param strategy the strategy to use
- */
- public void setClientIdLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
- clientIdLookupStrategy = Constraint.isNotNull(strategy, "Client ID lookup strategy can not be null");
- }
-
- /**
- * Set a fixed client_id to use no matter what the context/request.
- *
- * @param clientId the static clientId to use
- */
- public void setClientId(@Nullable final String clientId) {
- clientIdLookupStrategy = FunctionSupport.constant(StringSupport.trimOrNull(clientId));
- }
-
- /**
- * Get the client_id appropriate for the given context. Typically that associated
- * with the chosen downstream OpenID Connect Provider.
- *
- * @param profileRequestContext the profile request context
- *
- * @return the client_id
- */
- public String getClientId(@Nullable final ProfileRequestContext profileRequestContext) {
- return clientIdLookupStrategy.apply(profileRequestContext);
- }
-
- /**
- * Set the client authentication method lookup strategy which will locate the client_authentication method
- * for a given client.
- *
- * @param strategy the strategy to use
- */
- public void setClientAuthenticationMethodLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, String> strategy) {
- clientAuthenticationMethodLookupStrategy =
- Constraint.isNotNull(strategy, "Client authentication strategy can not be null");
- }
-
- /**
- * Set the client authentication method.
- *
- * @param clientAuthMethod the client_authentication method
- */
- public void setClientAuthenticationMethod(@Nullable final String clientAuthMethod) {
- clientAuthenticationMethodLookupStrategy = FunctionSupport.constant(clientAuthMethod);
- }
-
- /**
- * Get the client_authentication for the given context. Typically that associated with the
- * current client_id.
- *
- * @param profileRequestContext the profile request context
- *
- * @return the client_authentication method
- */
- public String getClientAuthenticationMethod(
- @Nullable final ProfileRequestContext profileRequestContext) {
- return clientAuthenticationMethodLookupStrategy.apply(profileRequestContext);
- }
-
- /**
- * Set the client credential lookup strategy.
- *
- * @param strategy the strategy to use
- */
- public void setClientCredentialLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, ClientSecretCredential> strategy) {
- clientCredentialLookupStrategy =
- Constraint.isNotNull(strategy, "Client credential lookup strategy can not be null");
- }
-
- /**
- * Set a fixed client credential to use no matter what the context/request.
- *
- * @param clientCredential the static client credential to use
- */
- public void setClientCredential(@Nullable final ClientSecretCredential clientCredential) {
- clientCredentialLookupStrategy = FunctionSupport.constant(clientCredential);
- }
-
- /**
- * Get the client credential for the given context. Typically a client_secret
- * associated with the current client_id.
- *
- * @param profileRequestContext the profile request context
- *
- * @return the client credential
- */
- public ClientSecretCredential getClientCredential(
- @Nullable final ProfileRequestContext profileRequestContext) {
- return clientCredentialLookupStrategy.apply(profileRequestContext);
- }
-
/**
* Set the redirect_uri lookup strategy used to locate an overridden redirect.
*
@@ -672,35 +555,6 @@ public class OIDCAuthorizationConfiguration extends AbstractOIDCSSOConfiguration
@Nonnull final Function<ProfileRequestContext,Set<String>> strategy) {
deniedUserInfoAttributesLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
}
-
- /**
- * Set the lookup strategy to determine the response_mode for authentication requests.
- *
- * @param strategy the strategy to use
- */
- public void setResponseModeLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
- responseModeLookupStrategy = Constraint.isNotNull(strategy, "ResponseMode lookup strategy can not be null");
- }
-
- /**
- * Get the response_mode to use for authentication requests.
- *
- * @param profileRequestContext the profile request context
- *
- * @return the response_mode
- */
- public String getResponseMode(@Nullable final ProfileRequestContext profileRequestContext) {
- return responseModeLookupStrategy.apply(profileRequestContext);
- }
-
- /**
- * Set the response_mode to use for authentication requests.
- *
- * @param responseMode the response_mode to use
- */
- public void setResponseMode(@Nonnull final String responseMode) {
- responseModeLookupStrategy = FunctionSupport.constant(responseMode);
- }
/**
* Get whether to include iss parameter in the authentication response.
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction.java
new file mode 100644
index 0000000..ffded26
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.shibboleth.oidc.profile.config.navigate;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
+import net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+
+/**
+ * Implements a set of default logic for determining the custom principals to derive the
+ * OIDC ACRs from.
+ *
+ * <p>This operates for the SAML to OIDC proxy use case. The values returned are empty unless the
+ * parent context itself contains a child context carrying particular values. The values are either
+ * 'passed through' or mapped by the given principal mappings. All input values are either SAML ACRs or AMRs,
+ * and all output values are OIDC ACRs.</p>
+ */
+public class ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction
+ implements Function<ProfileRequestContext,Collection<AuthenticationContextClassReferencePrincipal>> {
+
+ /** Mappings to transform proxied Principals. */
+ @Nonnull @NonnullElements private Map<Principal,Collection<Principal>> principalMappings;
+
+ /** Constructor. */
+ public ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction() {
+ principalMappings = Collections.emptyMap();
+ }
+
+ /**
+ * Sets the mappings from input/proxied Principals to zero or more equivalent values to use.
+ *
+ * <p>Any values not mapped will be assumed to be passed through.</p>
+ *
+ * @param mappings {@link Principal} mappings
+ */
+ public void setMappings(@Nullable @NonnullElements final Map<Principal,Collection<Principal>> mappings) {
+ if (mappings == null || mappings.isEmpty()) {
+ principalMappings = Collections.emptyMap();
+ return;
+ }
+
+ principalMappings = new HashMap<>(mappings.size());
+ mappings.forEach((k, v) -> principalMappings.put(k, List.copyOf(v)));
+ }
+
+ @Override
+ public Collection<AuthenticationContextClassReferencePrincipal> apply(final ProfileRequestContext input) {
+
+ if (input != null && input.getParent() instanceof AuthenticationContext) {
+
+ final RequestedPrincipalContext rpc = input.getParent().getSubcontext(RequestedPrincipalContext.class);
+
+ if (rpc != null) {
+
+ final List<AuthenticationContextClassReferencePrincipal> mappedAndPassedThroughPrincipals =
+ new ArrayList<>();
+
+ for (final Principal requestedPrincipal : rpc.getRequestedPrincipals()) {
+
+ // If a mapping exists, use it
+ if (principalMappings.containsKey(requestedPrincipal)) {
+ final Collection<Principal> mappedPrinicipals = principalMappings.get(requestedPrincipal);
+ for (final Principal mappedPrincipal : mappedPrinicipals) {
+ if (mappedPrincipal instanceof AuthenticationContextClassReferencePrincipal) {
+ mappedAndPassedThroughPrincipals.add(
+ (AuthenticationContextClassReferencePrincipal) mappedPrincipal);
+ }
+ }
+ } else {
+ // If no mapping exists, just convert to correct output type - which might not make sense
+ // to the upstream OP.
+ mappedAndPassedThroughPrincipals.add(
+ new AuthenticationContextClassReferencePrincipal(requestedPrincipal.getName()));
+ }
+
+ }
+ return mappedAndPassedThroughPrincipals;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+
+}
+
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction.java
new file mode 100644
index 0000000..a122310
--- /dev/null
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.shibboleth.oidc.profile.config.navigate;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Implements a set of logic for determining the principals to use from OIDC 'amr' or 'acr' claims.
+ *
+ * <p>This operates for the OIDC to SAML proxy use case, in effect the reverse of the
+ * {@link ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction} function.
+ * All input values are either OIDC ACRs or AMRs, and all output values Java {@link Principal}s.
+ * The values are mapped by the given principal mappings. If a mapping does not exist, the AMR or ACR is ignored.
+ * </p>
+ */
+ at ThreadSafe
+public class ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction
+ implements Function<Collection<String>,Collection<Principal>> {
+
+ /** Mappings to transform proxied Principals. */
+ @Nonnull @NonnullElements private final Map<String,Collection<Principal>> principalMappings;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param mappings the AMR/ACR value to Principal mappings
+ */
+ public ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction(
+ @Nullable @NonnullElements @ParameterName(name="mappings")
+ final Map<String,Collection<Principal>> mappings) {
+
+ if (mappings == null || mappings.isEmpty()) {
+ principalMappings = Collections.emptyMap();
+ } else {
+ principalMappings = new HashMap<>(mappings.size());
+ mappings.forEach((k, v) -> principalMappings.put(k, List.copyOf(v)));
+ }
+ }
+
+ @Override
+ public Collection<Principal> apply(final Collection<String> amrOrAcrs) {
+
+ if (amrOrAcrs != null) {
+ final List<Principal> principals = new ArrayList<>();
+ for (final String amrOrAcr : amrOrAcrs) {
+ if (principalMappings.containsKey(amrOrAcr)) {
+ final Collection<Principal> mappedPrincipals = principalMappings.get(amrOrAcr);
+ if (!mappedPrincipals.isEmpty()) {
+ principals.addAll(mappedPrincipals);
+ }
+ }
+ }
+ return principals;
+ }
+ return Collections.emptyList();
+ }
+
+ /** A simple lookup function that returns a singleton function.*/
+ public static class LookupFunctionWrapper
+ implements Function<ProfileRequestContext, Function<Collection<String>,Collection<Principal>>> {
+
+ /** A function used to map OIDC ACR/AMRs to Principals. A single instance is supplied.*/
+ private final Function<Collection<String>,Collection<Principal>> function;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param wrappedFunction the function to return when requested.
+ */
+ public LookupFunctionWrapper(@ParameterName(name="wrappedFunction")
+ final Function<Collection<String>,Collection<Principal>> wrappedFunction) {
+ function = Constraint.isNotNull(wrappedFunction, "Lookup function can not be null");
+ }
+
+ @Override
+ public Function<Collection<String>, Collection<Principal>> apply(final ProfileRequestContext prc) {
+ return function;
+ }
+
+ }
+}
+
diff --git a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/oauth2/config/AbstractOAuth2ClientAuthenticableProfileConfiguration.java b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/oauth2/config/AbstractOAuth2ClientAuthenticableProfileConfiguration.java
index 86584f4..d6d0f9f 100644
--- a/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/oauth2/config/AbstractOAuth2ClientAuthenticableProfileConfiguration.java
+++ b/oidc-common-profile-api/src/main/java/net/shibboleth/oidc/profile/oauth2/config/AbstractOAuth2ClientAuthenticableProfileConfiguration.java
@@ -37,6 +37,7 @@ import net.shibboleth.idp.authn.config.AuthenticationProfileConfiguration;
import net.shibboleth.idp.profile.config.AbstractConditionalProfileConfiguration;
import net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePrincipal;
import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
+import net.shibboleth.oidc.security.credential.ClientSecretCredential;
import net.shibboleth.utilities.java.support.annotation.constraint.NonNegative;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
@@ -56,6 +57,9 @@ public abstract class AbstractOAuth2ClientAuthenticableProfileConfiguration
/** Enabled token endpoint authentication methods. */
@Nonnull private Function<ProfileRequestContext,Set<String>> tokenEndpointAuthMethodsLookupStrategy;
+ /** The token endpoint authentication method to use with an upstream OpenID Provider. */
+ @Nonnull private Function<ProfileRequestContext,String> tokenEndpointAuthMethodLookupStrategy;
+
/** Validation of JWT claims for subset of client auth methods. */
@Nonnull private Function<ProfileRequestContext,ClaimsValidator> claimsValidatorLookupStrategy;
@@ -75,6 +79,14 @@ public abstract class AbstractOAuth2ClientAuthenticableProfileConfiguration
/** Lookup function to supply post authentication flows. */
@Nonnull private Function<ProfileRequestContext,Collection<String>> postAuthenticationFlowsLookupStrategy;
+ /** Lookup function to retrieve a client credential from the given profile request context. */
+ @Nonnull private Function<ProfileRequestContext, ClientSecretCredential> clientCredentialLookupStrategy;
+
+ /** Lookup function to retrieve the client_id from the given profile request context.*/
+ //TODO this is the same as the issuer in the proxy context?
+ @Nonnull private Function<ProfileRequestContext, String> clientIdLookupStrategy;
+
+
/**
* Constructor.
*
@@ -89,13 +101,17 @@ public abstract class AbstractOAuth2ClientAuthenticableProfileConfiguration
ClientAuthenticationMethod.CLIENT_SECRET_POST.toString(),
ClientAuthenticationMethod.CLIENT_SECRET_JWT.toString(),
ClientAuthenticationMethod.PRIVATE_KEY_JWT.toString()));
+ tokenEndpointAuthMethodLookupStrategy =
+ FunctionSupport.constant(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.toString());
claimsValidatorLookupStrategy = FunctionSupport.constant(null);
-
forceAuthnPredicate = Predicates.alwaysFalse();
proxyCountLookupStrategy = FunctionSupport.constant(null);
defaultAuthenticationContextsLookupStrategy = FunctionSupport.constant(null);
authenticationFlowsLookupStrategy = FunctionSupport.constant(null);
postAuthenticationFlowsLookupStrategy = FunctionSupport.constant(null);
+ clientCredentialLookupStrategy = FunctionSupport.constant(null);
+ clientIdLookupStrategy = FunctionSupport.constant(null);
+
}
/**
@@ -141,6 +157,44 @@ public abstract class AbstractOAuth2ClientAuthenticableProfileConfiguration
tokenEndpointAuthMethodsLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
}
+ /**
+ * Get the token endpoint authentication method to use with an upstream OpenID Provider.
+ *
+ * @param profileRequestContext profile request context
+ *
+ * @return the token endpoint authentication method to use.
+ *
+ * @since 2.2.0
+ */
+ @Nonnull public String getTokenEndpointAuthMethod(@Nullable final ProfileRequestContext profileRequestContext) {
+ return tokenEndpointAuthMethodLookupStrategy.apply(profileRequestContext);
+ }
+
+ /**
+ * Set the enabled token endpoint authentication method to use with an upstream OpenID Provider.
+ *
+ * @param method the token endpoint authentication method to set.
+ *
+ * @since 2.2.0
+ */
+ public void setTokenEndpointAuthMethod(@Nonnull @NonnullElements final String method) {
+ tokenEndpointAuthMethodLookupStrategy =
+ FunctionSupport.constant(Constraint.isNotNull(method, "Collection of methods cannot be null"));
+ }
+
+ /**
+ * Set a lookup strategy to find the enabled token endpoint authentication method to use with an
+ * upstream OpenID Provider.
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 2.2.0
+ */
+ public void setTokenEndpointAuthMethodLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, String> strategy) {
+ tokenEndpointAuthMethodLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
/**
* Get the {@link ClaimsValidator} to apply to JWT-based client authentication.
*
@@ -343,4 +397,79 @@ public abstract class AbstractOAuth2ClientAuthenticableProfileConfiguration
defaultAuthenticationContextsLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
}
+ /**
+ * Set the client credential lookup strategy.
+ *
+ * @param strategy the strategy to use
+ *
+ * @since 2.2.0
+ */
+ public void setClientCredentialLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, ClientSecretCredential> strategy) {
+ clientCredentialLookupStrategy =
+ Constraint.isNotNull(strategy, "Client credential lookup strategy can not be null");
+ }
+
+ /**
+ * Set a fixed client credential to use no matter what the context/request.
+ *
+ * @param clientCredential the static client credential to use
+ *
+ * @since 2.2.0
+ */
+ public void setClientCredential(@Nullable final ClientSecretCredential clientCredential) {
+ clientCredentialLookupStrategy = FunctionSupport.constant(clientCredential);
+ }
+
+ /**
+ * Get the client credential for the given context. Typically a client_secret
+ * associated with the current client_id.
+ *
+ * @param profileRequestContext the profile request context
+ *
+ * @return the client credential
+ *
+ * @since 2.2.0
+ */
+ public ClientSecretCredential getClientCredential(
+ @Nullable final ProfileRequestContext profileRequestContext) {
+ return clientCredentialLookupStrategy.apply(profileRequestContext);
+ }
+
+ /**
+ * Set the strategy to locate a client_id.
+ *
+ * @param strategy the strategy to use
+ *
+ * @since 2.2.0
+ */
+ public void setClientIdLookupStrategy(@Nonnull final Function<ProfileRequestContext, String> strategy) {
+ clientIdLookupStrategy = Constraint.isNotNull(strategy, "Client ID lookup strategy can not be null");
+ }
+
+ /**
+ * Set a fixed client_id to use no matter what the context/request.
+ *
+ * @param clientId the static clientId to use
+ *
+ * @since 2.2.0
+ */
+ public void setClientId(@Nullable final String clientId) {
+ clientIdLookupStrategy = FunctionSupport.constant(StringSupport.trimOrNull(clientId));
+ }
+
+ /**
+ * Get the client_id appropriate for the given context. Typically that associated
+ * with the chosen downstream OpenID Connect Provider.
+ *
+ * @param profileRequestContext the profile request context
+ *
+ * @return the client_id
+ *
+ * @since 2.2.0
+ */
+ public String getClientId(@Nullable final ProfileRequestContext profileRequestContext) {
+ return clientIdLookupStrategy.apply(profileRequestContext);
+ }
+
}
\ No newline at end of file
diff --git a/oidc-common-profile-api/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/oidc-common-profile-api/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
new file mode 100644
index 0000000..245a048
--- /dev/null
+++ b/oidc-common-profile-api/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -0,0 +1,28 @@
+<?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">
+
+ <!-- Generic OIDC System beans needed for OIDC based extensions to function, loaded after global.xml. -->
+
+ <!-- Credential bean factories -->
+ <bean id="shibboleth.oidc.ClientSecretCredential" abstract="true"
+ class="net.shibboleth.oidc.security.credential.impl.BasicClientSecretCredentialFactoryBean" />
+
+ <bean id="shibboleth.oidc.JWKCredential" abstract="true"
+ class="net.shibboleth.oidc.security.credential.impl.BasicJWKCredentialFactoryBean" />
+
+ <!-- Singleton JWK cache -->
+ <bean id="shibboleth.oidc.RemoteJwkSetCache"
+ class="net.shibboleth.oidc.jwk.RemoteJwkSetCache"
+ p:storage-ref="#{'%{idp.oidc.jwk.StorageService:shibboleth.StorageService}'.trim()}"
+ p:httpClient="#{getObject('shibboleth.oidc.NonBrowser.HttpClient') ?: getObject('shibboleth.InternalHttpClient')}"
+ p:httpClientSecurityParameters="#{getObject('shibboleth.oidc.NonBrowser.HttpClientSecurityParameters')}" />
+
+</beans>
\ No newline at end of file
diff --git a/oidc-common-profile-api/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml b/oidc-common-profile-api/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml
new file mode 100644
index 0000000..75ffe22
--- /dev/null
+++ b/oidc-common-profile-api/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml
@@ -0,0 +1,25 @@
+<?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">
+
+ <!-- Necessary for encoder parsing and claims mapping to function. -->
+
+ <bean id="OIDCByteTranscoder"
+ class="net.shibboleth.oidc.attribute.transcoding.impl.OIDCByteAttributeTranscoder" />
+
+ <bean id="OIDCStringTranscoder"
+ class="net.shibboleth.oidc.attribute.transcoding.impl.OIDCStringAttributeTranscoder" />
+
+ <bean id="OIDCScopedStringTranscoder"
+ class="net.shibboleth.oidc.attribute.transcoding.impl.OIDCScopedStringAttributeTranscoder" />
+
+</beans>
diff --git a/oidc-common-profile-api/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/oidc-common-profile-api/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
new file mode 100644
index 0000000..b59c919
--- /dev/null
+++ b/oidc-common-profile-api/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -0,0 +1,328 @@
+<?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">
+
+ <!--
+ Security Configuration Defaults. These settings establish the default security configurations for
+ signatures and loads the default credentials used.
+ -->
+ <bean id="shibboleth.oidc.BasicSignatureValidationConfiguration" abstract="true"
+ class="net.shibboleth.oidc.security.jose.impl.BasicSignatureValidationConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.oidc.IncludedSignatureAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.oidc.ExcludedSignatureAlgorithms')}" />
+
+ <bean id="shibboleth.oidc.BasicSignatureSigningConfiguration" abstract="true"
+ class="net.shibboleth.oidc.security.jose.impl.BasicSignatureSigningConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.oidc.IncludedSignatureAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.oidc.ExcludedSignatureAlgorithms')}" />
+
+ <bean id="shibboleth.oidc.BasicEncryptionConfiguration" abstract="true"
+ class="net.shibboleth.oidc.security.jose.impl.BasicEncryptionConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.oidc.IncludedEncryptionAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.oidc.ExcludedEncryptionAlgorithms')}" />
+
+ <bean id="shibboleth.oidc.BasicDecryptionConfiguration" abstract="true"
+ class="net.shibboleth.oidc.security.jose.impl.BasicDecryptionConfiguration"
+ p:includedAlgorithms="#{getObject('shibboleth.oidc.IncludedEncryptionAlgorithms')}"
+ p:excludedAlgorithms="#{getObject('shibboleth.oidc.ExcludedEncryptionAlgorithms')}" />
+
+ <bean id="AbstractOIDCProfile" abstract="true"
+ p:securityConfiguration-ref="%{idp.security.oidc.config:shibboleth.oidc.DefaultSecurityConfiguration}" />
+
+<!-- p:claimsValidator-ref="DefaultJWTClaimsValidator" -->
+ <bean id="AbstractOIDCSSOProfile" parent="AbstractOIDCProfile" abstract="true"
+ p:issuer-ref="issuer"
+ p:tokenEndpointAuthMethods="%{idp.oidc.tokenEndpointAuthMethods:client_secret_basic,client_secret_poster,client_secret_jwt,private_key_jwt}"
+ p:claimsValidator="#{getObject('shibboleth.oidc.DefaultJWTClaimsValidator')}"
+ p:encryptionOptional="%{idp.oidc.encryptionOptional:true}"
+ p:forcePKCE="%{idp.oidc.forcePKCE:false}"
+ p:allowPKCEPlain="%{idp.oidc.allowPKCEPlain:false}"
+ p:iDTokenLifetime="%{idp.oidc.idToken.defaultLifetime:PT1H}"
+ p:accessTokenType="%{idp.oauth2.accessToken.type:}"
+ p:accessTokenLifetime="%{idp.oidc.accessToken.defaultLifetime:PT10M}"
+ p:refreshTokenLifetime="%{idp.oidc.refreshToken.defaultLifetime:PT2H}"
+ p:alwaysIncludedAttributes="%{idp.oidc.alwaysIncludedAttributes:}"
+ p:tokenEndpointAuthMethod="%{idp.authn.oidc.rp.client.authenticationMethod:client_secret_basic}"
+ p:responseMode="%{idp.authn.oidc.rp.client.responseMode:#{null}}"
+ p:clientId="#{%{idp.authn.oidc.rp.provider.discoveryRequired:false} == true ? null : '%{idp.authn.oidc.rp.client.clientId:}'}"
+ p:clientCredential="#{%{idp.authn.oidc.rp.provider.discoveryRequired:false} == true ? {null} : getObject('shibboleth.authn.oidc.rp.DefaultCredential')}"/>
+
+ <bean id="OIDC.SSO" parent="AbstractOIDCSSOProfile" lazy-init="true"
+ class="net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration"
+ p:authorizeCodeLifetime="%{idp.oidc.authorizeCode.defaultLifetime:PT5M}"
+ p:encodeConsentInTokens="%{idp.oidc.encodeConsentInTokens:false}"
+ p:encodedAttributes="%{idp.oidc.encodedAttributes:%{idp.oidc.embeddedAttributes:}}"
+ p:deniedUserInfoAttributes="%{idp.oidc.deniedUserInfoAttributes:}"
+ p:httpRequestMethod="%{idp.authn.oidc.rp.httpRequestMethod:GET}"
+ p:retrieveUserInfoEndpointClaims="%{idp.authn.oidc.rp.client.userinfo.enabled:true}"
+ p:redirectUriOverride="%{idp.authn.oidc.rp.client.redirectURI:#{null}}"
+ p:encryptRequestObject="%{idp.authn.oidc.rp.client.requestobject.encrypted:false}"
+ p:signRequestObject="%{idp.authn.oidc.rp.client.requestobject.signed:true}"
+ p:useRequestObject="%{idp.authn.oidc.rp.client.requestobject.supported:false}"
+ p:scopes="%{idp.authn.oidc.rp.client.scopes:#{null}}">
+ <property name="forceAuthnPredicate">
+ <bean class="net.shibboleth.idp.saml.profile.config.logic.ProxyAwareForceAuthnPredicate" />
+ </property>
+ <property name="defaultAuthenticationMethodsLookupStrategy">
+ <bean
+ class="net.shibboleth.oidc.profile.config.navigate.ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction"
+ p:mappings="#{getObject('shibboleth.oidc.PrincipalProxyRequestMappings')}" />
+ </property>
+ <property name="authenticationContextClassReferenceTranslationStrategyLookupStrategy">
+ <bean
+ class="net.shibboleth.oidc.profile.config.navigate.ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction$LookupFunctionWrapper">
+ <constructor-arg>
+ <bean class="net.shibboleth.oidc.profile.config.navigate.ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction"
+ c:mappings="#{getObject('shibboleth.oidc.PrincipalProxyResponseMappings')}"/>
+ </constructor-arg>
+ </bean>
+ </property>
+ <property name="authenticationMethodsReferencesTranslationStrategyLookupStrategy">
+ <bean
+ class="net.shibboleth.oidc.profile.config.navigate.ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction$LookupFunctionWrapper">
+ <constructor-arg>
+ <bean class="net.shibboleth.oidc.profile.config.navigate.ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction"
+ c:mappings="#{getObject('shibboleth.oidc.PrincipalProxyResponseMappings')}"/>
+ </constructor-arg>
+ </bean>
+ </property>
+ </bean>
+
+ <!-- Keyset profile -->
+ <bean id="OIDC.Keyset" parent="AbstractOIDCProfile" lazy-init="true"
+ class="net.shibboleth.oidc.profile.config.OIDCPublishKeySetConfiguration"
+ p:securityConfiguration-ref="shibboleth.oidc.PublishKeySetSecurityConfiguration" />
+
+ <!-- Configuration for publishing key set. -->
+ <bean id="shibboleth.oidc.PublishKeySetSecurityConfiguration"
+ class="net.shibboleth.oidc.profile.config.JSONSecurityConfiguration">
+ <property name="jwtSignatureSigningConfiguration">
+ <ref bean="shibboleth.oidc.PublishKeySetSigningConfiguration" />
+ </property>
+ <property name="jwtDecryptionConfiguration">
+ <ref bean="shibboleth.oidc.PublishKeySetDecryptionConfiguration" />
+ </property>
+ </bean>
+
+ <!-- Signing keys to publish. -->
+ <bean id="shibboleth.oidc.PublishKeySetSigningConfiguration"
+ parent="shibboleth.oidc.BasicSignatureSigningConfiguration"
+ p:signingCredentials="#{getObject('shibboleth.oidc.SigningCredentialsToPublish') ?: getObject('shibboleth.oidc.SigningCredentialsFactory')}"/>
+
+ <!-- Encryption keys to publish. -->
+ <bean id="shibboleth.oidc.PublishKeySetDecryptionConfiguration"
+ parent="shibboleth.oidc.BasicDecryptionConfiguration">
+ <property name="KEKCredentialResolver">
+ <bean id="defaultOIDCKeyDecryptionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ReturnAllCollectionJOSEObjectCredentialResolver"
+ c:credentials="#{getObject('shibboleth.oidc.EncryptionCredentialsToPublish') ?: getObject('shibboleth.oidc.EncryptionCredentialsToPublishFactory')}"/>
+ </property>
+ </bean>
+
+ <bean id="shibboleth.oidc.EncryptionCredentialsToPublishFactory"
+ class="net.shibboleth.oidc.profile.config.CredentialsListFactory"
+ c:_0="#{getObject('shibboleth.oidc.EncryptionCredentials')}" />
+
+
+ <bean id="shibboleth.oidc.DefaultSecurityConfiguration"
+ class="net.shibboleth.oidc.profile.config.JSONSecurityConfiguration">
+ <property name="jwtSignatureSigningConfiguration">
+ <ref bean="#{'%{idp.oidc.signing.config:shibboleth.oidc.SigningConfiguration}'.trim()}" />
+ </property>
+ <property name="jwtEncryptionConfiguration">
+ <ref bean="#{'%{idp.oidc.encryption.config:shibboleth.oidc.EncryptionConfiguration}'.trim()}" />
+ </property>
+ <property name="jwtDecryptionConfiguration">
+ <ref bean="#{'%{idp.oidc.decryption.config:shibboleth.oidc.DecryptionConfiguration}'.trim()}" />
+ </property>
+ <property name="jwtSignatureValidationConfiguration">
+ <ref bean="#{'%{idp.oidc.validation.config:shibboleth.oidc.SignatureValidationConfiguration}'.trim()}" />
+ </property>
+ </bean>
+
+ <bean id="shibboleth.oidc.SigningConfiguration"
+ parent="shibboleth.oidc.BasicSignatureSigningConfiguration"
+ p:signingCredentials-ref="shibboleth.oidc.SigningCredentialsFactory">
+ <property name="signatureAlgorithms">
+ <list>
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.SignatureConstants.ALGO_ID_SIGNATURE_RS_256" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.SignatureConstants.ALGO_ID_SIGNATURE_RS_384" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.SignatureConstants.ALGO_ID_SIGNATURE_RS_512" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.SignatureConstants.ALGO_ID_SIGNATURE_HS_256" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.SignatureConstants.ALGO_ID_SIGNATURE_HS_384" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.SignatureConstants.ALGO_ID_SIGNATURE_HS_512" />
+ </list>
+ </property>
+ </bean>
+
+ <bean id="shibboleth.oidc.EncryptionConfiguration" parent="shibboleth.oidc.BasicEncryptionConfiguration"
+ p:KEKCredentialResolver-ref="defaultOIDCKeyEncryptionCredentialResolver"
+ p:contentEncryptionKeyCredentialResolver-ref="defaultOIDCContentEncryptionKeyCredentialResolver">
+ <property name="keyTransportEncryptionAlgorithms">
+ <list>
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_1_5" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_RSA_OAEP_256" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_128_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_192_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_256_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_128_GCM_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_192_GCM_KW" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.KeyManagementConstants.ALGO_ID_ALG_AES_256_GCM_KW" />
+ </list>
+ </property>
+ <property name="dataEncryptionAlgorithms">
+ <list>
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A128CBC_HS256" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A192CBC_HS384" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A256CBC_HS512" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A128GCM" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A192GCM" />
+ <util:constant
+ static-field="net.shibboleth.oidc.jwa.support.EncryptionConstants.ALGO_ID_ENC_ALG_A256GCM" />
+ </list>
+ </property>
+ </bean>
+
+ <bean id="shibboleth.oidc.SigningCredentialsFactory"
+ class="net.shibboleth.oidc.profile.config.CredentialsListFactory"
+ c:_0="#{getObject('shibboleth.oidc.SigningCredentials')}" />
+
+ <bean id="defaultOIDCKeyEncryptionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
+ <constructor-arg>
+ <list>
+ <!-- Used by the OP -->
+ <bean id="ClientInformationCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientInformationCredentialResolver"
+ p:remoteJwkSetCache-ref="shibboleth.oidc.RemoteJwkSetCache"
+ p:keyFetchInterval="%{idp.oidc.provider.keyfetch.interval:PT30M}"/>
+ <!-- Used by the RP -->
+ <bean id="OIDCProviderMetadataCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ProviderMetadataCredentialResolver"
+ p:remoteJwkSetCache-ref="shibboleth.oidc.RemoteJwkSetCache"
+ p:keyFetchInterval="%{idp.oidc.provider.keyfetch.interval:PT30M}" />
+ <bean id="ClientSecretCriterionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <bean id="defaultOIDCContentEncryptionKeyCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
+ <constructor-arg>
+ <list>
+ <!-- Used by the OP -->
+ <bean id="ClientInformationCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientInformationCredentialResolver"
+ p:remoteJwkSetCache-ref="shibboleth.oidc.RemoteJwkSetCache"
+ p:keyFetchInterval="%{idp.oidc.provider.keyfetch.interval:PT30M}"/>
+ <!-- Used by the RP -->
+ <bean id="ClientSecretCriterionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <bean id="shibboleth.oidc.DecryptionConfiguration"
+ parent="shibboleth.oidc.BasicDecryptionConfiguration"
+ p:KEKCredentialResolver-ref="defaultOIDCKeyDecryptionCredentialResolver"
+ p:contentEncryptionKeyCredentialResolver-ref="defaultOIDCContentDecryptionKeyCredentialResolver">
+ </bean>
+
+ <!--
+ A resolver to public/private key encryption keys global to the RP
+ -->
+ <bean id="defaultOIDCKeyDecryptionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
+ <constructor-arg>
+ <list>
+ <bean class="net.shibboleth.oidc.security.credential.impl.LocalJOSEObjectCredentialResolver">
+ <constructor-arg name="localCredentialResolver">
+ <bean
+ class="net.shibboleth.oidc.security.credential.impl.CollectionJOSEObjectCredentialResolver"
+ c:credentials-ref="shibboleth.oidc.EncryptionCredentials" />
+ </constructor-arg>
+ </bean>
+ <bean id="CriterionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <bean id="defaultOIDCContentDecryptionKeyCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
+ <constructor-arg>
+ <list>
+ <bean id="CriterionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <bean id="shibboleth.oidc.SignatureValidationConfiguration"
+ parent="shibboleth.oidc.BasicSignatureValidationConfiguration"
+ p:signatureTrustEngine-ref="ExplicitKeySignedJWTTrustEngine"/>
+
+
+ <bean id="ExplicitKeySignedJWTTrustEngine"
+ class="net.shibboleth.oidc.security.impl.ExplicitKeySignedJWTTrustEngine"
+ c:resolver-ref="defaultSignedJWTTrustedCredentialResolver"
+ c:JOSEObjectResolver-ref="defaultSignedJWTJOSEHeaderCredentialResolver" />
+
+ <!-- A resolver for resolving 'untrusted' credentials out of the JOSE header of JWTs -->
+ <bean id="defaultSignedJWTJOSEHeaderCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.BasicJOSEObjectCredentialResolver" />
+
+ <!-- A resolver for resolving trusted credentials to match against those resolved from the JWT -->
+ <bean id="defaultSignedJWTTrustedCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver">
+ <constructor-arg>
+ <list>
+ <!-- Used by the OP -->
+ <bean id="ClientInformationCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientInformationCredentialResolver"
+ p:remoteJwkSetCache-ref="shibboleth.oidc.RemoteJwkSetCache"
+ p:keyFetchInterval="%{idp.oidc.provider.keyfetch.interval:PT30M}"/>
+ <!-- Used by the RP -->
+ <bean id="OIDCProviderMetadataCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ProviderMetadataCredentialResolver"
+ p:remoteJwkSetCache-ref="shibboleth.oidc.RemoteJwkSetCache"
+ p:keyFetchInterval="%{idp.oidc.provider.keyfetch.interval:PT30M}"/>
+ <bean id="CriterionCredentialResolver"
+ class="net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+
+</beans>
diff --git a/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/CredentialsListFactoryTest.java b/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/CredentialsListFactoryTest.java
new file mode 100644
index 0000000..3fe818d
--- /dev/null
+++ b/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/CredentialsListFactoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package net.shibboleth.oidc.profile.config;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opensaml.security.credential.Credential;
+import org.testng.annotations.Test;
+
+import net.shibboleth.oidc.security.credential.BasicJWKCredential;
+
+/** Tests for the {@link CredentialsListFactory}.*/
+public class CredentialsListFactoryTest {
+
+ /**
+ * Test with a null input list.
+ *
+ * @throws Exception on error
+ */
+ @Test
+ public void testNullInputList() throws Exception {
+ final CredentialsListFactory factory = new CredentialsListFactory(null);
+ factory.afterPropertiesSet();
+ final List<Credential> creds = factory.createInstance();
+ assertNotNull(creds);
+ assertTrue(creds.isEmpty());
+ }
+
+
+ /**
+ * Test with an input list with a null element.
+ *
+ * @throws Exception on error
+ */
+ @Test
+ public void testInputListWithNullElement() throws Exception {
+ final var credsIn = new ArrayList<Credential>();
+ credsIn.add(null);
+ final CredentialsListFactory factory = new CredentialsListFactory(credsIn);
+ factory.afterPropertiesSet();
+ final List<Credential> creds = factory.createInstance();
+ assertNotNull(creds);
+ assertTrue(creds.isEmpty());
+ }
+
+ /**
+ * Test with an input list with one null element.
+ *
+ * @throws Exception on error
+ */
+ @Test
+ public void testInputListWithOneNullElement() throws Exception {
+ final var credsIn = new ArrayList<Credential>();
+ credsIn.add(null);
+ credsIn.add(new BasicJWKCredential());
+ final CredentialsListFactory factory = new CredentialsListFactory(credsIn);
+ factory.afterPropertiesSet();
+ final List<Credential> creds = factory.createInstance();
+ assertNotNull(creds);
+ assertTrue(creds.size()==1);
+ }
+
+}
diff --git a/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassLookupFunctionTest.java b/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassLookupFunctionTest.java
new file mode 100644
index 0000000..244abf8
--- /dev/null
+++ b/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassLookupFunctionTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.oidc.profile.config.navigate;
+
+import static org.testng.Assert.assertTrue;
+
+import java.security.Principal;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
+import net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal;
+import net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePrincipal;
+
+/** Tests for ProxyAwareDefaultOIDCAuthenticationContextClassLookupFunction.*/
+public class ProxyAwareDefaultOIDCAuthenticationContextClassLookupFunctionTest {
+
+ private ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction function;
+
+ private ProfileRequestContext prc;
+
+ private ProfileRequestContext nestedPrc;
+
+ private AuthenticationContext ac;
+
+ private RequestedPrincipalContext rpc;
+
+ @BeforeMethod
+ public void setup() {
+ function = new ProxyAwareDefaultOIDCAuthenticationContextClassRequestLookupFunction();
+ prc = new ProfileRequestContext();
+ ac = prc.getSubcontext(AuthenticationContext.class, true);
+ nestedPrc = ac.getSubcontext(ProfileRequestContext.class, true);
+ rpc = ac.getSubcontext(RequestedPrincipalContext.class, true);
+ }
+
+ @Test
+ public void testSingleMappingSuccess() {
+
+
+ final List<Principal> requestedPrincipals =
+ List.of(new AuthnContextClassRefPrincipal("http://example.org/ac/classes/mfa"));
+ rpc.setRequestedPrincipals(requestedPrincipals);
+ rpc.setOperator("exact");
+
+ final Map<Principal,Collection<Principal>> mappings = new HashMap<>();
+ mappings.put(new AuthnContextClassRefPrincipal("http://example.org/ac/classes/mfa"),
+ List.of(new AuthenticationContextClassReferencePrincipal("http://proxy.example.org/ac/classes/mfa")));
+ function.setMappings(mappings);
+
+ final Collection<AuthenticationContextClassReferencePrincipal> mapped = function.apply(nestedPrc);
+ System.out.println(mapped);
+ assertTrue(mapped.contains(
+ new AuthenticationContextClassReferencePrincipal("http://proxy.example.org/ac/classes/mfa")));
+
+ }
+
+ @Test
+ public void testMappedAndPassedThroughSuccess() {
+
+
+ // The second principal is passed-through as no mapping exists
+ final List<Principal> requestedPrincipals =
+ List.of(new AuthnContextClassRefPrincipal("http://example.org/ac/classes/mfa"),
+ new AuthnContextClassRefPrincipal("http://example.org/ac/classes/pass-through"));
+ rpc.setRequestedPrincipals(requestedPrincipals);
+ rpc.setOperator("exact");
+
+ final Map<Principal,Collection<Principal>> mappings = new HashMap<>();
+ mappings.put(new AuthnContextClassRefPrincipal("http://example.org/ac/classes/mfa"),
+ List.of(new AuthenticationContextClassReferencePrincipal("http://proxy.example.org/ac/classes/mfa")));
+ function.setMappings(mappings);
+
+ final Collection<AuthenticationContextClassReferencePrincipal> mapped = function.apply(nestedPrc);
+ System.out.println(mapped);
+ assertTrue(mapped.contains(
+ new AuthenticationContextClassReferencePrincipal("http://proxy.example.org/ac/classes/mfa")));
+ assertTrue(mapped.contains(
+ new AuthenticationContextClassReferencePrincipal("http://example.org/ac/classes/pass-through")));
+
+ }
+
+ @Test
+ public void testMultipleMappedAndPassedThroughSuccess() {
+
+
+ // The second principal is passed-through as no mapping exists
+ final List<Principal> requestedPrincipals =
+ List.of(new AuthnContextClassRefPrincipal("http://example.org/ac/classes/mfa"),
+ new AuthnContextClassRefPrincipal("http://example.org/ac/classes/pass-through"));
+ rpc.setRequestedPrincipals(requestedPrincipals);
+ rpc.setOperator("exact");
+
+ final Map<Principal,Collection<Principal>> mappings = new HashMap<>();
+ mappings.put(new AuthnContextClassRefPrincipal("http://example.org/ac/classes/mfa"),
+ List.of(new AuthenticationContextClassReferencePrincipal("http://proxy.example.org/ac/classes/mfa"),
+ new AuthenticationContextClassReferencePrincipal(
+ "http://proxy.two.example.org/ac/classes/mfa")));
+ function.setMappings(mappings);
+
+ final Collection<AuthenticationContextClassReferencePrincipal> mapped = function.apply(nestedPrc);
+ System.out.println(mapped);
+ assertTrue(mapped.contains(
+ new AuthenticationContextClassReferencePrincipal("http://proxy.example.org/ac/classes/mfa")));
+ assertTrue(mapped.contains(
+ new AuthenticationContextClassReferencePrincipal("http://proxy.two.example.org/ac/classes/mfa")));
+ assertTrue(mapped.contains(
+ new AuthenticationContextClassReferencePrincipal("http://example.org/ac/classes/pass-through")));
+
+ }
+
+}
diff --git a/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunctionTest.java b/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunctionTest.java
new file mode 100644
index 0000000..401d057
--- /dev/null
+++ b/oidc-common-profile-api/src/test/java/net/shibboleth/oidc/profile/config/navigate/ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunctionTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.oidc.profile.config.navigate;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
+import net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal;
+
+/** Tests for ProxyAwareDefaultOIDCAuthenticationContextClassLookupFunction.*/
+public class ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunctionTest {
+
+ private ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction function;
+
+ private ProfileRequestContext prc;
+
+ private ProfileRequestContext nestedPrc;
+
+ private AuthenticationContext ac;
+
+ private RequestedPrincipalContext rpc;
+
+ @BeforeMethod
+ public void setup() {
+ prc = new ProfileRequestContext();
+ ac = prc.getSubcontext(AuthenticationContext.class, true);
+ nestedPrc = ac.getSubcontext(ProfileRequestContext.class, true);
+ rpc = ac.getSubcontext(RequestedPrincipalContext.class, true);
+ }
+
+ @Test
+ public void testSingleMappingSuccess() {
+
+ final Map<String,Collection<Principal>> mappings = new HashMap<>();
+ mappings.put(
+ "pwd",
+ List.of(new AuthenticationMethodPrincipal
+ ("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")));
+
+ function = new ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction(mappings);
+
+ final Collection<Principal> mapped = function.apply(List.of("pwd"));
+ assertTrue(mapped.contains(
+ new AuthenticationMethodPrincipal
+ ("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")));
+
+ }
+
+ @Test
+ public void testSingleMappingSuccess_NotMappedIgnored() {
+
+
+ final Map<String,Collection<Principal>> mappings = new HashMap<>();
+ mappings.put(
+ "pwd",
+ List.of(new AuthenticationMethodPrincipal
+ ("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")));
+ function = new ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction(mappings);;
+
+ // OTP should not be in the result
+ final Collection<Principal> mapped = function.apply(List.of("pwd","otp"));
+ assertEquals(mapped.size(), 1);
+ assertTrue(mapped.contains(new AuthenticationMethodPrincipal
+ ("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")));
+
+ }
+
+ @Test
+ public void testSingleMappingSuccess_EmptyInput() {
+
+ // OTP should not be in the result
+ final Collection<Principal> mapped = function.apply(Collections.emptyList());
+ assertEquals(mapped.size(), 0);
+ }
+
+ @Test
+ public void testSingleMappingSuccess_NullMappings() {
+
+ function = new ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction(null);
+
+ // OTP should not be in the result
+ final Collection<Principal> mapped = function.apply(Collections.emptyList());
+ assertEquals(mapped.size(), 0);
+ }
+
+ @Test
+ public void testSingleMappingSuccess_EmptyMapping() {
+
+ final Map<String,Collection<Principal>> mappings = new HashMap<>();
+ mappings.put("pwd", Collections.emptyList());
+ function = new ProxyAwareDefaultOIDCAuthenticationContextClassResponseLookupFunction(mappings);
+
+ // OTP should not be in the result
+ final Collection<Principal> mapped = function.apply(Collections.emptyList());
+ assertEquals(mapped.size(), 0);
+ }
+
+
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list