|
16 | 16 |
|
17 | 17 | package example;
|
18 | 18 |
|
| 19 | +import java.io.InputStream; |
| 20 | +import java.lang.annotation.Retention; |
| 21 | +import java.lang.annotation.RetentionPolicy; |
| 22 | +import java.util.Collection; |
| 23 | +import java.util.Map; |
| 24 | +import java.util.stream.Collectors; |
| 25 | +import java.util.stream.Stream; |
| 26 | + |
| 27 | +import com.fasterxml.jackson.databind.ObjectMapper; |
19 | 28 | import org.junit.jupiter.api.Test;
|
20 | 29 |
|
21 | 30 | import org.springframework.beans.factory.annotation.Autowired;
|
22 | 31 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
23 | 32 | import org.springframework.context.annotation.Import;
|
| 33 | +import org.springframework.core.io.DefaultResourceLoader; |
| 34 | +import org.springframework.core.io.Resource; |
| 35 | +import org.springframework.core.io.ResourceLoader; |
| 36 | +import org.springframework.security.core.GrantedAuthority; |
24 | 37 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
| 38 | +import org.springframework.security.core.context.SecurityContext; |
| 39 | +import org.springframework.security.core.context.SecurityContextImpl; |
| 40 | +import org.springframework.security.oauth2.jwt.Jwt; |
| 41 | +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; |
| 42 | +import org.springframework.security.test.context.support.WithSecurityContext; |
| 43 | +import org.springframework.security.test.context.support.WithSecurityContextFactory; |
25 | 44 | import org.springframework.test.web.servlet.MockMvc;
|
26 | 45 |
|
27 | 46 | import static org.hamcrest.CoreMatchers.is;
|
@@ -102,4 +121,62 @@ void messageCanBeCreatedWithScopeMessageWriteAuthority() throws Exception {
|
102 | 121 | // @formatter:on
|
103 | 122 | }
|
104 | 123 |
|
| 124 | + @Test |
| 125 | + @WithMockJwt("classpath:validjwt.json") |
| 126 | + void indexGreetsAuthenticatedUserWithMockJwt() throws Exception { |
| 127 | + this.mockMvc.perform(get("/")).andExpect(content().string(is("Hello, ch4mpy!"))); |
| 128 | + } |
| 129 | + |
| 130 | + @Test |
| 131 | + @WithMockJwt(value = "classpath:validjwt.json", authorities = "SCOPE_message:read") |
| 132 | + void messageCanBeReadWithScopeMessageReadAuthorityWithMockJwt() throws Exception { |
| 133 | + // @formatter:off |
| 134 | + this.mockMvc.perform(get("/message")).andExpect(content().string(is("secret message"))); |
| 135 | + // @formatter:on |
| 136 | + } |
| 137 | + |
| 138 | + @Test |
| 139 | + @WithMockJwt(value = "classpath:validjwt.json", authorities = "SCOPE_message:read") |
| 140 | + void messageCanNotBeCreatedWithScopeMessageReadAuthorityWithMockJwt() throws Exception { |
| 141 | + // @formatter:off |
| 142 | + this.mockMvc.perform(post("/message") |
| 143 | + .content("Hello message")) |
| 144 | + .andExpect(status().isForbidden()); |
| 145 | + // @formatter:on |
| 146 | + } |
| 147 | + |
| 148 | + @Retention(RetentionPolicy.RUNTIME) |
| 149 | + @WithSecurityContext(factory = JwtFactory.class) |
| 150 | + @interface WithMockJwt { |
| 151 | + |
| 152 | + String value(); |
| 153 | + |
| 154 | + String[] authorities() default {}; |
| 155 | + |
| 156 | + } |
| 157 | + |
| 158 | + static class JwtFactory implements WithSecurityContextFactory<WithMockJwt> { |
| 159 | + |
| 160 | + private final ResourceLoader resourceLoader = new DefaultResourceLoader(); |
| 161 | + |
| 162 | + private final ObjectMapper mapper = new ObjectMapper(); |
| 163 | + |
| 164 | + @Override |
| 165 | + public SecurityContext createSecurityContext(WithMockJwt annotation) { |
| 166 | + Resource jwtString = this.resourceLoader.getResource(annotation.value()); |
| 167 | + try (InputStream in = jwtString.getInputStream()) { |
| 168 | + Map<String, Object> claims = (Map<String, Object>) this.mapper.readValue(in, Map.class); |
| 169 | + Jwt jwt = Jwt.withTokenValue("token").header("alg", "none").claims((c) -> c.putAll(claims)).build(); |
| 170 | + Collection<GrantedAuthority> authorities = Stream.of(annotation.authorities()) |
| 171 | + .map(SimpleGrantedAuthority::new) |
| 172 | + .collect(Collectors.toList()); |
| 173 | + return new SecurityContextImpl(new JwtAuthenticationToken(jwt, authorities)); |
| 174 | + } |
| 175 | + catch (Exception ex) { |
| 176 | + throw new RuntimeException(ex); |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + } |
| 181 | + |
105 | 182 | }
|
0 commit comments