Skip to content

Commit cb69344

Browse files
Downgrade springboot version - build kotlin-service
1 parent ab591a0 commit cb69344

File tree

12 files changed

+245
-87
lines changed

12 files changed

+245
-87
lines changed

authentication-service/src/main/java/com/microservice/authentication/AuthenticationServiceApplication.java

Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
package com.microservice.authentication;
22

3+
import java.nio.charset.StandardCharsets;
34
import java.security.KeyPair;
45
import java.security.interfaces.RSAPublicKey;
5-
import java.util.Arrays;
6+
import java.time.Instant;
67
import java.util.Collections;
8+
import java.util.Date;
79
import java.util.HashMap;
810
import java.util.Optional;
911
import java.util.Properties;
1012
import java.util.UUID;
1113
import java.util.concurrent.Executors;
1214

15+
import javax.crypto.spec.SecretKeySpec;
16+
17+
import com.microservice.authentication.autoconfigure.AuthenticationProperties;
1318
import com.microservice.authentication.common.model.Authentication;
1419
import com.microservice.authentication.common.model.Authority;
1520
import com.microservice.authentication.common.repository.AuthenticationCommonRepository;
1621
import com.microservice.authentication.config.SpringSecurityConfiguration;
1722
import com.microservice.web.common.util.constants.DefaultUsers;
23+
import com.nimbusds.jose.JOSEException;
24+
import com.nimbusds.jose.JWSAlgorithm;
25+
import com.nimbusds.jose.JWSHeader;
26+
import com.nimbusds.jose.crypto.MACSigner;
1827
import com.nimbusds.jose.jwk.JWK;
1928
import com.nimbusds.jose.jwk.JWKSet;
29+
import com.nimbusds.jose.jwk.OctetSequenceKey;
2030
import com.nimbusds.jose.jwk.RSAKey;
2131
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
2232
import com.nimbusds.jose.jwk.source.JWKSource;
2333
import com.nimbusds.jose.proc.SecurityContext;
24-
import jakarta.servlet.http.Cookie;
34+
import com.nimbusds.jwt.JWTClaimsSet;
35+
import com.nimbusds.jwt.SignedJWT;
2536
import lombok.AllArgsConstructor;
2637
import lombok.extern.slf4j.Slf4j;
38+
import net.minidev.json.JSONObject;
39+
import org.apache.commons.lang.StringUtils;
2740

2841
import org.springframework.beans.BeansException;
2942
import org.springframework.boot.CommandLineRunner;
@@ -39,6 +52,7 @@
3952
import org.springframework.context.ApplicationContext;
4053
import org.springframework.context.ApplicationContextAware;
4154
import org.springframework.context.annotation.Bean;
55+
import org.springframework.context.annotation.Primary;
4256
import org.springframework.core.task.AsyncTaskExecutor;
4357
import org.springframework.core.task.support.TaskExecutorAdapter;
4458
import org.springframework.data.mongodb.core.MongoTemplate;
@@ -49,10 +63,11 @@
4963
import org.springframework.security.crypto.password.PasswordEncoder;
5064
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
5165
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
66+
import org.springframework.security.oauth2.jwt.Jwt;
67+
import org.springframework.security.oauth2.jwt.JwtDecoder;
5268
import org.springframework.security.oauth2.jwt.JwtEncoder;
69+
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
5370
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
54-
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
55-
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
5671
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
5772
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
5873
import org.springframework.session.MapSessionRepository;
@@ -76,23 +91,6 @@ public static void main(String[] args) {
7691
SpringApplication.run(AuthenticationServiceApplication.class, args);
7792
}
7893

