Update to Use JwtEncoder

Closes gh-44
This commit is contained in:
Josh Cummings 2021-09-27 16:43:29 -06:00
parent 52cc331d9c
commit c4eaac0423
2 changed files with 31 additions and 30 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2020-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +16,16 @@
package example; package example;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -29,7 +37,9 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint; import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler; import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@ -45,6 +55,9 @@ public class RestConfig extends WebSecurityConfigurerAdapter {
@Value("${jwt.public.key}") @Value("${jwt.public.key}")
RSAPublicKey key; RSAPublicKey key;
@Value("${jwt.private.key}")
RSAPrivateKey priv;
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
// @formatter:off // @formatter:off
@ -77,4 +90,10 @@ public class RestConfig extends WebSecurityConfigurerAdapter {
return NimbusJwtDecoder.withPublicKey(this.key).build(); return NimbusJwtDecoder.withPublicKey(this.key).build();
} }
@Bean
JwtEncoder jwtEncoder() {
JWK jwk = new RSAKey.Builder(this.key).privateKey(this.priv).build();
JWKSource<SecurityContext> jwks = new ImmutableJWKSet<>(new JWKSet(jwk));
return new NimbusJwtEncoder(jwks);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2020 the original author or authors. * Copyright 2020-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,20 +16,15 @@
package example.web; package example.web;
import java.security.interfaces.RSAPrivateKey;
import java.time.Instant; import java.time.Instant;
import java.util.Date;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.nimbusds.jose.JWSAlgorithm; import org.springframework.beans.factory.annotation.Autowired;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -41,8 +36,8 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class TokenController { public class TokenController {
@Value("${jwt.private.key}") @Autowired
RSAPrivateKey key; JwtEncoder encoder;
@PostMapping("/token") @PostMapping("/token")
public String token(Authentication authentication) { public String token(Authentication authentication) {
@ -52,27 +47,14 @@ public class TokenController {
String scope = authentication.getAuthorities().stream() String scope = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority) .map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(" ")); .collect(Collectors.joining(" "));
JWTClaimsSet claims = new JWTClaimsSet.Builder() JwtClaimsSet claims = JwtClaimsSet.builder()
.issuer("self") .issuer("self")
.issueTime(new Date(now.toEpochMilli())) .issuedAt(now)
.expirationTime(new Date(now.plusSeconds(expiry).toEpochMilli())) .expiresAt(now.plusSeconds(expiry))
.subject(authentication.getName()) .subject(authentication.getName())
.claim("scope", scope) .claim("scope", scope)
.build(); .build();
// @formatter:on // @formatter:on
JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build(); return this.encoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
SignedJWT jwt = new SignedJWT(header, claims);
return sign(jwt).serialize();
}
SignedJWT sign(SignedJWT jwt) {
try {
jwt.sign(new RSASSASigner(this.key));
return jwt;
}
catch (Exception ex) {
throw new IllegalArgumentException(ex);
} }
} }
}