Skip to content

JWK endpoint as filter #31

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

Closed

Conversation

jbellmann
Copy link
Contributor

@jbellmann jbellmann commented Apr 18, 2020

Fixes #2

Provides an JWKSet endpoint implemented as filter with basic tests.

@anzap anzap mentioned this pull request Apr 20, 2020
@jgrandja
Copy link
Collaborator

jgrandja commented Apr 21, 2020

@jbellmann Thanks for the PR! FYI, when you are interested on working on a specific issue please reach out to us on the issue first so that other users can see that the issue is taken.

@ovidiupopa91 reached out in this comment requesting to work on this. All good either way, I just wanted to make you aware of the process. I will review this PR shortly. Thanks.

@jgrandja jgrandja mentioned this pull request Apr 21, 2020
@RequiredArgsConstructor
public class JWKSetEndpoint extends OncePerRequestFilter {

static final String WELL_KNOWN_JWK_URIS = "/.well-known/jwk_uris";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be better if the uri was configurable and the constant especially accessbile?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback @Captain-P-Goldfish. The goal is to start with the minimal amount of code to get things working. We will add custom configurations as we build things out.

Comment on lines 54 to 56
try (Writer writer = response.getWriter()) {
writer.write(jwkSet.toPublicJWKSet().toJSONObject().toJSONString());
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about error handling?
NullPointerExceptions would be pretty unpleasant

Copy link
Collaborator

@jgrandja jgrandja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @jbellmann. Please see my review comments.


import com.nimbusds.jose.jwk.JWKSet;

import lombok.RequiredArgsConstructor;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove lombok as Spring Security does not use it.

public class JWKSetEndpoint extends OncePerRequestFilter {

static final String WELL_KNOWN_JWK_URIS = "/.well-known/jwk_uris";
private final JWKSet jwkSet;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JWKSet should be provided with a default set of key(s). Please see main issue comment:

The keys that are used can be generated at startup or be constants

build.gradle Outdated
@@ -1,22 +1,38 @@
plugins {
id 'java'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move the code into the minimal sample and remove this gradle build.

@RequiredArgsConstructor
public class JWKSetEndpoint extends OncePerRequestFilter {

static final String WELL_KNOWN_JWK_URIS = "/.well-known/jwk_uris";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback @Captain-P-Goldfish. The goal is to start with the minimal amount of code to get things working. We will add custom configurations as we build things out.

}

@Test
void testIfRequestMatches() throws Exception {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should setup for keys to be returned here

@jgrandja jgrandja self-assigned this Apr 27, 2020
@jbellmann jbellmann requested a review from jgrandja April 28, 2020 11:17
}

protected boolean ifRequestMatches(HttpServletRequest request) {
return request.getRequestURI().endsWith(WELL_KNOWN_JWK_URIS);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also match /stuff/.well-known/jwk_uris, right? Is that acceptable or should it be an exact match?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use RequestMatcher, specifically AntPathRequestMatcher

Copy link
Collaborator

@jgrandja jgrandja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the updates @jbellmann. Please see my review comments.

.gitignore Outdated
@@ -12,6 +12,7 @@ build/
.settings
.springBeans
.sts4-cache
bin/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rebase on master as bin has been added in a recent commit.

@Bean
FilterRegistrationBean<JWKSetEndpoint> registerJWKSetEndpoint() throws JOSEException {
FilterRegistrationBean<JWKSetEndpoint> fb = new FilterRegistrationBean<>();
fb.setFilter(new JWKSetEndpoint(generateJwkSet()));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's register JWKSetEndpoint with the Spring Security filter chain via HttpSecurity.addFilter...

import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;

@Configuration
public class Config {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to SecurityConfig and extend WebSecurityConfigurerAdapter


import com.nimbusds.jose.jwk.JWKSet;

public class JWKSetEndpoint extends OncePerRequestFilter {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename to JwkSetEndpointFilter

}

protected boolean ifRequestMatches(HttpServletRequest request) {
return request.getRequestURI().endsWith(WELL_KNOWN_JWK_URIS);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use RequestMatcher, specifically AntPathRequestMatcher

@jbellmann jbellmann requested a review from jgrandja May 3, 2020 23:23
Copy link
Collaborator

@jgrandja jgrandja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates @jbellmann. Please see review comments.

Before you push the updates, please rebase on master and squash to 1 commit. Our git workflow is rebase instead of merge. Thanks.

import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;

@Configuration
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with @EnableWebSecurity

}

protected JWKSet generateJwkSet() throws JOSEException {
JWK jwk = new RSAKeyGenerator(2048).keyID("minimal-ASA").keyUse(KeyUse.ENCRYPTION).generate();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to KeyUse.SIGNATURE

public class FakeController {

@RequestMapping("/fake")
public String hello() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this declaration in the test class instead


@Test
void testRequestMatcher() {
assertTrue(this.filter.ifRequestMatches(new MockHttpServletRequest(GET.name(), WELL_KNOWN_JWK_URIS)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change all the assertion checks to use AssertJ instead as that is the primary test lib we use in Spring Security.

void testRequestMatcher() {
assertTrue(this.filter.ifRequestMatches(new MockHttpServletRequest(GET.name(), WELL_KNOWN_JWK_URIS)));

assertFalse(this.filter.ifRequestMatches(new MockHttpServletRequest(POST.name(), WELL_KNOWN_JWK_URIS)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should test the doFilter() method directly. Please change the protected methods to private in JwkSetEndpointFilter. See OAuth2AuthorizationCodeGrantFilterTests (spring-security-oauth2-client) on how we test Filter's.

@jbellmann jbellmann force-pushed the gh_2-JWK-Endpoint branch from 557b3c3 to 8a7629c Compare May 10, 2020 20:27
@jbellmann jbellmann force-pushed the gh_2-JWK-Endpoint branch from 8a7629c to 01f3ee1 Compare May 10, 2020 20:54
@jbellmann jbellmann requested a review from jgrandja May 10, 2020 20:58
@jgrandja jgrandja added status: duplicate A duplicate of another issue type: enhancement A general enhancement labels May 18, 2020
@jgrandja jgrandja added this to the 0.0.1 milestone May 18, 2020
jgrandja added a commit that referenced this pull request May 18, 2020
@jgrandja
Copy link
Collaborator

Thanks for all the updates @jbellmann ! FYI, I added a polish commit to get this merged. This is now in master.

@jgrandja jgrandja closed this May 18, 2020
doba16 pushed a commit to doba16/spring-authorization-server that referenced this pull request Apr 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add JWK Set Endpoint
4 participants