Commit 52b9bdaf authored by Matija Obreza's avatar Matija Obreza
Browse files

JPA Token store

parent ba61c42a
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
package org.genesys2.server.model.oauth; package org.genesys2.server.model.oauth;
import java.sql.Blob;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
...@@ -39,7 +37,7 @@ public class OAuthAccessToken implements HibernateModel { ...@@ -39,7 +37,7 @@ public class OAuthAccessToken implements HibernateModel {
@Lob @Lob
@Column(name = "token") @Column(name = "token")
private Blob token; private byte[] token;
@Column(name = "authentication_id") @Column(name = "authentication_id")
private String authenticationId; private String authenticationId;
...@@ -52,7 +50,7 @@ public class OAuthAccessToken implements HibernateModel { ...@@ -52,7 +50,7 @@ public class OAuthAccessToken implements HibernateModel {
@Lob @Lob
@Column(name = "authentication") @Column(name = "authentication")
private Blob authentication; private byte[] authentication;
@Column(name = "refresh_token") @Column(name = "refresh_token")
private String refreshToken; private String refreshToken;
...@@ -65,11 +63,11 @@ public class OAuthAccessToken implements HibernateModel { ...@@ -65,11 +63,11 @@ public class OAuthAccessToken implements HibernateModel {
this.tokenId = tokenId; this.tokenId = tokenId;
} }
public Blob getToken() { public byte[] getToken() {
return token; return token;
} }
public void setToken(Blob token) { public void setToken(byte[] token) {
this.token = token; this.token = token;
} }
...@@ -97,11 +95,11 @@ public class OAuthAccessToken implements HibernateModel { ...@@ -97,11 +95,11 @@ public class OAuthAccessToken implements HibernateModel {
this.clientId = clientId; this.clientId = clientId;
} }
public Blob getAuthentication() { public byte[] getAuthentication() {
return authentication; return authentication;
} }
public void setAuthentication(Blob authentication) { public void setAuthentication(byte[] authentication) {
this.authentication = authentication; this.authentication = authentication;
} }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.genesys2.server.model.oauth; package org.genesys2.server.model.oauth;
import java.sql.Blob;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
...@@ -37,11 +35,11 @@ public class OAuthRefreshToken implements HibernateModel { ...@@ -37,11 +35,11 @@ public class OAuthRefreshToken implements HibernateModel {
@Lob @Lob
@Column(name = "token") @Column(name = "token")
private Blob token; private byte[] token;
@Lob @Lob
@Column(name = "authentication") @Column(name = "authentication")
private Blob authentication; private byte[] authentication;
public String getTokenId() { public String getTokenId() {
return tokenId; return tokenId;
...@@ -51,19 +49,19 @@ public class OAuthRefreshToken implements HibernateModel { ...@@ -51,19 +49,19 @@ public class OAuthRefreshToken implements HibernateModel {
this.tokenId = tokenId; this.tokenId = tokenId;
} }
public Blob getToken() { public byte[] getToken() {
return token; return token;
} }
public void setToken(Blob token) { public void setToken(byte[] bs) {
this.token = token; this.token = bs;
} }
public Blob getAuthentication() { public byte[] getAuthentication() {
return authentication; return authentication;
} }
public void setAuthentication(Blob authentication) { public void setAuthentication(byte[] authentication) {
this.authentication = authentication; this.authentication = authentication;
} }
......
...@@ -20,7 +20,8 @@ import java.util.Collection; ...@@ -20,7 +20,8 @@ import java.util.Collection;
import org.genesys2.server.model.oauth.OAuthAccessToken; import org.genesys2.server.model.oauth.OAuthAccessToken;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@Transactional @Transactional
...@@ -28,6 +29,11 @@ public interface OAuthAccessTokenPersistence extends JpaRepository<OAuthAccessTo ...@@ -28,6 +29,11 @@ public interface OAuthAccessTokenPersistence extends JpaRepository<OAuthAccessTo
Collection<OAuthAccessToken> findByClientId(String clientId); Collection<OAuthAccessToken> findByClientId(String clientId);
Collection<OAuth2AccessToken> findByUserName(String username); Collection<OAuthAccessToken> findByUserName(String username);
OAuthAccessToken findByAuthenticationId(String authenticationId);
@Query("delete from OAuthAccessToken where refreshToken = ?1")
@Modifying
void deleteByRefreshToken(String value);
} }
/**
* Copyright 2013 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.server.service.impl;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.oauth.OAuthAccessToken;
import org.genesys2.server.model.oauth.OAuthRefreshToken;
import org.genesys2.server.persistence.domain.OAuthAccessTokenPersistence;
import org.genesys2.server.persistence.domain.OAuthRefreshTokenPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.common.util.SerializationUtils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* OAuth2JPATokenStoreImpl based on JdbcTokenStore
*
* Original authors of JdbcTokenStore:
* @author Ken Dombeck
* @author Luke Taylor
* @author Dave Syer
*
* JPA:
* @author Matija Obreza
*/
@Service("tokenStore")
@Transactional
public class OAuth2JPATokenStoreImpl implements TokenStore {
private static final Log LOG = LogFactory.getLog(OAuth2JPATokenStoreImpl.class);
@Autowired
private OAuthAccessTokenPersistence accessTokenPersistence;
@Autowired
private OAuthRefreshTokenPersistence refreshTokenPersistence;
private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
this.authenticationKeyGenerator = authenticationKeyGenerator;
}
@Override
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
for (OAuthAccessToken token : accessTokenPersistence.findByClientId(clientId)) {
if (token != null) {
tokens.add(deserializeAccessToken(token.getToken()));
}
}
return tokens;
}
@Override
public Collection<OAuth2AccessToken> findTokensByUserName(String username) {
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
for (OAuthAccessToken token : accessTokenPersistence.findByUserName(username)) {
if (token != null) {
tokens.add(deserializeAccessToken(token.getToken()));
}
}
return tokens;
}
@Override
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
OAuth2AccessToken accessToken = null;
String key = authenticationKeyGenerator.extractKey(authentication);
try {
OAuthAccessToken persisted = accessTokenPersistence.findByAuthenticationId(key);
accessToken = deserializeAccessToken(persisted.getToken());
} catch (NullPointerException 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);
}
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;
}
@Override
public OAuth2AccessToken readAccessToken(String tokenValue) {
OAuth2AccessToken accessToken = null;
try {
OAuthAccessToken persisted = accessTokenPersistence.findOne(extractTokenKey(tokenValue));
accessToken = deserializeAccessToken(persisted.getToken());
} catch (NullPointerException 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);
removeAccessToken(tokenValue);
}
return accessToken;
}
@Override
public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
return readAuthentication(token.getValue());
}
@Override
public OAuth2Authentication readAuthentication(String token) {
OAuth2Authentication authentication = null;
try {
OAuthAccessToken persisted = accessTokenPersistence.findOne(extractTokenKey(token));
authentication = deserializeAuthentication(persisted.getAuthentication());
} catch (NullPointerException 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);
removeAccessToken(token);
}
return authentication;
}
@Override
public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
return readAuthenticationForRefreshToken(token.getValue());
}
public OAuth2Authentication readAuthenticationForRefreshToken(String value) {
OAuth2Authentication authentication = null;
try {
OAuthRefreshToken persisted = refreshTokenPersistence.findOne(extractTokenKey(value));
authentication = deserializeAuthentication(persisted.getAuthentication());
} catch (NullPointerException 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);
removeRefreshToken(value);
}
return authentication;
}
@Override
public OAuth2RefreshToken readRefreshToken(String token) {
OAuth2RefreshToken refreshToken = null;
try {
OAuthRefreshToken persisted = refreshTokenPersistence.findOne(extractTokenKey(token));
refreshToken = deserializeRefreshToken(persisted.getToken());
} catch (NullPointerException 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);
removeRefreshToken(token);
}
return refreshToken;
}
@Override
public void removeAccessToken(OAuth2AccessToken token) {
removeAccessToken(token.getValue());
}
private void removeAccessToken(String tokenId) {
accessTokenPersistence.delete(tokenId);
}
@Override
public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
accessTokenPersistence.deleteByRefreshToken(refreshToken.getValue());
}
@Override
public void removeRefreshToken(OAuth2RefreshToken token) {
removeRefreshToken(token.getValue());
}
private void removeRefreshToken(String tokenId) {
refreshTokenPersistence.delete(tokenId);
}
@Override
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
LOG.info("Storing new access token");
String refreshToken = null;
if (token.getRefreshToken() != null) {
refreshToken = token.getRefreshToken().getValue();
}
OAuthAccessToken persisted = new OAuthAccessToken();
persisted.setTokenId(extractTokenKey(token.getValue()));
persisted.setToken(serializeAccessToken(token));
persisted.setAuthenticationId(authenticationKeyGenerator.extractKey(authentication));
persisted.setUserName(authentication.isClientOnly() ? null : authentication.getName());
persisted.setClientId(authentication.getAuthorizationRequest().getClientId());
persisted.setAuthentication(serializeAuthentication(authentication));
persisted.setRefreshToken(extractTokenKey(refreshToken));
accessTokenPersistence.save(persisted);
}
@Override
public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
LOG.info("Storing new refresh token");
OAuthRefreshToken persisted = new OAuthRefreshToken();
persisted.setTokenId(extractTokenKey(refreshToken.getValue()));
persisted.setToken(serializeRefreshToken(refreshToken));
persisted.setAuthentication(serializeAuthentication(authentication));
refreshTokenPersistence.save(persisted);
}
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).");
}
}
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);
}
}
/**
* Copyright 2013 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.model.oauth.OAuthAccessToken;
import org.genesys2.server.model.oauth.OAuthClientDetails;
import org.genesys2.server.persistence.domain.OAuthAccessTokenPersistence;
import org.genesys2.server.persistence.domain.OAuthClientDetailsPersistence;
import org.genesys2.server.service.OAuth2ClientDetailsService;
import org.genesys2.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.provider.ClientAlreadyExistsException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
//@Service("tokenStore")
//@Transactional
public class OAuth2TokenStoreImpl implements TokenStore {
private static final Log logger = LogFactory.getLog(OAuth2TokenStoreImpl.class);
@Autowired
private OAuthClientDetailsPersistence clientDetailsPersistence;
@Autowired
private OAuthAccessTokenPersistence accessTokenPersistence;
@Autowired
private UserService userService;
private PasswordEncoder passwordEncoder = NoOpPasswordEncoder.getInstance();
/**
* @param passwordEncoder
* the password encoder to set
*/
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Override
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
// return accessTokenPersistence.findByClientId(clientId)
return null;
}
@Override
public Collection<OAuth2AccessToken> findTokensByUserName(String username) {
User user = userService.getUserByEmail(username);
return accessTokenPersistence.findByUser(user);
}
@Override
public OAuth2AccessToken getAccessToken(OAuth2Authentication arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public OAuth2AccessToken readAccessToken(String arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public OAuth2Authentication readAuthentication(OAuth2AccessToken arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public OAuth2Authentication readAuthentication(String arg0) {
// TODO Auto-generated method stub
return null;
}