v 1.5.0 RC2

v 1.5.0 RC2
This commit is contained in:
shimingxy
2020-05-17 09:58:36 +08:00
parent 2ac28e572f
commit 27e0c0b376
35 changed files with 1542 additions and 1313 deletions

View File

@@ -15,65 +15,70 @@ import org.springframework.jdbc.core.support.SqlLobValue;
import org.springframework.util.Assert;
/**
* Implementation of authorization code services that stores the codes and authentication in a database.
* Implementation of authorization code services that stores the codes and
* authentication in a database.
*
* @author Crystal.Sea
*/
public class JdbcAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {
private static final String DEFAULT_SELECT_STATEMENT = "select code, authentication from oauth_code where code = ?";
private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_code (code, authentication) values (?, ?)";
private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_code where code = ?";
private static final String DEFAULT_SELECT_STATEMENT = "select code, authentication from oauth_code where code = ?";
private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_code (code, authentication) values (?, ?)";
private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_code where code = ?";
private String selectAuthenticationSql = DEFAULT_SELECT_STATEMENT;
private String insertAuthenticationSql = DEFAULT_INSERT_STATEMENT;
private String deleteAuthenticationSql = DEFAULT_DELETE_STATEMENT;
private String selectAuthenticationSql = DEFAULT_SELECT_STATEMENT;
private String insertAuthenticationSql = DEFAULT_INSERT_STATEMENT;
private String deleteAuthenticationSql = DEFAULT_DELETE_STATEMENT;
private final JdbcTemplate jdbcTemplate;
private final JdbcTemplate jdbcTemplate;
public JdbcAuthorizationCodeServices(DataSource dataSource) {
Assert.notNull(dataSource, "DataSource required");
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public JdbcAuthorizationCodeServices(DataSource dataSource) {
Assert.notNull(dataSource, "DataSource required");
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
protected void store(String code, OAuth2Authentication authentication) {
jdbcTemplate.update(insertAuthenticationSql,
new Object[] { code, new SqlLobValue(SerializationUtils.serialize(authentication)) }, new int[] {
Types.VARCHAR, Types.BLOB });
}
public JdbcAuthorizationCodeServices(JdbcTemplate jdbcTemplate) {
Assert.notNull(jdbcTemplate, "jdbcTemplate required");
this.jdbcTemplate = jdbcTemplate;
}
@Override
protected void store(String code, OAuth2Authentication authentication) {
jdbcTemplate.update(insertAuthenticationSql,
new Object[] { code, new SqlLobValue(SerializationUtils.serialize(authentication)) },
new int[] { Types.VARCHAR, Types.BLOB });
}
public OAuth2Authentication remove(String code) {
OAuth2Authentication authentication;
public OAuth2Authentication remove(String code) {
OAuth2Authentication authentication;
try {
authentication = jdbcTemplate.queryForObject(selectAuthenticationSql,
new RowMapper<OAuth2Authentication>() {
public OAuth2Authentication mapRow(ResultSet rs, int rowNum)
throws SQLException {
return SerializationUtils.deserialize(rs.getBytes("authentication"));
}
}, code);
} catch (EmptyResultDataAccessException e) {
return null;
}
try {
authentication = jdbcTemplate.queryForObject(selectAuthenticationSql,
new RowMapper<OAuth2Authentication>() {
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
return SerializationUtils.deserialize(rs.getBytes("authentication"));
}
}, code);
} catch (EmptyResultDataAccessException e) {
return null;
}
if (authentication != null) {
jdbcTemplate.update(deleteAuthenticationSql, code);
}
if (authentication != null) {
jdbcTemplate.update(deleteAuthenticationSql, code);
}
return authentication;
}
return authentication;
}
public void setSelectAuthenticationSql(String selectAuthenticationSql) {
this.selectAuthenticationSql = selectAuthenticationSql;
}
public void setSelectAuthenticationSql(String selectAuthenticationSql) {
this.selectAuthenticationSql = selectAuthenticationSql;
}
public void setInsertAuthenticationSql(String insertAuthenticationSql) {
this.insertAuthenticationSql = insertAuthenticationSql;
}
public void setInsertAuthenticationSql(String insertAuthenticationSql) {
this.insertAuthenticationSql = insertAuthenticationSql;
}
public void setDeleteAuthenticationSql(String deleteAuthenticationSql) {
this.deleteAuthenticationSql = deleteAuthenticationSql;
}
public void setDeleteAuthenticationSql(String deleteAuthenticationSql) {
this.deleteAuthenticationSql = deleteAuthenticationSql;
}
}

View File

@@ -37,423 +37,416 @@ import org.springframework.util.Assert;
*/
public class JdbcTokenStore implements TokenStore {
private static final Log LOG = LogFactory.getLog(JdbcTokenStore.class);
private static final Log LOG = LogFactory.getLog(JdbcTokenStore.class);
private static final String DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT = "insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)";
private static final String DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT = "insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)";
private static final String DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_access_token where token_id = ?";
private static final String DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_access_token where token_id = ?";
private static final String DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_access_token where token_id = ?";
private static final String DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_access_token where token_id = ?";
private static final String DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT = "select token_id, token from oauth_access_token where authentication_id = ?";
private static final String DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT = "select token_id, token from oauth_access_token where authentication_id = ?";
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?";
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?";
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?";
private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?";
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?";
private static final String DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT = "delete from oauth_access_token where token_id = ?";
private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?";
private static final String DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT = "delete from oauth_access_token where refresh_token = ?";
private static final String DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT = "delete from oauth_access_token where token_id = ?";
private static final String DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT = "insert into oauth_refresh_token (token_id, token, authentication) values (?, ?, ?)";
private static final String DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT = "delete from oauth_access_token where refresh_token = ?";
private static final String DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_refresh_token where token_id = ?";
private static final String DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT = "insert into oauth_refresh_token (token_id, token, authentication) values (?, ?, ?)";
private static final String DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_refresh_token where token_id = ?";
private static final String DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_refresh_token where token_id = ?";
private static final String DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT = "delete from oauth_refresh_token where token_id = ?";
private static final String DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_refresh_token where token_id = ?";
private String insertAccessTokenSql = DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT;
private static final String DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT = "delete from oauth_refresh_token where token_id = ?";
private String selectAccessTokenSql = DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT;
private String insertAccessTokenSql = DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT;
private String selectAccessTokenAuthenticationSql = DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
private String selectAccessTokenSql = DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT;
private String selectAccessTokenFromAuthenticationSql = DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT;
private String selectAccessTokenAuthenticationSql = DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT;
private String selectAccessTokenFromAuthenticationSql = DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT;
private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT;
private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT;
private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT;
private String deleteAccessTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT;
private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT;
private String insertRefreshTokenSql = DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT;
private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT;
private String selectRefreshTokenSql = DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT;
private String deleteAccessTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT;
private String selectRefreshTokenAuthenticationSql = DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
private String insertRefreshTokenSql = DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT;
private String deleteRefreshTokenSql = DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT;
private String selectRefreshTokenSql = DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT;
private String deleteAccessTokenFromRefreshTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT;
private String selectRefreshTokenAuthenticationSql = DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
private String deleteRefreshTokenSql = DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT;
private final JdbcTemplate jdbcTemplate;
private String deleteAccessTokenFromRefreshTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT;
public JdbcTokenStore(DataSource dataSource) {
Assert.notNull(dataSource, "DataSource required");
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
this.authenticationKeyGenerator = authenticationKeyGenerator;
}
private final JdbcTemplate jdbcTemplate;
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
OAuth2AccessToken accessToken = null;
String key = authenticationKeyGenerator.extractKey(authentication);
try {
accessToken = jdbcTemplate.queryForObject(selectAccessTokenFromAuthenticationSql,
new RowMapper<OAuth2AccessToken>() {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAccessToken(rs.getBytes(2));
}
}, key);
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.debug("Failed to find access token for authentication " + authentication);
}
}
catch (IllegalArgumentException e) {
LOG.error("Could not extract access token for authentication " + authentication, e);
}
if (accessToken != null
&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {
removeAccessToken(accessToken.getValue());
// Keep the store consistent (maybe the same user is represented by this authentication but the details have
// changed)
storeAccessToken(accessToken, authentication);
}
return accessToken;
}
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
String refreshToken = null;
if (token.getRefreshToken() != null) {
refreshToken = token.getRefreshToken().getValue();
}
if (readAccessToken(token.getValue())!=null) {
removeAccessToken(token.getValue());
}
jdbcTemplate.update(insertAccessTokenSql, new Object[] { extractTokenKey(token.getValue()),
new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication),
authentication.isClientOnly() ? null : authentication.getName(),
authentication.getOAuth2Request().getClientId(),
new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] {
Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR });
}
public OAuth2AccessToken readAccessToken(String tokenValue) {
OAuth2AccessToken accessToken = null;
try {
accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAccessToken(rs.getBytes(2));
}
}, extractTokenKey(tokenValue));
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + tokenValue);
}
}
catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize access token for " + tokenValue, e);
removeAccessToken(tokenValue);
}
return accessToken;
}
public void removeAccessToken(OAuth2AccessToken token) {
removeAccessToken(token.getValue());
}
public void removeAccessToken(String tokenValue) {
jdbcTemplate.update(deleteAccessTokenSql, extractTokenKey(tokenValue));
}
public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
return readAuthentication(token.getValue());
}
public OAuth2Authentication readAuthentication(String token) {
OAuth2Authentication authentication = null;
try {
authentication = jdbcTemplate.queryForObject(selectAccessTokenAuthenticationSql,
new RowMapper<OAuth2Authentication>() {
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAuthentication(rs.getBytes(2));
}
}, extractTokenKey(token));
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + token);
}
}
catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize authentication for " + token, e);
removeAccessToken(token);
}
return authentication;
}
public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
jdbcTemplate.update(insertRefreshTokenSql, new Object[] { extractTokenKey(refreshToken.getValue()),
new SqlLobValue(serializeRefreshToken(refreshToken)),
new SqlLobValue(serializeAuthentication(authentication)) }, new int[] { Types.VARCHAR, Types.BLOB,
Types.BLOB });
}
public OAuth2RefreshToken readRefreshToken(String token) {
OAuth2RefreshToken refreshToken = null;
try {
refreshToken = jdbcTemplate.queryForObject(selectRefreshTokenSql, new RowMapper<OAuth2RefreshToken>() {
public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeRefreshToken(rs.getBytes(2));
}
}, extractTokenKey(token));
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find refresh token for token " + token);
}
}
catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize refresh token for token " + token, e);
removeRefreshToken(token);
}
return refreshToken;
}
public void removeRefreshToken(OAuth2RefreshToken token) {
removeRefreshToken(token.getValue());
}
public void removeRefreshToken(String token) {
jdbcTemplate.update(deleteRefreshTokenSql, extractTokenKey(token));
}
public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
return readAuthenticationForRefreshToken(token.getValue());
}
public OAuth2Authentication readAuthenticationForRefreshToken(String value) {
OAuth2Authentication authentication = null;
try {
authentication = jdbcTemplate.queryForObject(selectRefreshTokenAuthenticationSql,
new RowMapper<OAuth2Authentication>() {
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAuthentication(rs.getBytes(2));
}
}, extractTokenKey(value));
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + value);
}
}
catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize access token for " + value, e);
removeRefreshToken(value);
}
return authentication;
}
public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
removeAccessTokenUsingRefreshToken(refreshToken.getValue());
}
public void removeAccessTokenUsingRefreshToken(String refreshToken) {
jdbcTemplate.update(deleteAccessTokenFromRefreshTokenSql, new Object[] { extractTokenKey(refreshToken) },
new int[] { Types.VARCHAR });
}
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
try {
accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(),
clientId);
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for clientId " + clientId);
}
}
accessTokens = removeNulls(accessTokens);
return accessTokens;
}
public Collection<OAuth2AccessToken> findTokensByUserName(String userName) {
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
try {
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(),
userName);
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled())
LOG.info("Failed to find access token for userName " + userName);
}
accessTokens = removeNulls(accessTokens);
return accessTokens;
}
public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
try {
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameAndClientIdSql, new SafeAccessTokenRowMapper(),
userName, clientId);
}
catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName);
}
}
accessTokens = removeNulls(accessTokens);
return accessTokens;
}
private List<OAuth2AccessToken> removeNulls(List<OAuth2AccessToken> accessTokens) {
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
for (OAuth2AccessToken token : accessTokens) {
if (token != null) {
tokens.add(token);
}
}
return tokens;
}
protected String extractTokenKey(String value) {
if (value == null) {
return null;
}
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
}
try {
byte[] bytes = digest.digest(value.getBytes("UTF-8"));
return String.format("%032x", new BigInteger(1, bytes));
}
catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
}
}
private final class SafeAccessTokenRowMapper implements RowMapper<OAuth2AccessToken> {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
try {
return deserializeAccessToken(rs.getBytes(2));
}
catch (IllegalArgumentException e) {
String token = rs.getString(1);
jdbcTemplate.update(deleteAccessTokenSql, token);
return null;
}
}
}
protected byte[] serializeAccessToken(OAuth2AccessToken token) {
return SerializationUtils.serialize(token);
}
protected byte[] serializeRefreshToken(OAuth2RefreshToken token) {
return SerializationUtils.serialize(token);
}
protected byte[] serializeAuthentication(OAuth2Authentication authentication) {
return SerializationUtils.serialize(authentication);
}
protected OAuth2AccessToken deserializeAccessToken(byte[] token) {
return SerializationUtils.deserialize(token);
}
protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) {
return SerializationUtils.deserialize(token);
}
protected OAuth2Authentication deserializeAuthentication(byte[] authentication) {
return SerializationUtils.deserialize(authentication);
}
public void setInsertAccessTokenSql(String insertAccessTokenSql) {
this.insertAccessTokenSql = insertAccessTokenSql;
}
public void setSelectAccessTokenSql(String selectAccessTokenSql) {
this.selectAccessTokenSql = selectAccessTokenSql;
}
public void setDeleteAccessTokenSql(String deleteAccessTokenSql) {
this.deleteAccessTokenSql = deleteAccessTokenSql;
}
public void setInsertRefreshTokenSql(String insertRefreshTokenSql) {
this.insertRefreshTokenSql = insertRefreshTokenSql;
}
public void setSelectRefreshTokenSql(String selectRefreshTokenSql) {
this.selectRefreshTokenSql = selectRefreshTokenSql;
}
public void setDeleteRefreshTokenSql(String deleteRefreshTokenSql) {
this.deleteRefreshTokenSql = deleteRefreshTokenSql;
}
public void setSelectAccessTokenAuthenticationSql(String selectAccessTokenAuthenticationSql) {
this.selectAccessTokenAuthenticationSql = selectAccessTokenAuthenticationSql;
}
public void setSelectRefreshTokenAuthenticationSql(String selectRefreshTokenAuthenticationSql) {
this.selectRefreshTokenAuthenticationSql = selectRefreshTokenAuthenticationSql;
}
public void setSelectAccessTokenFromAuthenticationSql(String selectAccessTokenFromAuthenticationSql) {
this.selectAccessTokenFromAuthenticationSql = selectAccessTokenFromAuthenticationSql;
}
public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFromRefreshTokenSql) {
this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql;
}
public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) {
this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql;
}
public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) {
this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql;
}
public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) {
this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql;
}
public JdbcTokenStore(DataSource dataSource) {
Assert.notNull(dataSource, "DataSource required");
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public JdbcTokenStore(JdbcTemplate jdbcTemplate) {
Assert.notNull(jdbcTemplate, "jdbcTemplate required");
this.jdbcTemplate = jdbcTemplate;
}
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
this.authenticationKeyGenerator = authenticationKeyGenerator;
}
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
OAuth2AccessToken accessToken = null;
String key = authenticationKeyGenerator.extractKey(authentication);
try {
accessToken = jdbcTemplate.queryForObject(selectAccessTokenFromAuthenticationSql,
new RowMapper<OAuth2AccessToken>() {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAccessToken(rs.getBytes(2));
}
}, key);
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.debug("Failed to find access token for authentication " + authentication);
}
} catch (IllegalArgumentException e) {
LOG.error("Could not extract access token for authentication " + authentication, e);
}
if (accessToken != null
&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {
removeAccessToken(accessToken.getValue());
// Keep the store consistent (maybe the same user is represented by this
// authentication but the details have
// changed)
storeAccessToken(accessToken, authentication);
}
return accessToken;
}
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
String refreshToken = null;
if (token.getRefreshToken() != null) {
refreshToken = token.getRefreshToken().getValue();
}
if (readAccessToken(token.getValue()) != null) {
removeAccessToken(token.getValue());
}
jdbcTemplate.update(insertAccessTokenSql,
new Object[] { extractTokenKey(token.getValue()), new SqlLobValue(serializeAccessToken(token)),
authenticationKeyGenerator.extractKey(authentication),
authentication.isClientOnly() ? null : authentication.getName(),
authentication.getOAuth2Request().getClientId(),
new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) },
new int[] { Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB,
Types.VARCHAR });
}
public OAuth2AccessToken readAccessToken(String tokenValue) {
OAuth2AccessToken accessToken = null;
try {
accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAccessToken(rs.getBytes(2));
}
}, extractTokenKey(tokenValue));
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + tokenValue);
}
} catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize access token for " + tokenValue, e);
removeAccessToken(tokenValue);
}
return accessToken;
}
public void removeAccessToken(OAuth2AccessToken token) {
removeAccessToken(token.getValue());
}
public void removeAccessToken(String tokenValue) {
jdbcTemplate.update(deleteAccessTokenSql, extractTokenKey(tokenValue));
}
public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
return readAuthentication(token.getValue());
}
public OAuth2Authentication readAuthentication(String token) {
OAuth2Authentication authentication = null;
try {
authentication = jdbcTemplate.queryForObject(selectAccessTokenAuthenticationSql,
new RowMapper<OAuth2Authentication>() {
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAuthentication(rs.getBytes(2));
}
}, extractTokenKey(token));
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + token);
}
} catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize authentication for " + token, e);
removeAccessToken(token);
}
return authentication;
}
public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
jdbcTemplate.update(insertRefreshTokenSql,
new Object[] { extractTokenKey(refreshToken.getValue()),
new SqlLobValue(serializeRefreshToken(refreshToken)),
new SqlLobValue(serializeAuthentication(authentication)) },
new int[] { Types.VARCHAR, Types.BLOB, Types.BLOB });
}
public OAuth2RefreshToken readRefreshToken(String token) {
OAuth2RefreshToken refreshToken = null;
try {
refreshToken = jdbcTemplate.queryForObject(selectRefreshTokenSql, new RowMapper<OAuth2RefreshToken>() {
public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeRefreshToken(rs.getBytes(2));
}
}, extractTokenKey(token));
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find refresh token for token " + token);
}
} catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize refresh token for token " + token, e);
removeRefreshToken(token);
}
return refreshToken;
}
public void removeRefreshToken(OAuth2RefreshToken token) {
removeRefreshToken(token.getValue());
}
public void removeRefreshToken(String token) {
jdbcTemplate.update(deleteRefreshTokenSql, extractTokenKey(token));
}
public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
return readAuthenticationForRefreshToken(token.getValue());
}
public OAuth2Authentication readAuthenticationForRefreshToken(String value) {
OAuth2Authentication authentication = null;
try {
authentication = jdbcTemplate.queryForObject(selectRefreshTokenAuthenticationSql,
new RowMapper<OAuth2Authentication>() {
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
return deserializeAuthentication(rs.getBytes(2));
}
}, extractTokenKey(value));
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + value);
}
} catch (IllegalArgumentException e) {
LOG.warn("Failed to deserialize access token for " + value, e);
removeRefreshToken(value);
}
return authentication;
}
public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
removeAccessTokenUsingRefreshToken(refreshToken.getValue());
}
public void removeAccessTokenUsingRefreshToken(String refreshToken) {
jdbcTemplate.update(deleteAccessTokenFromRefreshTokenSql, new Object[] { extractTokenKey(refreshToken) },
new int[] { Types.VARCHAR });
}
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
try {
accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(),
clientId);
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for clientId " + clientId);
}
}
accessTokens = removeNulls(accessTokens);
return accessTokens;
}
public Collection<OAuth2AccessToken> findTokensByUserName(String userName) {
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
try {
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(),
userName);
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled())
LOG.info("Failed to find access token for userName " + userName);
}
accessTokens = removeNulls(accessTokens);
return accessTokens;
}
public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
try {
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameAndClientIdSql,
new SafeAccessTokenRowMapper(), userName, clientId);
} catch (EmptyResultDataAccessException e) {
if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName);
}
}
accessTokens = removeNulls(accessTokens);
return accessTokens;
}
private List<OAuth2AccessToken> removeNulls(List<OAuth2AccessToken> accessTokens) {
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
for (OAuth2AccessToken token : accessTokens) {
if (token != null) {
tokens.add(token);
}
}
return tokens;
}
protected String extractTokenKey(String value) {
if (value == null) {
return null;
}
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
}
try {
byte[] bytes = digest.digest(value.getBytes("UTF-8"));
return String.format("%032x", new BigInteger(1, bytes));
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
}
}
private final class SafeAccessTokenRowMapper implements RowMapper<OAuth2AccessToken> {
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
try {
return deserializeAccessToken(rs.getBytes(2));
} catch (IllegalArgumentException e) {
String token = rs.getString(1);
jdbcTemplate.update(deleteAccessTokenSql, token);
return null;
}
}
}
protected byte[] serializeAccessToken(OAuth2AccessToken token) {
return SerializationUtils.serialize(token);
}
protected byte[] serializeRefreshToken(OAuth2RefreshToken token) {
return SerializationUtils.serialize(token);
}
protected byte[] serializeAuthentication(OAuth2Authentication authentication) {
return SerializationUtils.serialize(authentication);
}
protected OAuth2AccessToken deserializeAccessToken(byte[] token) {
return SerializationUtils.deserialize(token);
}
protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) {
return SerializationUtils.deserialize(token);
}
protected OAuth2Authentication deserializeAuthentication(byte[] authentication) {
return SerializationUtils.deserialize(authentication);
}
public void setInsertAccessTokenSql(String insertAccessTokenSql) {
this.insertAccessTokenSql = insertAccessTokenSql;
}
public void setSelectAccessTokenSql(String selectAccessTokenSql) {
this.selectAccessTokenSql = selectAccessTokenSql;
}
public void setDeleteAccessTokenSql(String deleteAccessTokenSql) {
this.deleteAccessTokenSql = deleteAccessTokenSql;
}
public void setInsertRefreshTokenSql(String insertRefreshTokenSql) {
this.insertRefreshTokenSql = insertRefreshTokenSql;
}
public void setSelectRefreshTokenSql(String selectRefreshTokenSql) {
this.selectRefreshTokenSql = selectRefreshTokenSql;
}
public void setDeleteRefreshTokenSql(String deleteRefreshTokenSql) {
this.deleteRefreshTokenSql = deleteRefreshTokenSql;
}
public void setSelectAccessTokenAuthenticationSql(String selectAccessTokenAuthenticationSql) {
this.selectAccessTokenAuthenticationSql = selectAccessTokenAuthenticationSql;
}
public void setSelectRefreshTokenAuthenticationSql(String selectRefreshTokenAuthenticationSql) {
this.selectRefreshTokenAuthenticationSql = selectRefreshTokenAuthenticationSql;
}
public void setSelectAccessTokenFromAuthenticationSql(String selectAccessTokenFromAuthenticationSql) {
this.selectAccessTokenFromAuthenticationSql = selectAccessTokenFromAuthenticationSql;
}
public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFromRefreshTokenSql) {
this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql;
}
public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) {
this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql;
}
public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) {
this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql;
}
public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) {
this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql;
}
}