79-
@Bean
80-
BearerTokenResolver bearerTokenResolver() {
81-
DefaultBearerTokenResolver defaultBearerTokenResolver = new DefaultBearerTokenResolver();
82-
return request -> {
83-
var cookies = request.getCookies();
84-
log.debug("Getting Bearer Token resolver: cookies: {}", cookies);
85-
if (cookies == null) {
86-
cookies = new Cookie[] {};
87-
}
88-
return Arrays
89-
.stream(cookies)
90-
.filter(c -> c.getName().equals("SESSIONID"))
91-
.map(Cookie::getValue)
92-
.findFirst().orElseGet(() -> defaultBearerTokenResolver.resolve(request));
93-
};
94-
}
95-
9694
@Bean
9795
@ConditionalOnMissingBean
9896
public SessionRepository defaultSessionRepository() {
@@ -114,16 +112,85 @@ public PasswordEncoder encoder() {
114112
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
115113
}
116114

115+
@ConditionalOnProperty(prefix = "com.microservice.authentication.jwt", name = "key-value")
116+
@Primary
117+
@ConditionalOnMissingBean
118+
@Bean
119+
public JwtDecoder jwtDecoder(AuthenticationProperties properties) throws JOSEException {
120+
AuthenticationProperties.Jwt jwt = properties.getJwt();
121+
byte[] secret = jwt.getKeyValue().getBytes(StandardCharsets.UTF_8);
122+
123+
MACSigner macSigner = new MACSigner(secret);
124+
return NimbusJwtDecoder.withSecretKey(macSigner.getSecretKey()).build();
125+
}
126+
117127
@Bean
118128
@ConditionalOnMissingBean
119-
JwtEncoder jwtEncoder() {
120-
KeyPair keyPair = applicationContext.getBean(KeyPair.class);
129+
JwtEncoder jwtEncoder(AuthenticationProperties properties) {
130+
AuthenticationProperties.Jwt jwt = properties.getJwt();
131+
String keyValue = jwt.getKeyValue();
132+
if (StringUtils.isNotBlank(keyValue)) {
133+
return parameters -> {
134+
byte[] secret = jwt.getKeyValue().getBytes(StandardCharsets.UTF_8);
135+
SecretKeySpec secretKeySpec = new SecretKeySpec(secret, "HMACSHA256");
136+
137+
try {
138+
MACSigner signer = new MACSigner(secretKeySpec);
139+
140+
JWTClaimsSet.Builder claimsSetBuilder = new JWTClaimsSet.Builder();
141+
parameters.getClaims().getClaims().forEach((key, value) ->
142+
claimsSetBuilder.claim(key, value instanceof Instant ? Date.from((Instant) value) : value)
143+
);
144+
JWTClaimsSet claimsSet = claimsSetBuilder.build();
121145

122-
JWK jwk = new RSAKey.Builder((RSAPublicKey) keyPair.getPublic())
123-
.privateKey(keyPair.getPrivate())
146+
JSONObject jsonObject = new JSONObject();
147+
jsonObject.put("alg", JWSAlgorithm.HS256.getName());
148+
jsonObject.put("typ", "JWT");
149+
150+
JWSHeader header = JWSHeader.parse(jsonObject);
151+
SignedJWT signedJWT = new SignedJWT(header, claimsSet);
152+
signedJWT.sign(signer);
153+
154+
return Jwt.withTokenValue(signedJWT.serialize())
155+
.header("alg", header.getAlgorithm().getName())
156+
.header("typ", "JWT")
157+
.subject(claimsSet.getSubject())
158+
.issuer(claimsSet.getIssuer())
159+
.claims(claims -> claims.putAll(claimsSet.getClaims()))
160+
.issuedAt(claimsSet.getIssueTime().toInstant())
161+
.expiresAt(claimsSet.getExpirationTime().toInstant())
162+
.build();
163+
}
164+
catch (Exception e) {
165+
throw new IllegalStateException("Error while signing the JWT", e);
166+
}
167+
};
168+
} else {
169+
KeyPair keyPair = applicationContext.getBean(KeyPair.class);
170+
171+
JWK jwk = new RSAKey.Builder((RSAPublicKey) keyPair.getPublic())
172+
.privateKey(keyPair.getPrivate())
173+
.build();
174+
JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
175+
return new NimbusJwtEncoder(jwks);
176+
}
177+
}
178+
179+
@ConditionalOnProperty(prefix = "com.microservice.authentication.jwt", name = "key-value")
180+
@Bean
181+
@ConditionalOnMissingBean
182+
public JWKSource<SecurityContext> jwkSource(AuthenticationProperties properties) {
183+
AuthenticationProperties.Jwt jwt = properties.getJwt();
184+
byte[] secret = jwt.getKeyValue().getBytes(StandardCharsets.UTF_8);
185+
186+
OctetSequenceKey octetKey = new OctetSequenceKey.Builder(secret)
187+
.keyID(UUID.randomUUID().toString())
188+
.algorithm(JWSAlgorithm.HS256)
124189
.build();
125-
JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
126-
return new NimbusJwtEncoder(jwks);
190+
191+
JWKSet jwkSet = new JWKSet(octetKey);
192+
193+
return (jwkSelector, context) -> jwkSelector.select(jwkSet);
127194
}
128195

129196
@Bean

authentication-service/src/test/java/com/microservice/authentication/AuthenticationServiceApplicationIntegrationTest.java

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
"logging.level.com.microservice=debug",
9494
"spring.cloud.consul.config.enabled=false",
9595
"de.flapdoodle.mongodb.embedded.version=5.0.5",
96-
"logging.level.org.springframework.security=trace"})
96+
"logging.level.org.springframework.security=trace"})
9797
@ContextConfiguration(initializers = AuthenticationServiceApplicationIntegrationTest.GenerateKeyPairInitializer.class,
9898
classes = {AuthenticationServiceApplicationIntegrationTest.MockConfiguration.class})
9999
@AutoConfigureMockMvc
@@ -206,14 +206,10 @@ public void shouldUserBeAuthenticatedWhenCallingApi() throws Exception {
206206
LinkedMultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
207207
formData.add("username", "master@gmail.com");
208208
formData.add("password", "password123");
209-
var response = mockMvc.perform(post("/login")
210-
.params(formData)
211-
.with(csrf()))
212-
.andExpect(status().is3xxRedirection())
213-
.andReturn()
214-
.getResponse();
215-
216-
assertThat(response.getCookies()).isNotEmpty();
209+
mockMvc.perform(post("/login")
210+
.params(formData)
211+
.with(csrf()))
212+
.andExpect(status().is3xxRedirection());
217213
}
218214

