-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Allow for customization of IssuerResolver #9005
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aac9194
f8a3663
3fdb9c2
86c51b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,7 +65,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat | |
|
||
private final AuthenticationManagerResolver<String> issuerAuthenticationManagerResolver; | ||
|
||
private final Converter<HttpServletRequest, String> issuerConverter = new JwtClaimIssuerConverter(); | ||
private Converter<HttpServletRequest, String> issuerConverter; | ||
|
||
/** | ||
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided | ||
|
@@ -78,13 +78,15 @@ public JwtIssuerAuthenticationManagerResolver(String... trustedIssuers) { | |
|
||
/** | ||
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided | ||
* | ||
* parameters | ||
* @param trustedIssuers a list of trusted issuers | ||
*/ | ||
public JwtIssuerAuthenticationManagerResolver(Collection<String> trustedIssuers) { | ||
Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty"); | ||
this.issuerAuthenticationManagerResolver = new TrustedIssuerJwtAuthenticationManagerResolver( | ||
Collections.unmodifiableCollection(trustedIssuers)::contains); | ||
this.issuerConverter = new JwtClaimIssuerConverter(); | ||
} | ||
|
||
/** | ||
|
@@ -110,8 +112,41 @@ public JwtIssuerAuthenticationManagerResolver(Collection<String> trustedIssuers) | |
*/ | ||
public JwtIssuerAuthenticationManagerResolver( | ||
AuthenticationManagerResolver<String> issuerAuthenticationManagerResolver) { | ||
this(issuerAuthenticationManagerResolver, new JwtClaimIssuerConverter()); | ||
} | ||
|
||
/** | ||
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided | ||
* parameters | ||
* | ||
* Note that the {@link AuthenticationManagerResolver} provided in this constructor | ||
* will need to verify that the issuer is trusted. This should be done via an | ||
* allowlist. | ||
* | ||
* One way to achieve this is with a {@link Map} where the keys are the known issuers: | ||
* <pre> | ||
* Map<String, AuthenticationManager> authenticationManagers = new HashMap<>(); | ||
* authenticationManagers.put("https://issuerOne.example.org", managerOne); | ||
* authenticationManagers.put("https://issuerTwo.example.org", managerTwo); | ||
* JwtAuthenticationManagerResolver resolver = new JwtAuthenticationManagerResolver | ||
* (authenticationManagers::get); | ||
* </pre> | ||
* | ||
* The keys in the {@link Map} are the allowed issuers. | ||
* @param issuerAuthenticationManagerResolver a strategy for resolving the | ||
* {@link AuthenticationManager} by the issuer | ||
* @param issuerConverter a custom converter to resolve the token A custom converter | ||
* allows to use a custom {@link BearerTokenResolver} | ||
* | ||
* @since 5.4 | ||
*/ | ||
public JwtIssuerAuthenticationManagerResolver( | ||
AuthenticationManagerResolver<String> issuerAuthenticationManagerResolver, | ||
Converter<HttpServletRequest, String> issuerConverter) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we are using a setter for the issuer converter, this constructor is unnecessary. |
||
Assert.notNull(issuerAuthenticationManagerResolver, "issuerAuthenticationManagerResolver cannot be null"); | ||
Assert.notNull(issuerConverter, "issuerConverter cannot be null"); | ||
this.issuerAuthenticationManagerResolver = issuerAuthenticationManagerResolver; | ||
this.issuerConverter = issuerConverter; | ||
} | ||
|
||
/** | ||
|
@@ -130,6 +165,10 @@ public AuthenticationManager resolve(HttpServletRequest request) { | |
return authenticationManager; | ||
} | ||
|
||
public void setIssuerConverter(Converter<HttpServletRequest, String> issuerConverter) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add JavaDoc, including a |
||
this.issuerConverter = issuerConverter; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I believe it would be a bit more consistent with the rest of Spring Security to call this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, out of curiosity, do you have a use case where you need the more generic contract of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jzheaux the problem is that you cannot set the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with you that adding a setter to One nice thing about using |
||
} | ||
|
||
private static class JwtClaimIssuerConverter implements Converter<HttpServletRequest, String> { | ||
|
||
private final BearerTokenResolver resolver = new DefaultBearerTokenResolver(); | ||
|
@@ -160,8 +199,16 @@ private static class TrustedIssuerJwtAuthenticationManagerResolver | |
|
||
private final Predicate<String> trustedIssuer; | ||
|
||
private final JwtAuthenticationConverter jwtAuthenticationConverter; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's leave these changes regarding |
||
|
||
TrustedIssuerJwtAuthenticationManagerResolver(Predicate<String> trustedIssuer) { | ||
this(trustedIssuer, null); | ||
} | ||
|
||
TrustedIssuerJwtAuthenticationManagerResolver(Predicate<String> trustedIssuer, | ||
JwtAuthenticationConverter jwtAuthenticationConverter) { | ||
this.trustedIssuer = trustedIssuer; | ||
this.jwtAuthenticationConverter = jwtAuthenticationConverter; | ||
} | ||
|
||
@Override | ||
|
@@ -171,7 +218,18 @@ public AuthenticationManager resolve(String issuer) { | |
(k) -> { | ||
this.logger.debug("Constructing AuthenticationManager"); | ||
JwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuer); | ||
return new JwtAuthenticationProvider(jwtDecoder)::authenticate; | ||
if (this.jwtAuthenticationConverter != null) { | ||
this.logger.debug(("Using custom JwtAuthenticationConverter")); | ||
final JwtAuthenticationProvider jwtAuthenticationProvider = new JwtAuthenticationProvider( | ||
jwtDecoder); | ||
jwtAuthenticationProvider | ||
.setJwtAuthenticationConverter(this.jwtAuthenticationConverter); | ||
return jwtAuthenticationProvider::authenticate; | ||
} | ||
else { | ||
this.logger.debug(("Using default JwtAuthenticationConverter")); | ||
return new JwtAuthenticationProvider(jwtDecoder)::authenticate; | ||
} | ||
}); | ||
this.logger.debug(LogMessage.format("Resolved AuthenticationManager for issuer '%s'", issuer)); | ||
return authenticationManager; | ||
|
Uh oh!
There was an error while loading. Please reload this page.