11package com .microservice .authentication ;
22
3+ import java .nio .charset .StandardCharsets ;
34import java .security .KeyPair ;
45import java .security .interfaces .RSAPublicKey ;
5- import java .util . Arrays ;
6+ import java .time . Instant ;
67import java .util .Collections ;
8+ import java .util .Date ;
79import java .util .HashMap ;
810import java .util .Optional ;
911import java .util .Properties ;
1012import java .util .UUID ;
1113import java .util .concurrent .Executors ;
1214
15+ import javax .crypto .spec .SecretKeySpec ;
16+
17+ import com .microservice .authentication .autoconfigure .AuthenticationProperties ;
1318import com .microservice .authentication .common .model .Authentication ;
1419import com .microservice .authentication .common .model .Authority ;
1520import com .microservice .authentication .common .repository .AuthenticationCommonRepository ;
1621import com .microservice .authentication .config .SpringSecurityConfiguration ;
1722import 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 ;
1827import com .nimbusds .jose .jwk .JWK ;
1928import com .nimbusds .jose .jwk .JWKSet ;
29+ import com .nimbusds .jose .jwk .OctetSequenceKey ;
2030import com .nimbusds .jose .jwk .RSAKey ;
2131import com .nimbusds .jose .jwk .source .ImmutableJWKSet ;
2232import com .nimbusds .jose .jwk .source .JWKSource ;
2333import com .nimbusds .jose .proc .SecurityContext ;
24- import jakarta .servlet .http .Cookie ;
34+ import com .nimbusds .jwt .JWTClaimsSet ;
35+ import com .nimbusds .jwt .SignedJWT ;
2536import lombok .AllArgsConstructor ;
2637import lombok .extern .slf4j .Slf4j ;
38+ import net .minidev .json .JSONObject ;
39+ import org .apache .commons .lang .StringUtils ;
2740
2841import org .springframework .beans .BeansException ;
2942import org .springframework .boot .CommandLineRunner ;
3952import org .springframework .context .ApplicationContext ;
4053import org .springframework .context .ApplicationContextAware ;
4154import org .springframework .context .annotation .Bean ;
55+ import org .springframework .context .annotation .Primary ;
4256import org .springframework .core .task .AsyncTaskExecutor ;
4357import org .springframework .core .task .support .TaskExecutorAdapter ;
4458import org .springframework .data .mongodb .core .MongoTemplate ;
4963import org .springframework .security .crypto .password .PasswordEncoder ;
5064import org .springframework .security .oauth2 .client .authentication .OAuth2AuthenticationToken ;
5165import org .springframework .security .oauth2 .core .oidc .user .DefaultOidcUser ;
66+ import org .springframework .security .oauth2 .jwt .Jwt ;
67+ import org .springframework .security .oauth2 .jwt .JwtDecoder ;
5268import org .springframework .security .oauth2 .jwt .JwtEncoder ;
69+ import org .springframework .security .oauth2 .jwt .NimbusJwtDecoder ;
5370import 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 ;
5671import org .springframework .security .web .authentication .logout .LogoutSuccessHandler ;
5772import org .springframework .security .web .authentication .logout .SimpleUrlLogoutSuccessHandler ;
5873import 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
0 commit comments