Skip to content

Commit

Permalink
Fix tests after granted_scopes refactor
Browse files Browse the repository at this point in the history
[#158577941] https://www.pivotaltracker.com/story/show/158577941

Signed-off-by: Bruce Ricard <bricard@pivotal.io>
  • Loading branch information
jhamon authored and bruce-ricard committed Jul 18, 2018
1 parent 71cf5fb commit 2e5051d
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 38 deletions.
Expand Up @@ -52,6 +52,7 @@
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
Expand Down Expand Up @@ -1065,6 +1066,7 @@ protected TokenValidation validateToken(String token, boolean isAccessToken) {
token = revocableToken.getValue(); token = revocableToken.getValue();
} }



TokenValidation tokenValidation = isAccessToken ? TokenValidation tokenValidation = isAccessToken ?
buildAccessTokenValidator(token) : buildRefreshTokenValidator(token); buildAccessTokenValidator(token) : buildRefreshTokenValidator(token);
tokenValidation tokenValidation
Expand Down
Expand Up @@ -114,20 +114,58 @@ private TokenValidation(String token, boolean isAccessToken) {
this.claims = new HashMap<>(); this.claims = new HashMap<>();
} }


if (tokenJwt != null) { Optional<SignatureVerifier> signatureVerifier =
validateHeader(tokenJwt); fetchSignatureVerifierFromToken(tokenJwt);

signatureVerifier.ifPresent(this::validateHeader);

this.decoded = isValid();
}

private TokenValidation(String token, boolean isAccessToken, SignatureVerifier signatureVerifier) {
this.token = token;
this.isAccessToken = isAccessToken;

Jwt tokenJwt;
try {
tokenJwt = JwtHelper.decode(token);
} catch (Exception ex) {
tokenJwt = null;
validationErrors.add(new InvalidTokenException("Invalid token (could not decode): " + token, ex));
} }
this.tokenJwt = tokenJwt;

String tokenJwtClaims;
if(tokenJwt != null && StringUtils.hasText(tokenJwtClaims = tokenJwt.getClaims())) {
Map<String, Object> claims;
try {
claims = JsonUtils.readValue(tokenJwtClaims, new TypeReference<Map<String, Object>>() {});
}
catch (JsonUtils.JsonUtilException ex) {
claims = null;
validationErrors.add(new InvalidTokenException("Invalid token (cannot read token claims): " + token, ex));
}
this.claims = claims;
} else {
this.claims = new HashMap<>();
}

validateHeader(signatureVerifier);


this.decoded = isValid(); this.decoded = isValid();
} }


private TokenValidation validateHeader(Jwt tokenJwt) { private Optional<SignatureVerifier> fetchSignatureVerifierFromToken(Jwt tokenJwt) {
if (tokenJwt == null) {
return Optional.empty();
}

String kid = tokenJwt.getHeader().getKid(); String kid = tokenJwt.getHeader().getKid();
if (kid == null) { if (kid == null) {
validationErrors.add( validationErrors.add(
new InvalidTokenException("kid claim not found in JWT token header") new InvalidTokenException("kid claim not found in JWT token header")
); );
return this; return Optional.empty();
} }


KeyInfo signingKey = KeyInfo.getKey(kid); KeyInfo signingKey = KeyInfo.getKey(kid);
Expand All @@ -137,10 +175,15 @@ private TokenValidation validateHeader(Jwt tokenJwt) {
"Token header claim [kid] references unknown signing key : [%s]", kid "Token header claim [kid] references unknown signing key : [%s]", kid
)) ))
); );
return this; return Optional.empty();
} }


SignatureVerifier signatureVerifier = signingKey.getVerifier(); SignatureVerifier signatureVerifier = signingKey.getVerifier();

return Optional.of(signatureVerifier);
}

private TokenValidation validateHeader(SignatureVerifier signatureVerifier) {
return checkSignature(signatureVerifier); return checkSignature(signatureVerifier);
} }


Expand All @@ -167,7 +210,7 @@ private TokenValidation(TokenValidation source) {
this.scopes = source.scopes; this.scopes = source.scopes;
} }



//TODO: make private
public TokenValidation checkSignature(SignatureVerifier verifier) { public TokenValidation checkSignature(SignatureVerifier verifier) {
if(isValid()) { if(isValid()) {
try { try {
Expand Down Expand Up @@ -272,7 +315,8 @@ protected TokenValidation checkScopesWithin(String... scopes) {
} }


protected TokenValidation checkScopesWithin(Collection<String> scopes) { protected TokenValidation checkScopesWithin(Collection<String> scopes) {
getScopes().ifPresent(tokenScopes -> { Optional<List<String>> scopesGot = getScopes();
scopesGot.ifPresent(tokenScopes -> {
Set<Pattern> scopePatterns = UaaStringUtils.constructWildcards(scopes); Set<Pattern> scopePatterns = UaaStringUtils.constructWildcards(scopes);
List<String> missingScopes = tokenScopes.stream().filter(s -> !scopePatterns.stream().anyMatch(p -> p.matcher(s).matches())).collect(Collectors.toList()); List<String> missingScopes = tokenScopes.stream().filter(s -> !scopePatterns.stream().anyMatch(p -> p.matcher(s).matches())).collect(Collectors.toList());
if(!missingScopes.isEmpty()) { if(!missingScopes.isEmpty()) {
Expand Down Expand Up @@ -500,9 +544,11 @@ private Optional<List<String>> readScopesFromClaim(String claimName) {
} }


try { try {
return scopes = Optional.of(((List<?>) scopeClaim).stream() List<String> scopeList = ((List<?>) scopeClaim).stream()
.map(s -> (String) s) .map(s -> (String) s)
.collect(Collectors.toList())); .collect(Collectors.toList());
scopes = Optional.of(scopeList);
return scopes;
} catch (ClassCastException ex) { } catch (ClassCastException ex) {
addError("The token's scope claim is invalid or unparseable.", ex); addError("The token's scope claim is invalid or unparseable.", ex);
return scopes = Optional.empty(); return scopes = Optional.empty();
Expand Down Expand Up @@ -559,4 +605,16 @@ public UaaUser getUserDetails(UaaUserDatabase userDatabase) {
} }
return null; return null;
} }


public static TokenValidation buildAccessTokenValidatorForTesting(String tokenJwtValue,
SignatureVerifier signatureVerifier) {
return new TokenValidation(tokenJwtValue, true, signatureVerifier);
}

public static TokenValidation buildRefreshTokenValidatorForTesting(String tokenJwtValue,
SignatureVerifier signatureVerifier) {
return new TokenValidation(tokenJwtValue, false, signatureVerifier);
}

} }

0 comments on commit 2e5051d

Please sign in to comment.