View File

@@ -49,8 +49,9 @@ import org.springframework.security.crypto.codec.Base64;
import org.springframework.util.Assert;
/**
* Helper that translates between JWT encoded token values and OAuth authentication information (in both directions).
* Also acts as a {@link TokenEnhancer} when tokens are granted.
* Helper that translates between JWT encoded token values and OAuth
* authentication information (in both directions). Also acts as a
* {@link TokenEnhancer} when tokens are granted.
*
* @see TokenEnhancer
* @see AccessTokenConverter
@@ -60,219 +61,218 @@ import org.springframework.util.Assert;
*/
public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConverter, InitializingBean {
/**
* Field name for token id.
*/
public static final String TOKEN_ID = AccessTokenConverter.JTI;
/**
* Field name for token id.
*/
public static final String TOKEN_ID = AccessTokenConverter.JTI;
private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class);
private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class);
private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
private JsonParser objectMapper = JsonParserFactory.create();
private JsonParser objectMapper = JsonParserFactory.create();
private String verifierKey = new RandomValueStringGenerator().generate();
private String verifierKey = new RandomValueStringGenerator().generate();
private Signer signer = new MacSigner(verifierKey);
private Signer signer = new MacSigner(verifierKey);
private String signingKey = verifierKey;
private String signingKey = verifierKey;
private SignatureVerifier verifier;
private SignatureVerifier verifier;
/**
* @param tokenConverter the tokenConverter to set
*/
public void setAccessTokenConverter(AccessTokenConverter tokenConverter) {
this.tokenConverter = tokenConverter;
}
/**
* @param tokenConverter the tokenConverter to set
*/
public void setAccessTokenConverter(AccessTokenConverter tokenConverter) {
this.tokenConverter = tokenConverter;
}
/**
* @return the tokenConverter in use
*/
public AccessTokenConverter getAccessTokenConverter() {
return tokenConverter;
}
/**
* @return the tokenConverter in use
*/
public AccessTokenConverter getAccessTokenConverter() {
return tokenConverter;
}
@Override
public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
return tokenConverter.convertAccessToken(token, authentication);
}
@Override
public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
return tokenConverter.convertAccessToken(token, authentication);
}
@Override
public OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map) {
return tokenConverter.extractAccessToken(value, map);
}
@Override
public OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map) {
return tokenConverter.extractAccessToken(value, map);
}
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
return tokenConverter.extractAuthentication(map);
}
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
return tokenConverter.extractAuthentication(map);
}
/**
* Get the verification key for the token signatures.
*
* @return the key used to verify tokens
*/
public Map<String, String> getKey() {
Map<String, String> result = new LinkedHashMap<String, String>();
result.put("alg", signer.algorithm());
result.put("value", verifierKey);
return result;
}
/**
* Get the verification key for the token signatures.
*
* @return the key used to verify tokens
*/
public Map<String, String> getKey() {
Map<String, String> result = new LinkedHashMap<String, String>();
result.put("alg", signer.algorithm());
result.put("value", verifierKey);
return result;
}
public void setKeyPair(KeyPair keyPair) {
PrivateKey privateKey = keyPair.getPrivate();
Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA ");
signer = new RsaSigner((RSAPrivateKey) privateKey);
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
verifier = new RsaVerifier(publicKey);
verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded())) + "\n-----END PUBLIC KEY-----";
}
/**
* Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format,
* as produced by <tt>ssh-keygen</tt>.
*
* @param key the key to be used for signing JWTs.
*/
public void setSigningKey(String key) {
Assert.hasText(key);
key = key.trim();
public void setKeyPair(KeyPair keyPair) {
PrivateKey privateKey = keyPair.getPrivate();
Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA ");
signer = new RsaSigner((RSAPrivateKey) privateKey);
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
verifier = new RsaVerifier(publicKey);
verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded()))
+ "\n-----END PUBLIC KEY-----";
}
this.signingKey = key;
/**
* Sets the JWT signing key. It can be either a simple MAC key or an RSA key.
* RSA keys should be in OpenSSH format, as produced by <tt>ssh-keygen</tt>.
*
* @param key the key to be used for signing JWTs.
*/
public void setSigningKey(String key) {
Assert.hasText(key);
key = key.trim();
if (isPublic(key)) {
signer = new RsaSigner(key);
logger.info("Configured with RSA signing key");
}
else {
// Assume it's a MAC key
this.verifierKey = key;
signer = new MacSigner(key);
}
}
this.signingKey = key;
/**
* @return true if the key has a public verifier
*/
private boolean isPublic(String key) {
return key.startsWith("-----BEGIN");
}
/**
* @return true if the signing key is a public key
*/
public boolean isPublic() {
return signer instanceof RsaSigner;
}
if (isPublic(key)) {
signer = new RsaSigner(key);
logger.info("Configured with RSA signing key");
} else {
// Assume it's a MAC key
this.verifierKey = key;
signer = new MacSigner(key);
}
}
/**
* The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint
* to allow resource servers to obtain the key.
*
* For an HMAC key it will be the same value as the signing key and does not need to be set. For and RSA key, it
* should be set to the String representation of the public key, in a standard format (e.g. OpenSSH keys)
*
* @param key the signature verification key (typically an RSA public key)
*/
public void setVerifierKey(String key) {
this.verifierKey = key;
try {
new RsaSigner(verifierKey);
throw new IllegalArgumentException("Private key cannot be set as verifierKey property");
}
catch (Exception expected) {
// Expected
}
}
/**
* @return true if the key has a public verifier
*/
private boolean isPublic(String key) {
return key.startsWith("-----BEGIN");
}
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
Map<String, Object> info = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
String tokenId = result.getValue();
if (!info.containsKey(TOKEN_ID)) {
info.put(TOKEN_ID, tokenId);
}
result.setAdditionalInformation(info);
result.setValue(encode(result, authentication));
OAuth2RefreshToken refreshToken = result.getRefreshToken();
if (refreshToken != null) {
DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken);
encodedRefreshToken.setValue(refreshToken.getValue());
Map<String, Object> refreshTokenInfo = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue());
encodedRefreshToken.setAdditionalInformation(refreshTokenInfo);
DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode(encodedRefreshToken, authentication));
if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration();
encodedRefreshToken.setExpiration(expiration);
token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, authentication), expiration);
}
result.setRefreshToken(token);
}
return result;
}
/**
* @return true if the signing key is a public key
*/
public boolean isPublic() {
return signer instanceof RsaSigner;
}
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String content;
try {
content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication));
}
catch (Exception e) {
throw new IllegalStateException("Cannot convert access token to JSON", e);
}
String token = JwtHelper.encode(content, signer).getEncoded();
return token;
}
/**
* The key used for verifying signatures produced by this class. This is not
* used but is returned from the endpoint to allow resource servers to obtain
* the key.
*
* For an HMAC key it will be the same value as the signing key and does not
* need to be set. For and RSA key, it should be set to the String
* representation of the public key, in a standard format (e.g. OpenSSH keys)
*
* @param key the signature verification key (typically an RSA public key)
*/
public void setVerifierKey(String key) {
this.verifierKey = key;
try {
new RsaSigner(verifierKey);
throw new IllegalArgumentException("Private key cannot be set as verifierKey property");
} catch (Exception expected) {
// Expected
}
}
protected Map<String, Object> decode(String token) {
try {
Jwt jwt = JwtHelper.decodeAndVerify(token, verifier);
String content = jwt.getClaims();
Map<String, Object> map = objectMapper.parseMap(content);
if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
Integer intValue = (Integer) map.get(EXP);
map.put(EXP, new Long(intValue));
}
return map;
}
catch (Exception e) {
throw new InvalidTokenException("Cannot convert access token to JSON", e);
}
}
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
Map<String, Object> info = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
String tokenId = result.getValue();
if (!info.containsKey(TOKEN_ID)) {
info.put(TOKEN_ID, tokenId);
}
result.setAdditionalInformation(info);
result.setValue(encode(result, authentication));
OAuth2RefreshToken refreshToken = result.getRefreshToken();
if (refreshToken != null) {
DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken);
encodedRefreshToken.setValue(refreshToken.getValue());
Map<String, Object> refreshTokenInfo = new LinkedHashMap<String, Object>(
accessToken.getAdditionalInformation());
refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue());
encodedRefreshToken.setAdditionalInformation(refreshTokenInfo);
DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(
encode(encodedRefreshToken, authentication));
if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration();
encodedRefreshToken.setExpiration(expiration);
token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, authentication), expiration);
}
result.setRefreshToken(token);
}
return result;
}
public void afterPropertiesSet() throws Exception {
// Check the signing and verification keys match
if (signer instanceof RsaSigner) {
RsaVerifier verifier;
try {
verifier = new RsaVerifier(verifierKey);
}
catch (Exception e) {
logger.warn("Unable to create an RSA verifier from verifierKey");
return;
}
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String content;
try {
content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication));
} catch (Exception e) {
throw new IllegalStateException("Cannot convert access token to JSON", e);
}
String token = JwtHelper.encode(content, signer).getEncoded();
return token;
}
byte[] test = "test".getBytes();
try {
verifier.verify(test, signer.sign(test));
logger.info("Signing and verification RSA keys match");
}
catch (InvalidSignatureException e) {
logger.error("Signing and verification RSA keys do not match");
}
}
else {
// Avoid a race condition where setters are called in the wrong order. Use of == is intentional.
Assert.state(this.signingKey == this.verifierKey,
"For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key");
}
SignatureVerifier verifier = new MacSigner(verifierKey);
try {
verifier = new RsaVerifier(verifierKey);
}
catch (Exception e) {
logger.warn("Unable to create an RSA verifier from verifierKey");
}
this.verifier = verifier;
}
protected Map<String, Object> decode(String token) {
try {
Jwt jwt = JwtHelper.decodeAndVerify(token, verifier);
String content = jwt.getClaims();
Map<String, Object> map = objectMapper.parseMap(content);
if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
Integer intValue = (Integer) map.get(EXP);
map.put(EXP, new Long(intValue));
}
return map;
} catch (Exception e) {
throw new InvalidTokenException("Cannot convert access token to JSON", e);
}
}
public void afterPropertiesSet() throws Exception {
// Check the signing and verification keys match
if (signer instanceof RsaSigner) {
RsaVerifier verifier;
try {
verifier = new RsaVerifier(verifierKey);
} catch (Exception e) {
logger.warn("Unable to create an RSA verifier from verifierKey");
return;
}
byte[] test = "test".getBytes();
try {
verifier.verify(test, signer.sign(test));
logger.info("Signing and verification RSA keys match");
} catch (InvalidSignatureException e) {
logger.error("Signing and verification RSA keys do not match");
}
} else {
// Avoid a race condition where setters are called in the wrong order. Use of ==
// is intentional.
Assert.state(this.signingKey == this.verifierKey,
"For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key");
}
SignatureVerifier verifier = new MacSigner(verifierKey);
try {
verifier = new RsaVerifier(verifierKey);
} catch (Exception e) {
logger.warn("Unable to create an RSA verifier from verifierKey");
}
this.verifier = verifier;
}
}