Sunday, July 28, 2013

Store OAuth 10a token in the database

1. Create a token table as below
 This is how you do in mysql
CREATE TABLE `token` (
 `id` int(10) NOT NULL AUTO_INCREMENT,
 `consumer_id` int(10) NOT NULL,
 `public_key` varchar(255) DEFAULT NULL,
 `private_key` varchar(255) DEFAULT NULL,
 `created_date` timestamp NULL DEFAULT NULL,
 `callback_url` varchar(255) DEFAULT NULL,
 `verifier` varchar(255) DEFAULT NULL,
 `access_token` int(2) DEFAULT NULL,
 `authentication` blob,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

2. Write a custom JDBC token service class
public class CustomTokenService {
private TokenDao tokenDao;

public CustomTokenService(TokenDao tokenDao) {
this.tokenDao = tokenDao;
}

public OAuthProviderTokenImpl readToken(String token) {
List<Token> sessionList = tokenDao.getNamedQueryAndNamedParam("Token.findById", "id", token);
Token session = sessionList.get(0);
for (Token t : sessionList) {
if (t.getIsActive() == 1) {
session = t;
}
}
session.setLastAccessedDate(new Date());
tokenDao.saveOrUpdate(session);
OAuthProviderTokenImpl accessToken = createOAuthProviderToken(session);
return accessToken;
}

public void storeToken(String tokenValue, OAuthProviderTokenImpl token) {         // Token class is orm of token table
Token customToken = new Token();
customToken.setCreatedDate(new Date());

Authentication userAuthentication = token.getUserAuthentication();
if (userAuthentication != null) {
byte[] authSerialized = serializeAuthentication(userAuthentication);
customToken.setUserAuthentication(authSerialized);
}

String consumerKey = token.getConsumerKey();
// need to create a consumer object
customToken.setConsumerId(consumer);
customToken.setSessionId(token.getValue());
String callbackUrl = token.getCallbackUrl();
String verifier = token.getVerifier();
customToken.setCallbackUrl(callbackUrl);
customToken.setVerifier(verifier);
customToken.setPrivateKey(token.getSecret());
customToken.setPublicKey(token.getValue());

Integer accessToken = token.isAccessToken() ? 1 : 0;
customToken.setAccessToken(accessToken);
tokenDao.saveOrUpdate(customToken);
}

public OAuthProviderTokenImpl removeToken(String tokenValue) {
// remove or null from the database and return the object
tokenDao.saveOrUpdate(token);
OAuthProviderTokenImpl tokenImpl = createOAuthProviderToken(token);
return tokenImpl;
}

private OAuthProviderTokenImpl createOAuthProviderToken(Token findById) {
OAuthProviderTokenImpl token = new OAuthProviderTokenImpl();
if (findById.getUserAuthentication() != null) {
Authentication userAuthentication = deserializeAuthentication(findById
.getUserAuthentication());
token.setUserAuthentication(userAuthentication);
}
//create the consumer key
token.setConsumerKey(consumerKey);
boolean accessToken = false;
if (findById.getAccessToken() == 1) {
accessToken = true;
}
token.setAccessToken(accessToken);
token.setSecret(findById.getPrivateKey());
token.setValue(findById.getPublicKey());
token.setCallbackUrl(findById.getCallbackUrl());
token.setVerifier(findById.getVerifier());
return token;
}

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[] serializeAuthentication(Authentication authentication) {
return SerializationUtils.serialize(authentication);
}

protected Authentication deserializeAuthentication(byte[] authentication) {
return (Authentication) SerializationUtils.deserialize(authentication);
}
}

3. Write Custom OAuth Token Service
public class CustomOAuthTokenService extends RandomValueProviderTokenServices{

CustomTokenService customTokenService;
protected final ConcurrentHashMap<String, OAuthProviderTokenImpl> tokenStore = new ConcurrentHashMap<String, OAuthProviderTokenImpl>();

public CustomOAuthTokenService(CustomTokenService customTokenService) {
super();
this.customTokenService = customTokenService;
}

@Override
protected OAuthProviderTokenImpl readToken(String token) {
OAuthProviderTokenImpl readToken = customTokenService.readToken(token);
return readToken;
}

@Override
protected void storeToken(String tokenValue, OAuthProviderTokenImpl token) {
customTokenService.storeToken(tokenValue, token);
}

@Override
protected OAuthProviderTokenImpl removeToken(String tokenValue) {
return customTokenService.removeToken(tokenValue);
}

}

4. Changes to Spring security config file

<beans:bean id="tokenServices" class="....CustomOAuthTokenService">
<beans:constructor-arg ref="customTokenService" />
</beans:bean>

<beans:bean id="customTokenService" class=".....CustomTokenService">
<beans:constructor-arg>
<beans:ref bean="tokenDao" />
</beans:constructor-arg>
</beans:bean>