219215
@Test
@@ -237,7 +233,7 @@ public void shouldWorkLogoutUrl() throws Exception {
237233
@DisplayName("Test - When Calling GET - /api/authenticatedUser without jwt should return 401 - Unauthorized")
238234
public void shouldReturnUnauthorizedWhenCallingApiWithoutAuthorizationHeader() throws Exception {
239235
mockMvc.perform(get("/api/authenticatedUser")
240-
.with(csrf()))
236+
.with(csrf()))
241237
.andExpect(status().is4xxClientError());
242238
}
243239

@@ -249,8 +245,8 @@ public void shouldReturnUnauthorizedWhenCallingAuthenticateApiWithDefaultSystemU
249245
formData.add("password", "noPassword");
250246

251247
mockMvc.perform(post("/api/authenticate")
252-
.params(formData)
253-
.with(csrf()))
248+
.params(formData)
249+
.with(csrf()))
254250
.andExpect(status().is4xxClientError())
255251
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
256252
.andExpect(header().doesNotExist(HttpHeaders.AUTHORIZATION))
@@ -278,7 +274,7 @@ public void shouldReturnOkWithToken() throws Exception {
278274
String authorizationHeader = "Bearer " + signedJWT.serialize();
279275

280276
mockMvc.perform(get("/")
281-
.header(HttpHeaders.AUTHORIZATION, authorizationHeader))
277+
.header(HttpHeaders.AUTHORIZATION, authorizationHeader))
282278
.andExpect(status().is2xxSuccessful());
283279
}
284280

@@ -289,15 +285,15 @@ public void shouldWorkLoginWithoutCsrf() throws Exception {
289285
formData.add("password", "password123");
290286

291287
String content = mockMvc.perform(get("/api/csrf"))
292-
.andExpect(status().is2xxSuccessful())
293-
.andDo(print())
294-
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
295-
.andExpect(jsonPath("$.headerName", is(notNullValue())))
296-
.andExpect(jsonPath("$.parameterName", is(notNullValue())))
297-
.andExpect(jsonPath("$.token", is(notNullValue())))
298-
.andReturn()
299-
.getResponse()
300-
.getContentAsString();
288+
.andExpect(status().is2xxSuccessful())
289+
.andDo(print())
290+
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
291+
.andExpect(jsonPath("$.headerName", is(notNullValue())))
292+
.andExpect(jsonPath("$.parameterName", is(notNullValue())))
293+
.andExpect(jsonPath("$.token", is(notNullValue())))
294+
.andReturn()
295+
.getResponse()
296+
.getContentAsString();
301297

302298
assertThat(content).isNotEmpty();
303299

@@ -308,7 +304,7 @@ public void shouldWorkLoginWithoutCsrf() throws Exception {
308304
mockMvc.perform(post("/api/authenticate")
309305
.params(formData)
310306
.with(csrf()))
311-
//.header(csrfToken.getHeaderName(), csrfToken.getToken()))
307+
//.header(csrfToken.getHeaderName(), csrfToken.getToken()))
312308
.andExpect(status().isOk())
313309
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
314310
.andExpect(header().exists(HttpHeaders.AUTHORIZATION))
@@ -342,16 +338,6 @@ public void shouldWorkLoginAndLogout() throws Exception {
342338
assertThat(accessToken).isNotEmpty();
343339
assertThat(accessToken.get("tokenValue")).isNotNull();
344340

345-
mockMvc.perform(get("/api/authenticatedUser")
346-
.with(csrf())
347-
.cookie(response.getCookies())
348-
.header("sessionId", response.getHeader("sessionId")))
349-
.andDo(print())
350-
.andExpect(status().isOk())
351-
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
352-
.andExpect(header().exists(HttpHeaders.AUTHORIZATION))
353-
.andExpect(jsonPath("$.tokenValue", is(notNullValue())));
354-
355341
String authorization = "Bearer " + accessToken.get("tokenValue").toString();
356342
mockMvc.perform(get("/api/authenticatedUser")
357343
.with(csrf())

authentication-service/src/test/resources/application.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@ spring:
3939
google:
4040
client-id: test
4141
client-secret: test
42-
resourceserver:
43-
jwt:
44-
jwk-set-uri: http://localhost:${server.port}/.well-known/jwks.json
45-
opaquetoken:
46-
client-id:
4742
data:
4843
redis:
4944
repositories:

0 commit comments

Comments
 (0)