Add WithMockJwt Sample tests

Closes gh-318
This commit is contained in:
Josh Cummings
2024-08-28 10:38:43 -06:00
parent 3489338049
commit 277055548f
2 changed files with 78 additions and 0 deletions

View File

@@ -16,12 +16,31 @@
package example;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.test.context.support.WithSecurityContext;
import org.springframework.security.test.context.support.WithSecurityContextFactory;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.CoreMatchers.is;
@@ -102,4 +121,62 @@ public class OAuth2ResourceServerControllerTests {
// @formatter:on
}
@Test
@WithMockJwt("classpath:validjwt.json")
void indexGreetsAuthenticatedUserWithMockJwt() throws Exception {
this.mockMvc.perform(get("/")).andExpect(content().string(is("Hello, ch4mpy!")));
}
@Test
@WithMockJwt(value = "classpath:validjwt.json", authorities = "SCOPE_message:read")
void messageCanBeReadWithScopeMessageReadAuthorityWithMockJwt() throws Exception {
// @formatter:off
this.mockMvc.perform(get("/message")).andExpect(content().string(is("secret message")));
// @formatter:on
}
@Test
@WithMockJwt(value = "classpath:validjwt.json", authorities = "SCOPE_message:read")
void messageCanNotBeCreatedWithScopeMessageReadAuthorityWithMockJwt() throws Exception {
// @formatter:off
this.mockMvc.perform(post("/message")
.content("Hello message"))
.andExpect(status().isForbidden());
// @formatter:on
}
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = JwtFactory.class)
@interface WithMockJwt {
String value();
String[] authorities() default {};
}
static class JwtFactory implements WithSecurityContextFactory<WithMockJwt> {
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
private final ObjectMapper mapper = new ObjectMapper();
@Override
public SecurityContext createSecurityContext(WithMockJwt annotation) {
Resource jwtString = this.resourceLoader.getResource(annotation.value());
try (InputStream in = jwtString.getInputStream()) {
Map<String, Object> claims = (Map<String, Object>) this.mapper.readValue(in, Map.class);
Jwt jwt = Jwt.withTokenValue("token").header("alg", "none").claims((c) -> c.putAll(claims)).build();
Collection<GrantedAuthority> authorities = Stream.of(annotation.authorities())
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
return new SecurityContextImpl(new JwtAuthenticationToken(jwt, authorities));
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
}