diff --git a/testbed/integration/shibboleth-idp/Dockerfile b/testbed/integration/shibboleth-idp/Dockerfile
index 1a4087074..6cfe13c7f 100644
--- a/testbed/integration/shibboleth-idp/Dockerfile
+++ b/testbed/integration/shibboleth-idp/Dockerfile
@@ -1,4 +1,4 @@
-FROM i2incommon/shib-idp:4.1.4_20210802
+FROM i2incommon/shib-idp:4.2.1_20220624
# The build args below can be used at build-time to tell the build process where to find your config files. This is for a completely burned-in config.
ARG TOMCFG=config/tomcat
@@ -11,15 +11,23 @@ ARG SHBEDWAPP=config/shib-idp/edit-webapp
ARG SHBMSGS=config/shib-idp/messages
ARG SHBMD=config/shib-idp/metadata
+#enable OIDC plugins and generate needed keys
+ADD ${SHBCREDS} /opt/shibboleth-idp/credentials
+RUN /opt/shibboleth-idp/bin/plugin.sh -i https://shibboleth.net/downloads/identity-provider/plugins/oidc-common/2.1.0/oidc-common-dist-2.1.0.tar.gz --noPrompt
+RUN /opt/shibboleth-idp/bin/plugin.sh -i https://shibboleth.net/downloads/identity-provider/plugins/oidc-op/3.2.1/idp-plugin-oidc-op-distribution-3.2.1.tar.gz --noPrompt
+RUN /opt/shibboleth-idp/bin/jwtgen.sh -t RSA -s 2048 -u sig -i defaultRSASign | tail -n +2 > /opt/shibboleth-idp/credentials/idp-signing-rs.jwk
+RUN /opt/shibboleth-idp/bin/jwtgen.sh -t EC -c P-256 -u sig -i defaultECSign | tail -n +2 > /opt/shibboleth-idp/credentials/idp-signing-es.jwk
+RUN /opt/shibboleth-idp/bin/jwtgen.sh -t RSA -s 2048 -u enc -i defaultRSAEnc | tail -n +2 > /opt/shibboleth-idp/credentials/idp-encryption-rsa.jwk
+
# copy in the needed config files
ADD ${TOMCFG} /usr/local/tomcat/conf
ADD ${TOMCERT} /opt/certs
ADD ${TOMWWWROOT} /usr/local/tomcat/webapps/ROOT
ADD ${SHBCFG} /opt/shibboleth-idp/conf
-ADD ${SHBCREDS} /opt/shibboleth-idp/credentials
#ADD ${SHBVIEWS} /opt/shibboleth-idp/views
#ADD ${SHBEDWAPP} /opt/shibboleth-idp/edit-webapp
#ADD ${SHBMSGS} /opt/shibboleth-idp/messages
ADD ${SHBMD} /opt/shibboleth-idp/metadata
+
EXPOSE 8080
diff --git a/testbed/integration/shibboleth-idp/config/shib-idp/conf/credentials.xml b/testbed/integration/shibboleth-idp/config/shib-idp/conf/credentials.xml
new file mode 100644
index 000000000..f2d3309b1
--- /dev/null
+++ b/testbed/integration/shibboleth-idp/config/shib-idp/conf/credentials.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testbed/integration/shibboleth-idp/config/shib-idp/conf/idp.properties b/testbed/integration/shibboleth-idp/config/shib-idp/conf/idp.properties
index 50af60005..c3c450a11 100644
--- a/testbed/integration/shibboleth-idp/config/shib-idp/conf/idp.properties
+++ b/testbed/integration/shibboleth-idp/config/shib-idp/conf/idp.properties
@@ -1,5 +1,5 @@
# Load any additional property resources from a comma-delimited list
-idp.additionalProperties=/conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/authn/duo.properties, /credentials/secrets.properties
+idp.additionalProperties=/conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/authn/duo.properties, /credentials/secrets.properties, /conf/oidc.properties
# In most cases (and unless noted in the surrounding comments) the
# commented settings in the distributed files document default behavior.
diff --git a/testbed/integration/shibboleth-idp/config/shib-idp/conf/oidc.properties b/testbed/integration/shibboleth-idp/config/shib-idp/conf/oidc.properties
new file mode 100644
index 000000000..36da7f76d
--- /dev/null
+++ b/testbed/integration/shibboleth-idp/config/shib-idp/conf/oidc.properties
@@ -0,0 +1,141 @@
+# Set the Open ID Connect Issuer value
+idp.oidc.issuer = https://idp.unicon.local
+
+#Dynamic registration properties
+# The validity of registration before a new one is required.
+#idp.oidc.dynreg.defaultRegistrationValidity = PT24H
+# The validity of client secret registered
+#idp.oidc.dynreg.defaultSecretExpiration = P12M
+# The default scopes accepted in dynamic registration
+#idp.oidc.dynreg.defaultScope = openid profile email address phone offline_access
+# The default subject type if not set by client in request. Maybe set to pairwise or public.
+#idp.oidc.dynreg.defaultSubjectType = public
+# The acceptable client authentication methods when using dynamic registration
+#idp.oidc.dynreg.tokenEndpointAuthMethods = client_secret_basic,client_secret_post,client_secret_jwt,private_key_jwt
+# Regardless of what signing algorithms are configured, allow none for request object signing
+#idp.oidc.dynreg.allowNoneForRequestSigning = true
+# Bean to determine whether dynamic registration should validate the remote JWK set if it's defined in the request
+#idp.oidc.dynreg.validateRemoteJwks = shibboleth.Conditions.TRUE
+# Full path to the file containing default metadata policy used for dynamic client registration
+#idp.oidc.dynreg.defaultMetadataPolicyFile =
+# Bean to determine the default metadata policy used for dynamic client registration
+#idp.oidc.dynreg.defaultMetadataPolicy = shibboleth.oidc.dynreg.DefaultMetadataPolicy
+
+# Storage for storing remote jwk sets.
+#idp.oidc.jwk.StorageService = shibboleth.StorageService
+
+#Authorization/Token endpoint properties
+# The acceptable client authentication methods
+#idp.oidc.tokenEndpointAuthMethods = client_secret_basic,client_secret_post,client_secret_jwt,private_key_jwt
+
+# Default lifetime of OIDC tokens (issued to the client or against the OP itself)
+#idp.oidc.authorizeCode.defaultLifetime = PT5M
+#idp.oidc.accessToken.defaultLifetime = PT10M
+#idp.oidc.refreshToken.defaultLifetime = PT2H
+#idp.oidc.idToken.defaultLifetime = PT1H
+
+# Lifetime of entries in revocation cache for authorize code
+#idp.oidc.revocationCache.authorizeCode.lifetime = PT6H
+# Storage for revocation cache. Requires server-side storage
+#idp.oidc.revocationCache.StorageService = shibboleth.StorageService
+
+# Signing keys for id tokens / userinfo response
+idp.signing.oidc.rs.key = %{idp.home}/credentials/idp-signing-rs.jwk
+idp.signing.oidc.es.key = %{idp.home}/credentials/idp-signing-es.jwk
+# Request object decryption key
+idp.signing.oidc.rsa.enc.key = %{idp.home}/credentials/idp-encryption-rsa.jwk
+
+# Set false to preclude issuing unencrypted ID/UserInfo tokens without specific overrides
+#idp.oidc.encryptionOptional = true
+
+#PKCE/AppAuth related properties
+#idp.oidc.forcePKCE = false
+#idp.oidc.allowPKCEPlain = false
+
+# Store user consent to authorization code & access/refresh tokens instead of exploiting consent storage
+#idp.oidc.encodeConsentInTokens = false
+
+# shibboleth.ClientInformationResolverService properties
+#idp.service.clientinfo.failFast = false
+#idp.service.clientinfo.checkInterval = PT0S
+#idp.service.clientinfo.resources = shibboleth.ClientInformationResolverResources
+
+# Special claim handling rules
+# "Encoded" attributes are encrypted and embedded into the access token
+#idp.oidc.encodedAttributes =
+# "Always included" attributes are forced into ID tokens for all response_types
+#idp.oidc.alwaysIncludedAttributes =
+# "Denied" attributes are omitted from the UserInfo token
+#idp.oidc.deniedUserInfoAttributes =
+
+# The source attribute used in generating the sub claim
+idp.oidc.subject.sourceAttribute = uid
+
+# The digest algorithm used in generating the sub claim
+#idp.oidc.subject.algorithm = SHA
+
+# The salt used in generating the subject
+# Do *NOT* share the salt with other people, it's like divulging your private key.
+# It is suggested you move this property into credentials/secrets.properties
+idp.oidc.subject.salt = this_too_should_be_ch4ng3d
+
+# Bean to determine whether SAML metadata should be exploited for trusted OIDC RP resolution
+#idp.oidc.metadata.saml = shibboleth.Conditions.TRUE
+
+# Upgrade interval to the remote JWKs
+#idp.oidc.jwksuri.fetchInterval = PT30M
+
+# Bounds on the next file refresh of the OP configuration resource
+#idp.oidc.config.minRefreshDelay = PT5M
+#idp.oidc.config.maxRefreshDelay = PT4H
+
+# Bean to configure additional response headers: none is added by default, but e.g. shibboleth.ResponseHeaderFilter
+# contains headers further configurable via other properties such as 'idp.hsts', 'idp.frameoptions' and 'idp.csp'.
+#idp.oidc.ResponseHeaderFilter = shibboleth.ResponseHeaderFilter
+
+# Bean used for extracting login_hint from the authentication request. The default function parses login_hint as is.
+#idp.oidc.LoginHintLookupStrategy = DefaultRequestLoginHintLookupFunction
+
+# Bean used for creating SPSessions needed for SLO. By default builds protocol-independent BasicSPSession, as SLO is not yet supported.
+#idp.oidc.SPSessionCreationStrategy = DefaultSPSessionCreationStrategy
+
+# Settings for issue-registration-access-token flow
+#idp.oidc.admin.registration.logging = IssueRegistrationAccessToken
+#idp.oidc.admin.registration.nonBrowserSupported = true
+#idp.oidc.admin.registration.authenticated = false
+#idp.oidc.admin.registration.resolveAttributes = false
+#idp.oidc.admin.registration.lookup.policy = shibboleth.oidc.admin.DefaultMetadataPolicyLookupStrategy
+#idp.oidc.admin.registration.defaultTokenLifetime = P1D
+#idp.oidc.admin.registration.accessPolicy = AccessByIPAddress
+#idp.oidc.admin.registration.policyLocationPolicy = AccessByAdmin
+#idp.oidc.admin.registration.policyIdPolicy = AccessByAdmin
+#idp.oidc.admin.registration.clientIdPolicy = AccessByAdmin
+
+#
+# OAuth2 Settings - these typically involve generic OAuth 2.0 use cases
+#
+
+# Supported grant_type values for token requests
+#idp.oauth2.grantTypes = authorization_code,refresh_token
+
+# Default handling of generic OAuth tokens (for use against arbitrary resource servers)
+#idp.oauth2.accessToken.defaultLifetime = PT10M
+# Set to JWT if desired as a default.
+#idp.oauth2.accessToken.type =
+
+# Set false to preclude issuing unencrypted JWT access tokens without specific overrides
+#idp.oauth2.encryptionOptional = true
+
+# Default scope/audience values if you allow unverified clients without metadata.
+#idp.oauth2.defaultAllowedScope =
+#idp.oauth2.defaultAllowedAudience =
+
+# Regular expression matching OAuth login flows to enable.
+# For most deployments, the default is sufficient to accomodate a variety of methods
+#idp.oauth2.authn.flows = OAuth2Client
+
+# Set true to enforce refresh token rotation (defaults to false)
+#idp.oauth2.enforceRefreshTokenRotation = true
+
+# Revocation method: set to TOKEN to revoke single tokens (defaults to full chain (value = CHAIN))
+#idp.oauth2.revocationMethod = TOKEN
\ No newline at end of file
diff --git a/testbed/integration/shibboleth-idp/config/shib-idp/conf/relying-party.xml b/testbed/integration/shibboleth-idp/config/shib-idp/conf/relying-party.xml
index 478731ac5..84d406b7b 100644
--- a/testbed/integration/shibboleth-idp/config/shib-idp/conf/relying-party.xml
+++ b/testbed/integration/shibboleth-idp/config/shib-idp/conf/relying-party.xml
@@ -23,6 +23,8 @@
+
+
@@ -51,6 +53,10 @@
+
+
+
+
diff --git a/testbed/integration/shibboleth-idp/config/tomcat/context.xml b/testbed/integration/shibboleth-idp/config/tomcat/context.xml
index 98727cb7b..0bba305ef 100644
--- a/testbed/integration/shibboleth-idp/config/tomcat/context.xml
+++ b/testbed/integration/shibboleth-idp/config/tomcat/context.xml
@@ -20,6 +20,7 @@
+
WEB-INF/web.xml
${catalina.base}/conf/web.xml
diff --git a/testbed/integration/shibboleth-idp/config/tomcat/rewrite.config b/testbed/integration/shibboleth-idp/config/tomcat/rewrite.config
new file mode 100644
index 000000000..804401494
--- /dev/null
+++ b/testbed/integration/shibboleth-idp/config/tomcat/rewrite.config
@@ -0,0 +1 @@
+RewriteRule ^/.well-known/openid-configuration$ /idp/profile/oidc/configuration [L]
\ No newline at end of file
diff --git a/testbed/integration/shibboleth-idp/config/tomcat/server.xml b/testbed/integration/shibboleth-idp/config/tomcat/server.xml
index f4b875bca..de89b5842 100644
--- a/testbed/integration/shibboleth-idp/config/tomcat/server.xml
+++ b/testbed/integration/shibboleth-idp/config/tomcat/server.xml
@@ -16,6 +16,7 @@
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
+
diff --git a/testbed/integration/shibboleth-idp/credentials/shib-idp/net.shibboleth.idp.plugin.oidc.op/truststore.asc b/testbed/integration/shibboleth-idp/credentials/shib-idp/net.shibboleth.idp.plugin.oidc.op/truststore.asc
new file mode 100644
index 000000000..083158dc5
--- /dev/null
+++ b/testbed/integration/shibboleth-idp/credentials/shib-idp/net.shibboleth.idp.plugin.oidc.op/truststore.asc
@@ -0,0 +1,32 @@
+
+
Henri Mikkonen id 9355EBCA
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.70
+
+mQINBF46zL0BEACUeQllAAViSlyL8uFBCjlCXdH12GpDL9y8fubm+N50ofonIloA
+YLbJtETVrqpxfeh+SDiERbEG5W02fbM1y3wdSjef0jzAEP3PoXydv/SdNKvomvBP
+U7I9eALgHJI4Nkqzf8ggTrOBHcWbRIRGbVXFRhOE1Z86akmVz3fe3aQzddvzAS7I
+YYX0RxbKiNt8iaxUXUo+P1LopD9Zo2I1NTY8u27RuhtxBr5tnHnsuf38mzjG/l6U
+RzJ8qhHJr6D4E+MLqRo9ndTREOT/d1TeJUvQddXC59VEL75TrYCEc2v/NZ5m9fD6
+yg0+oqgyrQHmZhPVOqoJiz0lkd3rl7lUqCH9yjREr1H5PUchiuhBKBOogwtirqw3
+NMKH6bs0Bu6qUy5fIJRqjxKVv+6fOEty/xnp0xN7xoBEUPEt1M/V3ewwH1zhOwTo
+g4cr4zhTT9RNno3eM0eenEQYapQZ8dFmrNVmhvx9VJlshYGyakrxPwrF3coyC3hh
+HjWE9SzmoyGmmbRgvJVt//SqoGpDyaM+d1hPys9tX2N/E1TlwZiD2brWAtjr2K49
+NC9Skizw4qHAbphq4EMGCKzrp9ksnBvwZAY9JjL0JvdjAabqkyRFVh2Mpm5xSxbw
+d+Twryh5hXaT/EQXsKMC1WlQnIDREjHpm1UOXTzcsFPa9tEW8XUftPWbQQARAQAB
+tCZIZW5yaSBNaWtrb25lbiA8aGVucmkubWlra29uZW5AaWtpLmZpPokCVAQTAQgA
+PhYhBG0Y/WNwj8ygebaMzgJmkYOTVevKBQJeOsy9AhsDBQkHhh+ABQsJCAcCBhUK
+CQgLAgQWAgMBAh4BAheAAAoJEAJmkYOTVevKwWcP+gLrjnrNxqwEx7/Ly/KdjkGD
+0W7aMiQc8acvC9oo74/XXpAD0W1jkK/BXyLH1q/o5Lyjymmm6w7VvEWLSY1Q0+gC
+l+hUOqccH572767UrGEeZeJV8+tNhziTU2S7NagK2A0BelHoA3hIhfGmWLJ+ooJe
+HZXFCov4ThZOpGzu5d04dEYoOv2jVaWwnrjOBzoKcgws9J6RLX+6gOFhZ3Dh5Rxs
+UGhl0ZJuEBQCDT7X9jI4mHsA0Ngo27inb3gxfeCm/ziZhHDV2gZtl777dKVc/sQN
+fqGaRGVi1p37La6KKpfIA3KHRjGf4jfg17AQ1Ix+ZgRIpbPXb7fXQHtBElhIbbn/
+VR2CG0Jdchdc4UozelKU6WNsNlcMn3kfTNFosW7+gTiYEGSxZQC9ylSSl1s9oIFM
+dvk70u4AgTY6w+27TrTRuEpdARoNZG4NhBTJ8g0BkiX6cHVyc5ir5IOVpmewsxN5
+yLg0ed6OwpcK5V8SwGT60hgkkJp71OeBsnLzyzO3/YoI5GVAIgcwtdzptRUt0iL8
+GUccO3mO6Hm4EfJAZHFWRbxX3ITTfCzw4blbXURlIXkPefprptAYX2+rn/z4iC1F
+mJUANl+4WilKuPoAimKGDNi6CvlbckQW2i2i5gsoM3iMxRMsExoZUnoMpfY70Trg
+ToF/jwURMQSCsJnZvyQD
+=g4uH
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/testbed/integration/shibboleth-idp/credentials/shib-idp/net.shibboleth.oidc.common/truststore.asc b/testbed/integration/shibboleth-idp/credentials/shib-idp/net.shibboleth.oidc.common/truststore.asc
new file mode 100644
index 000000000..083158dc5
--- /dev/null
+++ b/testbed/integration/shibboleth-idp/credentials/shib-idp/net.shibboleth.oidc.common/truststore.asc
@@ -0,0 +1,32 @@
+
+
Henri Mikkonen id 9355EBCA
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.70
+
+mQINBF46zL0BEACUeQllAAViSlyL8uFBCjlCXdH12GpDL9y8fubm+N50ofonIloA
+YLbJtETVrqpxfeh+SDiERbEG5W02fbM1y3wdSjef0jzAEP3PoXydv/SdNKvomvBP
+U7I9eALgHJI4Nkqzf8ggTrOBHcWbRIRGbVXFRhOE1Z86akmVz3fe3aQzddvzAS7I
+YYX0RxbKiNt8iaxUXUo+P1LopD9Zo2I1NTY8u27RuhtxBr5tnHnsuf38mzjG/l6U
+RzJ8qhHJr6D4E+MLqRo9ndTREOT/d1TeJUvQddXC59VEL75TrYCEc2v/NZ5m9fD6
+yg0+oqgyrQHmZhPVOqoJiz0lkd3rl7lUqCH9yjREr1H5PUchiuhBKBOogwtirqw3
+NMKH6bs0Bu6qUy5fIJRqjxKVv+6fOEty/xnp0xN7xoBEUPEt1M/V3ewwH1zhOwTo
+g4cr4zhTT9RNno3eM0eenEQYapQZ8dFmrNVmhvx9VJlshYGyakrxPwrF3coyC3hh
+HjWE9SzmoyGmmbRgvJVt//SqoGpDyaM+d1hPys9tX2N/E1TlwZiD2brWAtjr2K49
+NC9Skizw4qHAbphq4EMGCKzrp9ksnBvwZAY9JjL0JvdjAabqkyRFVh2Mpm5xSxbw
+d+Twryh5hXaT/EQXsKMC1WlQnIDREjHpm1UOXTzcsFPa9tEW8XUftPWbQQARAQAB
+tCZIZW5yaSBNaWtrb25lbiA8aGVucmkubWlra29uZW5AaWtpLmZpPokCVAQTAQgA
+PhYhBG0Y/WNwj8ygebaMzgJmkYOTVevKBQJeOsy9AhsDBQkHhh+ABQsJCAcCBhUK
+CQgLAgQWAgMBAh4BAheAAAoJEAJmkYOTVevKwWcP+gLrjnrNxqwEx7/Ly/KdjkGD
+0W7aMiQc8acvC9oo74/XXpAD0W1jkK/BXyLH1q/o5Lyjymmm6w7VvEWLSY1Q0+gC
+l+hUOqccH572767UrGEeZeJV8+tNhziTU2S7NagK2A0BelHoA3hIhfGmWLJ+ooJe
+HZXFCov4ThZOpGzu5d04dEYoOv2jVaWwnrjOBzoKcgws9J6RLX+6gOFhZ3Dh5Rxs
+UGhl0ZJuEBQCDT7X9jI4mHsA0Ngo27inb3gxfeCm/ziZhHDV2gZtl777dKVc/sQN
+fqGaRGVi1p37La6KKpfIA3KHRjGf4jfg17AQ1Ix+ZgRIpbPXb7fXQHtBElhIbbn/
+VR2CG0Jdchdc4UozelKU6WNsNlcMn3kfTNFosW7+gTiYEGSxZQC9ylSSl1s9oIFM
+dvk70u4AgTY6w+27TrTRuEpdARoNZG4NhBTJ8g0BkiX6cHVyc5ir5IOVpmewsxN5
+yLg0ed6OwpcK5V8SwGT60hgkkJp71OeBsnLzyzO3/YoI5GVAIgcwtdzptRUt0iL8
+GUccO3mO6Hm4EfJAZHFWRbxX3ITTfCzw4blbXURlIXkPefprptAYX2+rn/z4iC1F
+mJUANl+4WilKuPoAimKGDNi6CvlbckQW2i2i5gsoM3iMxRMsExoZUnoMpfY70Trg
+ToF/jwURMQSCsJnZvyQD
+=g4uH
+-----END PGP PUBLIC KEY BLOCK-----