1:00 - 1:30pm | Introduction |
1:30 - 2:00pm | Trust management + OP configuration |
2:00 - 3:00pm | Authentication |
3:00 - 3:30pm | Coffee break |
3:30 - 4:15pm | Attribute definitions and filtering |
4:15 - 4:30pm | Subject identifier |
4:30 - 5:00pm | Profile configurations |
Introduction
Section Topics
- Project in general
- Project resources (releases, documentation and source code)
- Support channels
- Tutorial logistics
Project in general
- https://openid.net/connect/
- OAuth 2.0 based interfaces have become very popular because they were chosen by the social media providers
- Relying Party libraries exist for many programming languages
- Specifications
- Certification tool + programme
Project resources
- https://github.com/CSCfi/shibboleth-idp-oidc-extension
- idp-oidc-extension-parent
- idp-oidc-extension-api
- idp-oidc-extension-impl
Support channels
Shibboleth mailing lists: https://www.shibboleth.net/community/lists/
- Currently, before official releases: https://marc.info/?l=shibboleth-dev
GitHub issues
Tutorial logistics
Everybody should have a paper note containing IP address and a password for cloud-user
The virtual machines are running CentOS 7 with the following software already installed
- OpenJDK 8 JRE
- JAVA_HOME = /usr/lib/jvm/jre-1.8.0
- Apache 2
- Running on ports 80 and 8443
- OICD RP module mod_auth_openidc
- Jetty v9.4.2
- Running on ports 8080 and 443
- /opt/jetty
- /opt/shibboleth-idp/jetty-base
- MariaDB
- Database name for IdP: 'idp'
- Username 'idp' password: 'not_set_yet'
- 389 Directory Server
- Admin 'cn=Directory Manager' and pwd 'testpword'
- End-user teppo, password testaaja
- Shibboleth IdP 3.4 SNAPSHOT with GEANT OIDC plugin (early October)
- service name shibboleth-idp
- IDP home directory /opt/shibboleth-idp
Exercises
- Verify that you can log in to your virtual machine
- SSH-connection to the IP address as cloud-user with the given password
Restart the shibboleth-idp service
Verify from the logs that it starts up without errors
Trust Management & OP configuration
Section Topics
- SAML IdP Metadata vs. OpenID Provider Configuration
- OIDC Client Information
- Trust relationship establishment between Shibboleth OP and test RP
SAML IdP Metadata vs. OpenID Provider Configuration
- Example IdP metadata: https://idp.csc.fi/idp/shibboleth
- By default, the contents are fetched from /opt/shibboleth-idp/metadata/idp-metadata.xml
- The file is generated by the installation script and is NOT updated afterwards automatically
- Example federation metadata: https://haka.funet.fi/metadata/haka-metadata.xml
- Signed by the federation operator (trusted 3rd party)
- OpenID Connect Discovery spec - responds to two questions
- How the OP configuration is found?
- https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
- Webfinger protocol exploited for finding out the issuer name from the resource identifier
- URL format: <issuer>/.well-known/openid-configuration
- https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
- What are the contents of the OP configuration?
- How the OP configuration is found?
- Two ways to publish OP configuration in Shibboleth OP: https://github.com/CSCfi/shibboleth-idp-oidc-extension/wiki/DiscoveryAndOPConfiguration#openid-provider-metadata
- Static file - example found at /opt/shibboleth-idp/static/.well-known/openid-configuration
- Static file with dynamic claims - example found at /opt/shibboleth-idp/flows/oidc/discovery (URL-endpoint ../idp/profile/oidc/discovery)
Exercises
Google OP issuer name is 'https://accounts.google.com'
What is the endpoint URL for the openid-configuration?
Check the contents of Google's openid-configuration
Everybody has a Shibboleth OP instance running on a virtual machine with public IP. The OP issuer name is https://IP_ADDRESS
What is the endpoint URL for the openid-configuration?
What are the contents of the well-known endpoint?
What are the contents of the /idp/profile/oidc/discovery -endpoint? HINT: Copy-paste it to jsolint.com service for making it "human-readable".
Why they are different? Check /opt/shibboleth-idp/flows/oidc/discovery/discovery-beans.xml
OIDC Client Metadata
Static configuration example from Google:
Dynamic registration:
There's no direct equivalent to SAML SP Metadata (or EntityDescriptor/EntitiesDescriptor) on OIDC
- Similar federation metadata signing logic cannot be directly applied to OIDC
- See OIDC Federation draft
- https://openid.net/specs/openid-connect-federation-1_0.html
- Applies to OP discovery + dynamic client registration phases - different from the SAML R&E model
Trust relationship establishment between Shibboleth OP and test RP
Exercises
- Try OIDC flow with an RP that is not (yet) trusted
The OIDC sequence can be started with https://IP_ADDRESS:8443/protected/ endpoint - You should end up into an error screen at Shibboleth OP. The logs should show that the client is not trusted.
- Statically add an RP as trusted (RP config already done)
Check the RP-side configuration first from /etc/httpd/conf.d/auth_openidc.conf
Pick up the settings for client_id, client_secret, redirect_uris and scope from the RP configuration. Also add "response_types":["id_token","code"] and "grant_types":["authorization_code","implicit","refresh_token"] claims and apply them to /opt/shibboleth-idp/metadata/oidc-client.json. Either replace the existing configuration for client demo_rp, or add an additional configuration, as instructed by our wiki (MetadataConfiguration).
Reload the OIDC client metadata by reloading service shibboleth.ClientInformationResolverService.
Hints, Tips and Result[root@gn43-oidcshibop-devel shibboleth-idp]# /opt/shibboleth-idp/bin/reload-service.sh -id shibboleth.ClientInformationResolverService
- You should now get the login screen when starting the login sequence at: https://IP_ADDRESS:8443/protected/. Use username teppo with password testaaja. Check the logs during the login sequence.
Configuring Authentication
Section Topics
- OIDC Authentication Request
- Authentication flow selection for OIDC authentication request
OIDC Authentication Request
- Requested Authentication Context Class Reference values are defined by acr_values request parameter and acr claims request.
- Request may be essential or non-essential.
- prompt has options
- none, The Authorization Server MUST NOT display any authentication or consent user interface pages. Translates to isPassive.
- login, The Authorization Server SHOULD prompt the End-User for reauthentication. Translates to forceAuthn.
- consent, The Authorization Server SHOULD prompt the End-User for consent before returning information to the Client
- select_account, The Authorization Server SHOULD prompt the End-User to select a user account. Not supported by current implementation.
- max_age, specifies the allowable elapsed time in seconds since the last time the End-User was actively authenticated by the OP.
Authentication flow selection for OIDC authentication request
Exercises
ACR value
- Run authentication sequence.
- Verify the value and existence of the ACR claim.
Verify the ACR claim value from your landing page.
The value is set in action AddAcrToIdToken. Verify from the logs the action has taken place.
Client receives the ACR claim in ID Token. Locate ID Token from Token Response (field "id_token") in the logs. Decode the ID Token and verify the existence and value of ACR claim. One option for you to decode the ID Token is http://calebb.net/
Select flow by ACR value
Modify client to request for ACR value "ipaddress".
nano +417 /etc/httpd/conf.d/auth_openidc.conf OIDCAuthRequestParams acr_values=ipaddress service httpd restart
- Run authentication sequence.
Follow log entries, identify requested ACR and what is actually sent back as ACR in the response. Can you explain why they do not match?
Activate IPAddress authentication, configure it for acr "ipaddress" and verify it is actually used as preferred authentication flow.
Create essential claims request for ACR values urn:mace:incommon:iap:silver and urn:mace:incommon:iap:bronze. This is now request that must be met.
nano +417 /etc/httpd/conf.d/auth_openidc.conf OIDCAuthRequestParams claims=%7B%22id_token%22%3A%7B%22acr%22%3A%20%7B%22essential%22%3A%20true%2C%22values%22%3A%20%5B%22urn%3Amace%3Aincommon%3Aiap%3Asilver%22%2C%22urn%3Amace%3Aincommon%3Aiap%3Abronze%22%5D%7D%7D%7D service httpd restart
Start a new authentication sequence and see the result. This behavior should be something you are used to in SAML2 world.
Let's return to the original state
nano +417 /etc/httpd/conf.d/auth_openidc.conf #OIDCAuthRequestParams claims=%7B%22id_token%22%3A%7B%22acr%22%3A%20%7B%22essential%22%3A%20true%2C%22values%22%3A%20%5B%22urn%3Amace%3Aincommon%3Aiap%3Asilver%22%2C%22urn%3Amace%3Aincommon%3Aiap%3Abronze%22%5D%7D%7D%7D service httpd restart nano +143 /opt/shibboleth-idp/conf/idp.properties #Remove IPAddress as active authentication option idp.authn.flows=Password systemctl restart shibboleth-idp
prompt=consent and other prompt parameters
Set the consent to be requested
nano +417 /etc/httpd/conf.d/auth_openidc.conf OIDCAuthRequestParams prompt=consent service httpd restart
- Authenticate the user few times and verify this feature actually works as expected.
- Try different combinations of the parameter
Attribute Definitions
Section Topics
- OIDC user attributes possible locations
- OIDC Attribute resolving principle, authorization, token and userinfo endpoints
- OIDC attribute encoders
OIDC user attributes possible locations
User attributes may be returned either in ID Token http://openid.net/specs/openid-connect-core-1_0.html#IDToken or in UserInfo response http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse.
Whether the attribute ends up to the ID Token or UserInfo response depends on authentication request.
- If claim is requested by standard scope parameter, attribute will be set to userinfo response unless response type is "id_token" (i.e. UserInfo endpoint cannot be accessed).
- Client may specifically request claim to be returned either in ID Token or in UserInfo response
Third option is of course some agreement between RP and OP about non standard scope or some out of band agreement.
OIDC Attribute resolving principle, authorization, token and userinfo endpoints.
- Authentication endpoint. Front-channel endpoint responsible of authenticating the user are asking for consent. May return depending on response type ID Token, authorization code or Access Token or any combination of the three items.
- Token endpoint. Back-channel endpoint that is responsible of authenticating the client RP. Swaps authorization code(or Refresh Token) to Access Token, ID Token and to Refresh Token.
Userinfo endpoint. Back-channel endpoint that can be accessed with Access Token returning UserInfo response.
Attribute Resolving principle
Each of the endpoints perform attribute resolving!
Back-channel endpoints do not have all session/context information available!
Attributes that are based on session/context information must be instructed to be carried in tokens (i.e. encoded directly to authorization code and Access Token) unless implicit flow is used.
Attribute resolvers that use session/context information must check the existence for the source information and fail gracefully if checking fails
Resolver example<AttributeDefinition id="password" xsi:type="ScriptedAttribute" dependencyOnly="true" language="nashorn"> <Script><![CDATA[ logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.script.password"); <!-- Subject does not have credentials populated in Token and UserInfo endpoints, have to give up in such case --> subjectCtx = profileContext.getSubcontext("net.shibboleth.idp.authn.context.SubjectContext"); subject = subjectCtx.getSubjects()[0]; if (!subject.getPrivateCredentials().isEmpty()){ password.addValue(subject.getPrivateCredentials().toArray()[0].getName()); } ]]></Script> </AttributeDefinition>
OIDC attribute encoders
- oidcext:OIDCString, for encoding an IdPAttribute with simple string values as JSON Object.
- oidcext:OIDCScopedString, for encoding an IdPAttribute with scoped string values as JSON Object.
- oidcext:OIDCByte, for encoding an IdPAttribute with binary values as JSON Object.
Encoder formatting options
Default
<AttributeEncoder xsi:type="oidcext:OIDCString" name="affiliation" /> Input: IdPAttribute["member", "staff"] Output: "affiliation": "member staff"
asArray
<AttributeEncoder xsi:type="oidcext:OIDCString" asArray="true" name="affiliation" /> Input: IdPAttribute["member", "staff"] Output: "affiliation":["member","staff"]
asInt
<AttributeEncoder xsi:type="oidcext:OIDCString" asInt="true" name="updated_at" /> Input: IdPAttribute["1536143427"] Output: "updated_at": 1536143427
asBoolean
<AttributeEncoder xsi:type="oidcext:OIDCString" asBoolean="true" name="email_verified" /> Input: IdPAttribute["true"] Output: "email_verified": true
asObject
<AttributeDefinition id="address" xsi:type="ScriptedAttribute"> <Dependency ref="staticAttributes" /> <Script><![CDATA[address.addValue("{\"street_address\":\""+street_address.getValues().get(0) + "\"," +"\"locality\":\""+locality.getValues().get(0) + "\"," +"\"region\":\""+region.getValues().get(0) + "\"," +"\"postal_code\":\""+postal_code.getValues().get(0) + "\"," +"\"country\":\""+country.getValues().get(0) + "\"}");]]></Script> <AttributeEncoder xsi:type="oidcext:OIDCString" asObject="true" name="address" /> </AttributeDefinition> Output: "address":{"street_address":"234 Hollywood Blvd.","country":"US","locality":"Los Angeles","region":"CA","postal_code":"90210"}
Encoder delivery options
placeToIDToken & denyUserinfo
<!-- This demonstrates a claim that is placed always to id token --> <AttributeDefinition id="email_idtoken" xsi:type="Simple" sourceAttributeID="email"> <Dependency ref="email" /> <AttributeEncoder xsi:type="oidcext:OIDCString" placeToIDToken="true" denyUserinfo="true" name="email" /> </AttributeDefinition>
setToToken
Attribute not resolvable in token and UserInfo endpoints must be carried in tokens if necessary.
<AttributeDefinition id="password" xsi:type="ScriptedAttribute" dependencyOnly="true" language="nashorn"> <Script><![CDATA[ logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.script.password"); subjectCtx = profileContext.getSubcontext("net.shibboleth.idp.authn.context.SubjectContext"); <!-- Subject does not have credentials populated in Token and UserInfo endpoints, have to give up in such case --> if (subjectCtx!=null){ subject = subjectCtx.getSubjects()[0]; password.addValue(subject.getPrivateCredentials().toArray()[0].getName()); } ]]></Script> <AttributeEncoder xsi:type="oidcext:OIDCString" setToToken="true" name="password"/> </AttributeDefinition>
Exercises
Available contexts in Endpoints
- attribute-resolver.xml has a scripted attribute "scriptedAuthenticationFlowId" commented out. Activate the attribute resolving.
Authenticate user using with this new configuration. We are not creating release rules for the attribute, yet. See log for any errors related to the attribute.
Change the response type to "id_token". It means we are using only authentication endpoint.
nano +632 /etc/httpd/conf.d/auth_openidc.conf OIDCResponseType "id_token" service httpd restart
Authenticate user using with this new configuration. Notice there are not errors related to resolving the attribute. Can you explain why?
Change the response type back to "code". Correct the attribute to not cause errors. Correct also the attribute to be carried in tokens.
Formatting attribute
Authenticate the user. Locate "manipe" claim from the UserInfo response.
Instruct "manipe" to be encoded as an array. Verify the result from the UserInfo response.
Instruct "manipe" to be encoded as an array of integers. Verify the result from the UserInfo response.
Attribute Filtering
Section Topics
- Requesting Attributes in OIDC
- Filtering attributes for OIDC RPs
Requesting Attributes in OIDC
There are two main mechanisms for RP to ask for attributes,
- Authentication request scope - parameter
- There is a set of standard scope values profile, email, address and phone.
- The claims requested by the standard scope values are expected to be returned from UserInfo endpoint unless response type is "id_token"
- The claims requested by the standard scope values are treated as voluntary
- You may define your own scope values and rules for it.
- Authentication request claims - parameter
- You must declare the target for the claim, ID Token or UserInfo response
- You may list the claim as essential claim
- You may list a expected value for the claim
{ "userinfo": { "given_name": {"essential": true}, "nickname": null, "picture": null, "http://example.info/claims/groups": null }, "id_token": { "email": {"essential": true}, "email_verified": {"essential": true}, "sub": {"value": "248289761001"} "auth_time": {"essential": true}, "acr": {"essential": true, "values": ["urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze"]} } }
Filtering attributes for OIDC RPs
It is your job to resolve and filter attributes to match the requests. OIDC extension has reserved the right to control some claims you should not try to resolve or filter.
oidcext:OIDCScope
PolicyRule which returns true if any of the scope values in the authentication request matches a supplied string.
<!-- This demonstrates a rule that releases email claims in response to all oidc authentication requests having scope email. The requester needs to have scope email as a registered scope. --> <AttributeFilterPolicy id="OPENID_SCOPE_EMAIL"> <PolicyRequirementRule xsi:type="oidcext:OIDCScope" value="email" /> <AttributeRule attributeID="email"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> <AttributeRule attributeID="email_verified"> <PermitValueRule xsi:type="ANY" /> </AttributeRule> </AttributeFilterPolicy>
oidcext:AttributeInOIDCRequestedClaims
Matcher which returns attribute values after comparing them to requested claims parameter of oidc authentication request.
<!-- This demonstrates a rule that releases email in id token if specifically asked to be released as essential for id token --> <AttributeFilterPolicy id="REQUESTED_CLAIMS"> <PolicyRequirementRule xsi:type="ANY" /> <AttributeRule attributeID="email_idtoken"> <PermitValueRule xsi:type="oidcext:AttributeInOIDCRequestedClaims" matchOnlyIDToken="true" onlyIfEssential="true" /> </AttributeRule> </AttributeFilterPolicy>
Exercises
Define a new scope "campus". Target is to have scope "campus" that includes a claim "campus_id" to ID Token.
Locate "campusId" attribute from attribute resolver. Add a new filtering rules that releases campusId when scope "campus" is requested.
Modify client RP to request for scope "campus".
nano +633 /etc/httpd/conf.d/auth_openidc.conf OIDCScope "openid campus" service httpd restart
Authenticate the user. Verify from the logs that scope "campus" is being requested. Find out from the logs why it is not being released.
- Add scope "campus" for the RP as a valid scope value.
Authenticate the user. Verify from the logs that scope "campus" is being requested. Find out from the logs is it being released to ID Token or to UserInfo response.
Modify "campusId" attribute resolver to encode the claim always and only to ID Token.
Authenticate the user. Verify from the logs that scope "campus" is being requested. Verify from the logs it is being released only to ID Token.
Define attribute release rules to release "campusId" attribute to be released if asked to be released for ID Token as essential claim.
1. Make sure "campusId" is not requested anymore by scope.
nano +633 /etc/httpd/conf.d/auth_openidc.conf OIDCScope "openid"
2. Modify RP to ask "campusId" as essential ID Token claim.
nano +417 /etc/httpd/conf.d/auth_openidc.conf OIDCAuthRequestParams claims=%7B%22id_token%22%3A%7B%22campus_id%22%3A%20%7B%22essential%22%3A%20true%7D%7D%7D service httpd restart
3. Add a new filtering rule that will release "campusId" only if requested to be released as essential ID Token claim
4. Authenticate the user and verify from the logs the attribute is released. At this point you should be able to do it without hints and tips.
Subject Identifier
Section Topics
- Subject Identifier
- Subject Identifier Generation
Subject Identifier
Locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client. It MUST NOT exceed 255 ASCII characters in length. The value is a case sensitive string.
Two types of Subject Identifiers, public and pairwise, http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
Different RPs may belong to same pairwise group by sharing the sector_identifier_uri - value
Placed always in ID Token and UserInfo response, whether requested or not.
Subject Identifier Generation
Extension provides default resolver and a configuration for it.
Configuring Subject claim
Modify the registration data of the RP to list subject of type pairwise.
nano /opt/shibboleth-idp/metadata/oidc-client.json { "scope":"openid info profile email address phone", "redirect_uris":["https://192.168.0.150:8443/protected/redirect_uri"], "client_id":"test_rp", "client_secret":"testSecret1234", "response_types":["id_token","code"], "grant_types":["authorization_code","implicit","refresh_token"], "subject_type":"pairwise" }
Authenticate the user. Verify from landing page or from logs that the value of subject is different from previously used public value.
- Activate the attributes "subject-public" and "subject-pairwise". Ensure the filtering rules are such that these attributes are not filtered out but the attribute "subject" is filtered out for your RP.
Modify the registration data of the rp to request subject of type public.
nano /opt/shibboleth-idp/metadata/oidc-client.json { "scope":"openid info profile email address phone", "redirect_uris":["https://192.168.0.150:8443/protected/redirect_uri"], "client_id":"test_rp", "client_secret":"testSecret1234", "response_types":["id_token","code"], "grant_types":["authorization_code","implicit","refresh_token"], "subject_type":"public" }
Authenticate the user. Verify from landing page or from logs that the value of subject is now this plain text value.
Profile Configurations
Section Topics
- SAML and OIDC profile configurations
- Profile configuration options
- Default vs. RP-specific profile configurations
SAML and OIDC profile configurations
The profile configuration file is /opt/shibboleth-idp/conf/relying-party.xml
<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"> <!-- Unverified RP configuration, defaults to no support for any profiles. Add <ref> elements to the list to enable specific default profile settings (as below), or create new beans inline to override defaults. "Unverified" typically means the IdP has no metadata, or equivalent way of assuring the identity and legitimacy of a requesting system. To run an "open" IdP, you can enable profiles here. --> <bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <list> <!-- <bean parent="SAML2.SSO" p:encryptAssertions="false" /> --> </list> </property> </bean> <!-- Default configuration, with default settings applied for all profiles, and enables the attribute-release consent flow. --> <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty"> <property name="profileConfigurations"> <list> <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" /> <ref bean="SAML1.AttributeQuery" /> <ref bean="SAML1.ArtifactResolution" /> <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" /> <ref bean="SAML2.ECP" /> <ref bean="SAML2.Logout" /> <ref bean="SAML2.AttributeQuery" /> <ref bean="SAML2.ArtifactResolution" /> <ref bean="Liberty.SSOS" /> </list> </property> </bean> ...
The OIDC profile configuration file is /opt/shibboleth-idp/conf/oidc-relying-party.xml
... <!-- OIDC Profile Configurations. --> <bean id="OIDC.SSO" class="org.geant.idpextension.oidc.config.OIDCCoreProtocolConfiguration" p:securityConfiguration-ref="%{idp.security.oidc.config:shibboleth.oidc.DefaultSecurityConfiguration}" p:iDTokenLifetime="%{idp.oidc.idToken.defaultLifetime:PT1H}" p:accessTokenLifetime="%{idp.oidc.accessToken.defaultLifetime:PT10M}" p:authorizeCodeLifetime="%{idp.oidc.authorizeCode.defaultLifetime:PT5M}" p:refreshTokenLifetime="%{idp.oidc.refreshToken.defaultLifetime:PT2H}" p:servletRequest-ref="shibboleth.HttpServletRequest" p:tokenEndpointAuthMethods="%{idp.oidc.tokenEndpointAuthMethods:client_secret_basic,client_secret_post,client_secret_jwt,private_key_jwt}" /> <bean id="OIDC.UserInfo" class="org.geant.idpextension.oidc.config.OIDCUserInfoConfiguration" p:securityConfiguration-ref="%{idp.security.oidc.config:shibboleth.oidc.DefaultSecurityConfiguration}" p:servletRequest-ref="shibboleth.HttpServletRequest" /> <bean id="OIDC.Registration" class="org.geant.idpextension.oidc.config.OIDCDynamicRegistrationConfiguration" p:securityConfiguration-ref="%{idp.security.oidc.config:shibboleth.oidc.DefaultSecurityConfiguration}" p:servletRequest-ref="shibboleth.HttpServletRequest" p:tokenEndpointAuthMethods="%{idp.oidc.dynreg.tokenEndpointAuthMethods:client_secret_basic,client_secret_post,client_secret_jwt,private_key_jwt}" /> <bean id="OIDC.Configuration" class="org.geant.idpextension.oidc.config.OIDCProviderInformationConfiguration" p:securityConfiguration-ref="%{idp.security.oidc.config:shibboleth.oidc.DefaultSecurityConfiguration}" p:servletRequest-ref="shibboleth.HttpServletRequest"/> <bean id="OAUTH2.Revocation" class="org.geant.idpextension.oauth2.config.OAuth2TokenRevocationConfiguration" p:securityConfiguration-ref="%{idp.security.oidc.config:shibboleth.oidc.DefaultSecurityConfiguration}" p:servletRequest-ref="shibboleth.HttpServletRequest"/> ...
The main configuration file is /opt/shibboleth-idp/conf/relying-party.xml
<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"> <import resource="oidc-relying-party.xml"/> <bean id="shibboleth.UnverifiedRelyingParty" p:responderIdLookupStrategy-ref="profileResponderIdLookupFunction" parent="RelyingParty"> <property name="profileConfigurations"> <list> <bean parent="OIDC.Registration" /> <bean parent="OIDC.Configuration" /> </list> </property> </bean> <bean id="shibboleth.DefaultRelyingParty" p:responderIdLookupStrategy-ref="profileResponderIdLookupFunction" parent="RelyingParty"> <property name="profileConfigurations"> <list> <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" /> <ref bean="SAML2.Logout" /> <bean parent="OIDC.SSO" p:postAuthenticationFlows="attribute-release" /> <bean parent="OIDC.UserInfo"/> <bean parent="OAUTH2.Revocation"/> </list> </property> </bean> ...
Profile configuration options
- https://github.com/CSCfi/shibboleth-idp-oidc-extension/wiki/ProfileConfigurations
- https://wiki.shibboleth.net/confluence/display/IDP30/RelyingPartyConfiguration
- Shared options with all configurations
- Standard security configuration and our extensions.
- Used in various ways, depending on the context
- OIDC.Configuration: signing + encryption configuration (credentials, algorithms) for openid-configuration
- OIDC.Registration: which signing + encryption configuration details are supported
- OIDC.SSO: which signing + encryption configuration is enabled
- Used in various ways, depending on the context
- Inbound interceptor flows
- Outbound interceptor flows
- Standard security configuration and our extensions.
- Client authenticable configuration options for OIDC.SSO, OIDC.Registration and OAUTH2.Revocation
- Endpoint authentication methods
- Flow-aware configuration options for OIDC.SSO and OIDC.Registration
- Flags to enable implicit, hybrid and authorization code flows
- Flag to enable refresh tokens
- Flow-specific options
- Multiple options especially for OIDC.SSO and OIDC.Registration (lifetimes, etc)
- Post authentication flows, default authentication methods for OIDC.SSO
- Shared options with all configurations
Default vs. RP-specific profile configuration
- Default profile configurations enable wide set of features
Standard shibboleth.RelyingPartyOverrides mechanism can be used with OIDC RPs too
Snippet of /opt/shibboleth-idp/conf/relying-party.xml... <util:list id="shibboleth.RelyingPartyOverrides"> <bean parent="RelyingPartyByName" p:responderIdLookupStrategy-ref="profileResponderIdLookupFunction" c:relyingPartyIds="test_rp"> <property name="profileConfigurations"> <list> <bean parent="OIDC.SSO" /> </list> </property> </bean> </util:list> ...
- Some of the profile configuration options have overlapping claims in the client metadata
- E.g. token endpoint authentication methods
Exercises
Add additional audience test_api for all authenticated relying parties
Verify that the additional audience is visible in the id_token.
Remove postAuthenticationFlows and additionalAudiencesForIdToken settings for test_rp.
Are the additional audiences now visible for test_rp as they are defined in shibboleth.DefaultRelyingParty? Why?
What happens if you configure that only private_key_jwt is accepted as the token endpoint authentication method for test_rp?
Add context-check post authentication flow to the relying party configuration
Edit /opt/shibboleth-idp/conf/intercept/context-check-intercept-config.xml for your needs. HINT! The existing file contains good basis, find out from attribute-resolver which is the username in your configuration.
Restart IDP service and try to access the test RP with teppo and teppo2 (same password). You can logout the user via /idp/profile/Logout -endpoint.