![JAR search and dependency download from the Maven repository](/logo.png)
org.cloudfoundry.identity.uaa.util.UaaTokenUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cloudfoundry-identity-server Show documentation
Show all versions of cloudfoundry-identity-server Show documentation
Cloud Foundry User Account and Authentication
The newest version!
/*
* *****************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2015] Pivotal Software, Inc. All Rights Reserved.
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
* You may not use this product except in compliance with the License.
*
* This product includes a number of subcomponents with
* separate copyright notices and license terms. Your use of these
* subcomponents is subject to the terms and conditions of the
* subcomponent's license, as noted in the LICENSE file.
* *****************************************************************************
*/
package org.cloudfoundry.identity.uaa.util;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.codec.binary.Base64;
import org.cloudfoundry.identity.uaa.oauth.client.ClientConstants;
import org.cloudfoundry.identity.uaa.oauth.jwt.Jwt;
import org.cloudfoundry.identity.uaa.oauth.jwt.JwtHelper;
import org.cloudfoundry.identity.uaa.user.UaaUser;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.jwt.crypto.sign.Signer;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static java.util.Collections.emptySet;
import static java.util.Optional.ofNullable;
import static org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants.CID;
import static org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants.GRANT_TYPE;
import static org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants.SUB;
import static org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants.USER_ID;
import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.GRANT_TYPE_CLIENT_CREDENTIALS;
import static org.springframework.util.StringUtils.hasText;
public final class UaaTokenUtils {
public static final Pattern jwtPattern = Pattern.compile("[a-zA-Z0-9_\\-\\\\=]*\\.[a-zA-Z0-9_\\-\\\\=]*\\.[a-zA-Z0-9_\\-\\\\=]*");
private UaaTokenUtils() { }
public static String getRevocationHash(List salts) {
String result = "";
for (String s : salts) {
byte[] hashable = (result+ "###" + s).getBytes();
result = Integer.toHexString(murmurhash3x8632(hashable, 0, hashable.length, 0xF0F0));
}
return result;
}
/**
* This code is public domain.
*
* The MurmurHash3 algorithm was created by Austin Appleby and put into the public domain.
* @see http://code.google.com/p/smhasher
* @see https://github.com/yonik/java_util/blob/master/src/util/hash/MurmurHash3.java
*/
public static int murmurhash3x8632(byte[] data, int offset, int len, int seed) {
int c1 = 0xcc9e2d51;
int c2 = 0x1b873593;
int h1 = seed;
int roundedEnd = offset + (len & 0xfffffffc); // round down to 4 byte block
for (int i = offset; i < roundedEnd; i += 4) {
// little endian load order
int k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) | ((data[i + 2] & 0xff) << 16) | (data[i + 3] << 24);
k1 *= c1;
k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15);
k1 *= c2;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13);
h1 = h1 * 5 + 0xe6546b64;
}
// tail
int k1 = 0;
switch(len & 0x03) {
case 3:
k1 = (data[roundedEnd + 2] & 0xff) << 16;
// fallthrough
case 2:
k1 |= (data[roundedEnd + 1] & 0xff) << 8;
// fallthrough
case 1:
k1 |= data[roundedEnd] & 0xff;
k1 *= c1;
k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15);
k1 *= c2;
h1 ^= k1;
default:
}
// finalization
h1 ^= len;
// fmix(h1);
h1 ^= h1 >>> 16;
h1 *= 0x85ebca6b;
h1 ^= h1 >>> 13;
h1 *= 0xc2b2ae35;
h1 ^= h1 >>> 16;
return h1;
}
public static Set retainAutoApprovedScopes(Collection requestedScopes, Set autoApprovedScopes) {
HashSet result = new HashSet<>();
if(autoApprovedScopes == null){
return result;
}
if (autoApprovedScopes.contains("true")) {
result.addAll(requestedScopes);
return result;
}
Set autoApprovedScopePatterns = UaaStringUtils.constructWildcards(autoApprovedScopes);
// Don't want to approve more than what's requested
for (String scope : requestedScopes) {
if (UaaStringUtils.matches(autoApprovedScopePatterns, scope)) {
result.add(scope);
}
}
return result;
}
public static boolean isUserToken(Map claims) {
if (claims.get(GRANT_TYPE)!=null) {
return !GRANT_TYPE_CLIENT_CREDENTIALS.equals(claims.get(GRANT_TYPE));
}
if (claims.get(SUB)!=null) {
if (claims.get(SUB).equals(claims.get(USER_ID))) {
return true;
} else if (claims.get(SUB).equals(claims.get(CID))) {
return false;
}
}
//err on the side of caution
return true;
}
public static String getRevocableTokenSignature(ClientDetails client, String clientSecret, UaaUser user) {
String tokenSalt = (String) client.getAdditionalInformation().get(ClientConstants.TOKEN_SALT);
String clientId = client.getClientId();
return getRevocableTokenSignature(user, tokenSalt, clientId, clientSecret);
}
public static String getRevocableTokenSignature(UaaUser user, String tokenSalt, String clientId, String clientSecret) {
String[] salts = new String[] {
clientId,
clientSecret,
tokenSalt,
user == null ? null : user.getId(),
user == null ? null : user.getPassword(),
user == null ? null : user.getSalt(),
user == null ? null : user.getEmail(),
user == null ? null : user.getUsername(),
};
List saltlist = new LinkedList<>();
for (String s : salts) {
if (s!=null) {
saltlist.add(s);
}
}
return getRevocationHash(saltlist);
}
public static String constructToken(Map header, Map claims, Signer signer) {
byte[] headerJson = header == null ? new byte[0] : JsonUtils.writeValueAsBytes(header);
byte[] claimsJson = claims == null ? new byte[0] : JsonUtils.writeValueAsBytes(claims);
String headerBase64 = Base64.encodeBase64URLSafeString(headerJson);
String claimsBase64 = Base64.encodeBase64URLSafeString(claimsJson);
String headerAndClaims = headerBase64 + "." + claimsBase64;
byte[] signature = signer.sign(headerAndClaims.getBytes());
String signatureBase64 = Base64.encodeBase64URLSafeString(signature);
return headerAndClaims + "." + signatureBase64;
}
public static boolean isJwtToken(String token) {
return jwtPattern.matcher(token).matches();
}
public static String constructTokenEndpointUrl(String issuer) throws URISyntaxException {
URI uri;
if (!IdentityZoneHolder.isUaa()) {
String zone_issuer = IdentityZoneHolder.get().getConfig() != null ? IdentityZoneHolder.get().getConfig().getIssuer() : null;
if(zone_issuer != null) {
uri = validateIssuer(zone_issuer);
return UriComponentsBuilder.fromUri(uri).pathSegment("oauth/token").build().toUriString();
}
}
uri = validateIssuer(issuer);
String hostToUse = uri.getHost();
if (hasText(IdentityZoneHolder.get().getSubdomain())) {
hostToUse = IdentityZoneHolder.get().getSubdomain() + "." + hostToUse;
}
return UriComponentsBuilder.fromUri(uri).host(hostToUse).pathSegment("oauth/token").build().toUriString();
}
private static URI validateIssuer(String issuer) throws URISyntaxException {
try {
new URL(issuer);
} catch (MalformedURLException x) {
throw new URISyntaxException(issuer, x.getMessage());
}
return new URI(issuer);
}
public static boolean hasRequiredUserAuthorities(Collection requiredGroups, Collection extends GrantedAuthority> userGroups) {
return hasRequiredUserGroups(requiredGroups,
ofNullable(userGroups).orElse(emptySet())
.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList())
);
}
public static boolean hasRequiredUserGroups(Collection requiredGroups, Collection userGroups) {
return ofNullable(userGroups).orElse(emptySet())
.containsAll(ofNullable(requiredGroups).orElse(emptySet()));
}
public static Map getClaims(String jwtToken) {
Jwt jwt;
try {
jwt = JwtHelper.decode(jwtToken);
} catch (Exception ex) {
throw new InvalidTokenException("Invalid token (could not decode): " + jwtToken, ex);
}
Map claims;
try {
claims = JsonUtils.readValue(jwt.getClaims(), new TypeReference
© 2015 - 2025 Weber Informatics LLC | Privacy Policy