Code refactor.
This commit is contained in:
parent
2f8988ad4f
commit
a3e9b93382
@ -482,6 +482,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
### [](http://stackoverflow.com/questions/38557379/secure-and-stateless-jwt-implementation)
|
### [](http://stackoverflow.com/questions/38557379/secure-and-stateless-jwt-implementation)
|
||||||
|
|
||||||
|
http://by.jtl.xyz/2016/06/the-unspoken-vulnerability-of-jwts.html
|
||||||
|
|
||||||
|
http://nordicapis.com/how-to-control-user-identity-within-microservices/
|
||||||
|
|
||||||
http://stackoverflow.com/questions/3487991/why-does-oauth-v2-have-both-access-and-refresh-tokens/12885823
|
http://stackoverflow.com/questions/3487991/why-does-oauth-v2-have-both-access-and-refresh-tokens/12885823
|
||||||
|
|
||||||
https://tools.ietf.org/html/rfc6749#section-1.4
|
https://tools.ietf.org/html/rfc6749#section-1.4
|
||||||
@ -499,4 +503,6 @@ true statelessness and revocation are mutually exclusive
|
|||||||
|
|
||||||
https://www.sslvpn.online/are-breaches-of-jwt-based-servers-more-damaging/
|
https://www.sslvpn.online/are-breaches-of-jwt-based-servers-more-damaging/
|
||||||
|
|
||||||
http://nordicapis.com/how-to-control-user-identity-within-microservices/
|
http://nordicapis.com/how-to-control-user-identity-within-microservices/
|
||||||
|
|
||||||
|
https://tools.ietf.org/html/rfc6749
|
||||||
@ -5,8 +5,8 @@ import java.util.Collection;
|
|||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
import com.svlada.security.model.UnsafeJwtToken;
|
|
||||||
import com.svlada.security.model.UserContext;
|
import com.svlada.security.model.UserContext;
|
||||||
|
import com.svlada.security.model.token.RawAccessJwtToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link org.springframework.security.core.Authentication} implementation
|
* An {@link org.springframework.security.core.Authentication} implementation
|
||||||
@ -19,18 +19,18 @@ import com.svlada.security.model.UserContext;
|
|||||||
public class JwtAuthenticationToken extends AbstractAuthenticationToken {
|
public class JwtAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
private static final long serialVersionUID = 2877954820905567501L;
|
private static final long serialVersionUID = 2877954820905567501L;
|
||||||
|
|
||||||
private UnsafeJwtToken unsafeToken;
|
private RawAccessJwtToken rawAccessToken;
|
||||||
private UserContext userContext;
|
private UserContext userContext;
|
||||||
|
|
||||||
public JwtAuthenticationToken(UnsafeJwtToken unsafeToken) {
|
public JwtAuthenticationToken(RawAccessJwtToken unsafeToken) {
|
||||||
super(null);
|
super(null);
|
||||||
this.unsafeToken = unsafeToken;
|
this.rawAccessToken = unsafeToken;
|
||||||
this.setAuthenticated(false);
|
this.setAuthenticated(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JwtAuthenticationToken(UserContext userContext, Collection<? extends GrantedAuthority> authorities) {
|
public JwtAuthenticationToken(UserContext userContext, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
this.unsafeToken = null;
|
this.eraseCredentials();
|
||||||
this.userContext = userContext;
|
this.userContext = userContext;
|
||||||
super.setAuthenticated(true);
|
super.setAuthenticated(true);
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ public class JwtAuthenticationToken extends AbstractAuthenticationToken {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return unsafeToken;
|
return rawAccessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -57,6 +57,6 @@ public class JwtAuthenticationToken extends AbstractAuthenticationToken {
|
|||||||
@Override
|
@Override
|
||||||
public void eraseCredentials() {
|
public void eraseCredentials() {
|
||||||
super.eraseCredentials();
|
super.eraseCredentials();
|
||||||
this.unsafeToken = null;
|
this.rawAccessToken = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,9 +16,9 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.svlada.security.model.JwtToken;
|
|
||||||
import com.svlada.security.model.JwtTokenFactory;
|
|
||||||
import com.svlada.security.model.UserContext;
|
import com.svlada.security.model.UserContext;
|
||||||
|
import com.svlada.security.model.token.JwtToken;
|
||||||
|
import com.svlada.security.model.token.JwtTokenFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AjaxAwareAuthenticationSuccessHandler
|
* AjaxAwareAuthenticationSuccessHandler
|
||||||
@ -43,7 +43,7 @@ public class AjaxAwareAuthenticationSuccessHandler implements AuthenticationSucc
|
|||||||
Authentication authentication) throws IOException, ServletException {
|
Authentication authentication) throws IOException, ServletException {
|
||||||
UserContext userContext = (UserContext) authentication.getPrincipal();
|
UserContext userContext = (UserContext) authentication.getPrincipal();
|
||||||
|
|
||||||
JwtToken token = tokenFactory.createSafeToken(userContext);
|
JwtToken token = tokenFactory.createAccessJwtToken(userContext);
|
||||||
JwtToken refreshToken = tokenFactory.createRefreshToken(userContext);
|
JwtToken refreshToken = tokenFactory.createRefreshToken(userContext);
|
||||||
|
|
||||||
response.setStatus(HttpStatus.OK.value());
|
response.setStatus(HttpStatus.OK.value());
|
||||||
|
|||||||
@ -13,9 +13,9 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import com.svlada.security.auth.JwtAuthenticationToken;
|
import com.svlada.security.auth.JwtAuthenticationToken;
|
||||||
import com.svlada.security.config.JwtSettings;
|
import com.svlada.security.config.JwtSettings;
|
||||||
import com.svlada.security.model.JwtToken;
|
|
||||||
import com.svlada.security.model.UnsafeJwtToken;
|
|
||||||
import com.svlada.security.model.UserContext;
|
import com.svlada.security.model.UserContext;
|
||||||
|
import com.svlada.security.model.token.JwtToken;
|
||||||
|
import com.svlada.security.model.token.RawAccessJwtToken;
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jws;
|
import io.jsonwebtoken.Jws;
|
||||||
@ -40,13 +40,11 @@ public class JwtAuthenticationProvider implements AuthenticationProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
UnsafeJwtToken unsafeToken = (UnsafeJwtToken) authentication.getCredentials();
|
RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials();
|
||||||
|
|
||||||
Jws<Claims> jwsClaims = unsafeToken.parseClaims(jwtSettings.getTokenSigningKey());
|
Jws<Claims> jwsClaims = rawAccessToken.parseClaims(jwtSettings.getTokenSigningKey());
|
||||||
String subject = jwsClaims.getBody().getSubject();
|
String subject = jwsClaims.getBody().getSubject();
|
||||||
|
|
||||||
List<String> scopes = jwsClaims.getBody().get("scopes", List.class);
|
List<String> scopes = jwsClaims.getBody().get("scopes", List.class);
|
||||||
|
|
||||||
List<GrantedAuthority> authorities = scopes.stream()
|
List<GrantedAuthority> authorities = scopes.stream()
|
||||||
.map(authority -> new SimpleGrantedAuthority(authority))
|
.map(authority -> new SimpleGrantedAuthority(authority))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|||||||
@ -14,13 +14,11 @@ import org.springframework.security.core.context.SecurityContext;
|
|||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
|
||||||
|
|
||||||
import com.svlada.security.auth.JwtAuthenticationToken;
|
import com.svlada.security.auth.JwtAuthenticationToken;
|
||||||
import com.svlada.security.auth.jwt.extractor.TokenExtractor;
|
import com.svlada.security.auth.jwt.extractor.TokenExtractor;
|
||||||
import com.svlada.security.config.WebSecurityConfig;
|
import com.svlada.security.config.WebSecurityConfig;
|
||||||
import com.svlada.security.model.JwtTokenFactory;
|
import com.svlada.security.model.token.RawAccessJwtToken;
|
||||||
import com.svlada.security.model.UnsafeJwtToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs validation of provided JWT Token.
|
* Performs validation of provided JWT Token.
|
||||||
@ -32,24 +30,21 @@ import com.svlada.security.model.UnsafeJwtToken;
|
|||||||
public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
|
public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
|
||||||
private final AuthenticationFailureHandler failureHandler;
|
private final AuthenticationFailureHandler failureHandler;
|
||||||
private final TokenExtractor tokenExtractor;
|
private final TokenExtractor tokenExtractor;
|
||||||
private final JwtTokenFactory tokenFactory;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public JwtTokenAuthenticationProcessingFilter(AuthenticationFailureHandler failureHandler,
|
public JwtTokenAuthenticationProcessingFilter(AuthenticationFailureHandler failureHandler,
|
||||||
JwtTokenFactory tokenFactory,
|
|
||||||
TokenExtractor tokenExtractor,
|
TokenExtractor tokenExtractor,
|
||||||
String filterProcessingUrl) {
|
String filterProcessingUrl) {
|
||||||
super(filterProcessingUrl);
|
super(filterProcessingUrl);
|
||||||
this.failureHandler = failureHandler;
|
this.failureHandler = failureHandler;
|
||||||
this.tokenExtractor = tokenExtractor;
|
this.tokenExtractor = tokenExtractor;
|
||||||
this.tokenFactory = tokenFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws AuthenticationException, IOException, ServletException {
|
throws AuthenticationException, IOException, ServletException {
|
||||||
String tokenPayload = request.getHeader(WebSecurityConfig.JWT_TOKEN_HEADER_PARAM);
|
String tokenPayload = request.getHeader(WebSecurityConfig.JWT_TOKEN_HEADER_PARAM);
|
||||||
UnsafeJwtToken token = tokenFactory.createUnsafeToken(tokenExtractor.extract(tokenPayload));
|
RawAccessJwtToken token = new RawAccessJwtToken(tokenExtractor.extract(tokenPayload));
|
||||||
return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
|
return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.svlada.security.auth.jwt;
|
package com.svlada.security.auth.jwt.verifier;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.svlada.security.auth.jwt;
|
package com.svlada.security.auth.jwt.verifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -21,7 +21,7 @@ import com.svlada.security.auth.ajax.AjaxLoginProcessingFilter;
|
|||||||
import com.svlada.security.auth.jwt.JwtAuthenticationProvider;
|
import com.svlada.security.auth.jwt.JwtAuthenticationProvider;
|
||||||
import com.svlada.security.auth.jwt.JwtTokenAuthenticationProcessingFilter;
|
import com.svlada.security.auth.jwt.JwtTokenAuthenticationProcessingFilter;
|
||||||
import com.svlada.security.auth.jwt.extractor.TokenExtractor;
|
import com.svlada.security.auth.jwt.extractor.TokenExtractor;
|
||||||
import com.svlada.security.model.JwtTokenFactory;
|
import com.svlada.security.model.token.JwtTokenFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSecurityConfig
|
* WebSecurityConfig
|
||||||
|
|||||||
@ -21,18 +21,15 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import com.svlada.entity.User;
|
import com.svlada.entity.User;
|
||||||
import com.svlada.security.UserService;
|
import com.svlada.security.UserService;
|
||||||
import com.svlada.security.auth.jwt.TokenVerifier;
|
import com.svlada.security.auth.jwt.verifier.TokenVerifier;
|
||||||
import com.svlada.security.config.JwtSettings;
|
import com.svlada.security.config.JwtSettings;
|
||||||
import com.svlada.security.config.WebSecurityConfig;
|
import com.svlada.security.config.WebSecurityConfig;
|
||||||
import com.svlada.security.exceptions.InvalidJwtToken;
|
import com.svlada.security.exceptions.InvalidJwtToken;
|
||||||
import com.svlada.security.model.JwtToken;
|
|
||||||
import com.svlada.security.model.JwtTokenFactory;
|
|
||||||
import com.svlada.security.model.Scopes;
|
|
||||||
import com.svlada.security.model.UnsafeJwtToken;
|
|
||||||
import com.svlada.security.model.UserContext;
|
import com.svlada.security.model.UserContext;
|
||||||
|
import com.svlada.security.model.token.JwtToken;
|
||||||
import io.jsonwebtoken.Claims;
|
import com.svlada.security.model.token.JwtTokenFactory;
|
||||||
import io.jsonwebtoken.Jws;
|
import com.svlada.security.model.token.RawAccessJwtToken;
|
||||||
|
import com.svlada.security.model.token.RefreshToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RefreshTokenEndpoint
|
* RefreshTokenEndpoint
|
||||||
@ -41,7 +38,6 @@ import io.jsonwebtoken.Jws;
|
|||||||
*
|
*
|
||||||
* Aug 17, 2016
|
* Aug 17, 2016
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@RestController
|
@RestController
|
||||||
public class RefreshTokenEndpoint {
|
public class RefreshTokenEndpoint {
|
||||||
@Autowired private JwtTokenFactory tokenFactory;
|
@Autowired private JwtTokenFactory tokenFactory;
|
||||||
@ -51,31 +47,24 @@ public class RefreshTokenEndpoint {
|
|||||||
|
|
||||||
@RequestMapping(value="/api/auth/token", method=RequestMethod.GET, produces={ MediaType.APPLICATION_JSON_VALUE })
|
@RequestMapping(value="/api/auth/token", method=RequestMethod.GET, produces={ MediaType.APPLICATION_JSON_VALUE })
|
||||||
public @ResponseBody JwtToken refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
public @ResponseBody JwtToken refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
UnsafeJwtToken unsafeToken = this.tokenFactory.createUnsafeToken(request.getHeader(WebSecurityConfig.JWT_TOKEN_HEADER_PARAM));
|
RawAccessJwtToken rawToken = new RawAccessJwtToken(request.getHeader(WebSecurityConfig.JWT_TOKEN_HEADER_PARAM));
|
||||||
Jws<Claims> jwsClaims = unsafeToken.parseClaims(jwtSettings.getTokenSigningKey());
|
RefreshToken refreshToken = RefreshToken.create(rawToken, jwtSettings.getTokenSigningKey()).orElseThrow(() -> new InvalidJwtToken());
|
||||||
|
|
||||||
List<String> scopes = jwsClaims.getBody().get("scopes", List.class);
|
|
||||||
if (scopes == null || scopes.isEmpty()
|
|
||||||
|| !scopes.stream().filter(scope -> Scopes.REFRESH_TOKEN.authority().equals(scope)).findFirst().isPresent()) {
|
|
||||||
throw new InvalidJwtToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
String jti = jwsClaims.getBody().getId();
|
String jti = refreshToken.getJti();
|
||||||
if (!tokenVerifier.verify(jti)) {
|
if (!tokenVerifier.verify(jti)) {
|
||||||
throw new InvalidJwtToken();
|
throw new InvalidJwtToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
String subject = jwsClaims.getBody().getSubject();
|
String subject = refreshToken.getSubject();
|
||||||
|
|
||||||
User user = userService.getByUsername(subject).orElseThrow(() -> new UsernameNotFoundException("User not found: " + subject));
|
User user = userService.getByUsername(subject).orElseThrow(() -> new UsernameNotFoundException("User not found: " + subject));
|
||||||
|
|
||||||
if (user.getRoles() == null) throw new InsufficientAuthenticationException("User has no roles assigned");
|
if (user.getRoles() == null) throw new InsufficientAuthenticationException("User has no roles assigned");
|
||||||
List<GrantedAuthority> authorities = user.getRoles().stream()
|
List<GrantedAuthority> authorities = user.getRoles().stream()
|
||||||
.map(authority -> new SimpleGrantedAuthority(authority.getRole().authority()))
|
.map(authority -> new SimpleGrantedAuthority(authority.getRole().authority()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
UserContext userContext = UserContext.create(user.getUsername(), authorities);
|
UserContext userContext = UserContext.create(user.getUsername(), authorities);
|
||||||
|
|
||||||
return tokenFactory.createSafeToken(userContext);
|
return tokenFactory.createAccessJwtToken(userContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package com.svlada.security.exceptions;
|
|||||||
|
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
|
||||||
import com.svlada.security.model.JwtToken;
|
import com.svlada.security.model.token.JwtToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
package com.svlada.security.model;
|
package com.svlada.security.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.svlada.security.model;
|
package com.svlada.security.model.token;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
@ -11,11 +11,11 @@ import io.jsonwebtoken.Claims;
|
|||||||
*
|
*
|
||||||
* May 31, 2016
|
* May 31, 2016
|
||||||
*/
|
*/
|
||||||
public final class SafeJwtToken implements JwtToken {
|
public final class AccessJwtToken implements JwtToken {
|
||||||
private final String rawToken;
|
private final String rawToken;
|
||||||
@JsonIgnore private Claims claims;
|
@JsonIgnore private Claims claims;
|
||||||
|
|
||||||
protected SafeJwtToken(final String token, Claims claims) {
|
protected AccessJwtToken(final String token, Claims claims) {
|
||||||
this.rawToken = token;
|
this.rawToken = token;
|
||||||
this.claims = claims;
|
this.claims = claims;
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.svlada.security.model;
|
package com.svlada.security.model.token;
|
||||||
|
|
||||||
public interface JwtToken {
|
public interface JwtToken {
|
||||||
String getToken();
|
String getToken();
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.svlada.security.model;
|
package com.svlada.security.model.token;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -10,6 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.svlada.security.config.JwtSettings;
|
import com.svlada.security.config.JwtSettings;
|
||||||
|
import com.svlada.security.model.Scopes;
|
||||||
|
import com.svlada.security.model.UserContext;
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
@ -38,14 +40,12 @@ public class JwtTokenFactory {
|
|||||||
* @param roles
|
* @param roles
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public SafeJwtToken createSafeToken(UserContext userContext) {
|
public AccessJwtToken createAccessJwtToken(UserContext userContext) {
|
||||||
if (StringUtils.isBlank(userContext.getUsername())) {
|
if (StringUtils.isBlank(userContext.getUsername()))
|
||||||
throw new IllegalArgumentException("Cannot create JWT Token without username");
|
throw new IllegalArgumentException("Cannot create JWT Token without username");
|
||||||
}
|
|
||||||
|
|
||||||
if (userContext.getAuthorities() == null || userContext.getAuthorities().isEmpty()) {
|
if (userContext.getAuthorities() == null || userContext.getAuthorities().isEmpty())
|
||||||
throw new IllegalArgumentException("User doesn't have any privileges");
|
throw new IllegalArgumentException("User doesn't have any privileges");
|
||||||
}
|
|
||||||
|
|
||||||
Claims claims = Jwts.claims().setSubject(userContext.getUsername());
|
Claims claims = Jwts.claims().setSubject(userContext.getUsername());
|
||||||
claims.put("scopes", userContext.getAuthorities().stream().map(s -> s.toString()).collect(Collectors.toList()));
|
claims.put("scopes", userContext.getAuthorities().stream().map(s -> s.toString()).collect(Collectors.toList()));
|
||||||
@ -60,7 +60,7 @@ public class JwtTokenFactory {
|
|||||||
.signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey())
|
.signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey())
|
||||||
.compact();
|
.compact();
|
||||||
|
|
||||||
return new SafeJwtToken(token, claims);
|
return new AccessJwtToken(token, claims);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JwtToken createRefreshToken(UserContext userContext) {
|
public JwtToken createRefreshToken(UserContext userContext) {
|
||||||
@ -82,18 +82,6 @@ public class JwtTokenFactory {
|
|||||||
.signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey())
|
.signWith(SignatureAlgorithm.HS512, settings.getTokenSigningKey())
|
||||||
.compact();
|
.compact();
|
||||||
|
|
||||||
return new SafeJwtToken(token, claims);
|
return new AccessJwtToken(token, claims);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsafe version of JWT token is created.
|
|
||||||
*
|
|
||||||
* <strong>WARNING:</strong> Token signature validation is not performed.
|
|
||||||
*
|
|
||||||
* @param tokenPayload
|
|
||||||
* @return unsafe version of JWT token.
|
|
||||||
*/
|
|
||||||
public UnsafeJwtToken createUnsafeToken(String tokenPayload) {
|
|
||||||
return new UnsafeJwtToken(tokenPayload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.svlada.security.model;
|
package com.svlada.security.model.token;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -14,12 +14,12 @@ import io.jsonwebtoken.MalformedJwtException;
|
|||||||
import io.jsonwebtoken.SignatureException;
|
import io.jsonwebtoken.SignatureException;
|
||||||
import io.jsonwebtoken.UnsupportedJwtException;
|
import io.jsonwebtoken.UnsupportedJwtException;
|
||||||
|
|
||||||
public class UnsafeJwtToken implements JwtToken {
|
public class RawAccessJwtToken implements JwtToken {
|
||||||
private static Logger logger = LoggerFactory.getLogger(UnsafeJwtToken.class);
|
private static Logger logger = LoggerFactory.getLogger(RawAccessJwtToken.class);
|
||||||
|
|
||||||
private String token;
|
private String token;
|
||||||
|
|
||||||
public UnsafeJwtToken(String token) {
|
public RawAccessJwtToken(String token) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
package com.svlada.security.model.token;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
|
||||||
|
import com.svlada.security.exceptions.JwtExpiredTokenException;
|
||||||
|
import com.svlada.security.model.Scopes;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jws;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author vladimir.stankovic
|
||||||
|
*
|
||||||
|
* Aug 19, 2016
|
||||||
|
*/
|
||||||
|
public class RefreshToken implements JwtToken {
|
||||||
|
private Jws<Claims> claims;
|
||||||
|
|
||||||
|
private RefreshToken(Jws<Claims> claims) {
|
||||||
|
this.claims = claims;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and validates Refresh token
|
||||||
|
*
|
||||||
|
* @param token
|
||||||
|
* @param signingKey
|
||||||
|
*
|
||||||
|
* @throws BadCredentialsException
|
||||||
|
* @throws JwtExpiredTokenException
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Optional<RefreshToken> create(RawAccessJwtToken token, String signingKey) {
|
||||||
|
Jws<Claims> claims = token.parseClaims(signingKey);
|
||||||
|
|
||||||
|
List<String> scopes = claims.getBody().get("scopes", List.class);
|
||||||
|
if (scopes == null || scopes.isEmpty()
|
||||||
|
|| !scopes.stream().filter(scope -> Scopes.REFRESH_TOKEN.authority().equals(scope)).findFirst().isPresent()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.of(new RefreshToken(claims));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getToken() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jws<Claims> getClaims() {
|
||||||
|
return claims;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJti() {
|
||||||
|
return claims.getBody().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return claims.getBody().getSubject();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user