OPAudienceInjectionAttackMitigation
Files: conf/relying-partyxml
Format: Native Spring
Overview
An Audience Injection Attack for, amongst others, private key JWT client authentication is discussed in a research paper. The paper outlines a mitigation strategy. This strategy involves setting the value of the audience (aud) claim in a JWT assertion to match the issuer identifier of the OP instead of the token (or target) endpoint URL. This approach is also suggested by the draft RFC.
Mitigation for v4.3.0+
OP v4.3.0 provides new profile configuration options to easily enforce the suggested changes:
useTargetedEndpointAsJWTAudience: Flag to enable use of endpoints (the token or target endpoint) in the JWT client authentication audience (defaults to true)
requireSingleJWTAudience: Flag to require single value in the JWT client authentication audience (defaults to false)
clientAuthenticationJWTType: Mandatory value for the
typ
header used within JWT authentication (default to null, meaning any or missing value is accepted)
The first two options are also available as global properties:
idp.oauth2.jwtAuth.targetedEndpointAsJWTAudience (defaults to true)
idp.oauth2.jwtAuth.requireSingleJWTAudience (defaults to false)
Mitigation for older versions
For older versions, the following methods can be used for preventing the use of token (or target) endpoint URL as the audience:
Globally for all RPs
Define the following kind of bean in the
conf/relying-party.xml
:<bean id="StrictAudienceValidator" class="net.shibboleth.oidc.security.jwt.claims.impl.AudienceClaimsValidator" p:extraAudienceValidation="true"> <property name="audienceLookupStrategy"> <bean parent="shibboleth.BiFunctions.Constant" c:target="#{getObject('shibboleth.oidc.issuer')}" /> </property> </bean>
Wire the bean as the custom JWT authentication audience validator in
conf/oidc.properties
:idp.oauth2.jwtAuth.audienceValidator = StrictAudienceValidator
Per-RP and -Profile basis
Define the following bean in the
conf/relying-party.xml
:<bean id="CustomJWTClaimsValidator" class="net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator"> <property name="claimValidators"> <util:list id="CustomClaimsValidators" value-type="net.shibboleth.oidc.jwt.claims.ClaimsValidator"> <ref bean="ExpiryClaimsValidator" /> <ref bean="NotBeforeClaimsValidator" /> <ref bean="IssuedAtClaimsValidator" /> <ref bean="IssuerClaimsValidator" /> <ref bean="SubjectClaimsValidator" /> <bean class="net.shibboleth.oidc.security.jwt.claims.impl.AudienceClaimsValidator" p:extraAudienceValidation="true"> <property name="audienceLookupStrategy"> <bean parent="shibboleth.BiFunctions.Constant" c:target="#{getObject('shibboleth.oidc.issuer')}" /> </property> </bean> <ref bean="JWTIdentifierClaimsValidator" /> </util:list> </property> </bean>
Wire the bean to the desired profiles (possibly to specific RPs via shibboleth.RelyingPartyOverrides) in the following way. The applicable profile beans are OIDC.SSO, OAUTH2.PAR, OAUTH2.Token and OAUTH2.Introspection) together with their -MDDriven variants).
... <bean parent="OAUTH2.Token.MDDriven" p:claimsValidator-ref="CustomJWTClaimsValidator" /> <bean parent="OAUTH2.Introspection.MDDriven" p:claimsValidator-ref="CustomJWTClaimsValidator" /> ...