|
32 | 32 | import org.forgerock.util.Reject;
|
33 | 33 |
|
34 | 34 | import java.util.List;
|
| 35 | +import java.util.regex.Matcher; |
| 36 | +import java.util.regex.Pattern; |
35 | 37 | import java.util.Set;
|
36 | 38 |
|
37 | 39 | import static org.forgerock.openam.authentication.modules.oidc.OpenIdConnectConfig.*;
|
@@ -68,7 +70,7 @@ public JwtClaimsSet validateJwt(String jwtValue) throws AuthLoginException {
|
68 | 70 | final SignedJwt signedJwt = getSignedJwt(jwtValue);
|
69 | 71 | JwtClaimsSet jwtClaimSet = signedJwt.getClaimsSet();
|
70 | 72 | final String jwtClaimSetIssuer = jwtClaimSet.getIssuer();
|
71 |
| - if (!config.getConfiguredIssuer().equals(jwtClaimSetIssuer)) { |
| 73 | + if (!config.getConfiguredIssuer().equals(jwtClaimSetIssuer) && !isJwtFromIssuerFormat(jwtClaimSet)) { |
72 | 74 | logger.error("The issuer configured for the module, " + config.getConfiguredIssuer() + ", and the " +
|
73 | 75 | "issuer found in the token, " + jwtClaimSetIssuer + ", do not match. This means that the token " +
|
74 | 76 | "authentication was directed at the wrong module, or the targeted module is mis-configured.");
|
@@ -136,6 +138,30 @@ public JwtClaimsSet validateJwt(String jwtValue) throws AuthLoginException {
|
136 | 138 | return jwtClaimSet;
|
137 | 139 | }
|
138 | 140 |
|
| 141 | + /** |
| 142 | + * Indicates whether the JWT token is issued by configured issuer, with parameterized substitution from the claims set. |
| 143 | + * Example: <tt>https://login.microsoftonline.com/{tid}/v2.0</tt> shall have <tt>{tid}</tt> replaced with the iss claim's value. |
| 144 | + * |
| 145 | + * @param jwtClaimSet The JWT claims. |
| 146 | + * @return Whether the JWT token is issued by the configured issuer. |
| 147 | + */ |
| 148 | + private boolean isJwtFromIssuerFormat(JwtClaimsSet jwtClaimSet) { |
| 149 | + /* Since the OpenID Connect Core says "The Issuer Identifier [...] MUST exactly match the value of the iss (issuer) Claim.", |
| 150 | + allow only parameterized matching. */ |
| 151 | + final Matcher m = Pattern.compile("\\{[^\\}]+\\}").matcher(config.getConfiguredIssuer()); |
| 152 | + final StringBuffer issuer = new StringBuffer(); |
| 153 | + while (m.find()) { |
| 154 | + final String group = m.group(); |
| 155 | + final String key = group.substring(1, group.length() - 1); |
| 156 | + final Object value = jwtClaimSet.getClaim(key); |
| 157 | + if (value != null) |
| 158 | + m.appendReplacement(issuer, value.toString()); |
| 159 | + } |
| 160 | + m.appendTail(issuer); |
| 161 | + |
| 162 | + return issuer.toString().equals(jwtClaimSet.getIssuer()); |
| 163 | + } |
| 164 | + |
139 | 165 | /**
|
140 | 166 | * Retrieve the actual JWT token from the encoded JWT token.
|
141 | 167 | *
|
|
0 commit comments