/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.core.manager.impl;
import java.security.SecureRandom;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.orcid.core.manager.InternalSSOManager;
import org.orcid.core.utils.JsonUtils;
import org.orcid.persistence.dao.InternalSSODao;
import org.orcid.persistence.jpa.entities.InternalSSOEntity;
import org.orcid.pojo.ajaxForm.PojoUtil;
import org.springframework.beans.factory.annotation.Value;
public class InternalSSOManagerImpl implements InternalSSOManager {
@Value("${org.orcid.core.soo.token.validity_minutes:10}")
private int maxAgeMinutes;
@Value("${org.orcid.security.cookie.allowed_domain:.orcid.org}")
private String allowedDomain;
@Resource
InternalSSODao internalSSODao;
public InternalSSOManagerImpl() {
}
public InternalSSOManagerImpl(int maxAgeInMunutes) {
this.maxAgeMinutes = maxAgeInMunutes;
}
@Override
public void writeCookie(String orcid, HttpServletRequest request, HttpServletResponse response) {
// Deletes previous cookie if exists
deleteToken(orcid, request, response);
//Generate the token
String token = generateAndStoreToken(orcid);
//Save the cookie in the response
populateCookie(orcid, token, request, response);
}
private void populateCookie(String orcid, String token, HttpServletRequest request, HttpServletResponse response) {
HashMap<String, String> cookieValues = new HashMap<String, String>();
cookieValues.put(COOKIE_KEY_ORCID, orcid);
cookieValues.put(COOKIE_KEY_TOKEN, token);
String jsonCookie = JsonUtils.convertToJsonString(cookieValues);
// Return it as a cookie in the response
Cookie tokenCookie = new Cookie(COOKIE_NAME, jsonCookie);
tokenCookie.setMaxAge(maxAgeMinutes * 60);
tokenCookie.setPath("/");
tokenCookie.setSecure(true);
tokenCookie.setHttpOnly(true);
tokenCookie.setDomain(allowedDomain.trim());
response.addCookie(tokenCookie);
}
private String generateAndStoreToken(String orcid) {
// Generate a random token
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[16];
random.nextBytes(bytes);
byte[] encoded = Base64.encodeBase64(bytes);
String token = new String(encoded);
// Insert it into the DB
internalSSODao.insert(orcid, token);
return token;
}
@SuppressWarnings("unchecked")
@Override
public void updateCookie(String orcid, HttpServletRequest request, HttpServletResponse response) {
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals(COOKIE_NAME)) {
HashMap<String, String> cookieValues = JsonUtils.readObjectFromJsonString(cookie.getValue(), HashMap.class);
if(cookieValues.containsKey(COOKIE_KEY_TOKEN)) {
if (internalSSODao.update(orcid, cookieValues.get(COOKIE_KEY_TOKEN))) {
//Create new cookie
Cookie tokenCookie = new Cookie(COOKIE_NAME, cookie.getValue());
tokenCookie.setMaxAge(maxAgeMinutes * 60);
tokenCookie.setPath("/");
tokenCookie.setSecure(true);
tokenCookie.setHttpOnly(true);
tokenCookie.setDomain(allowedDomain.trim());
//Add new cookie to response
response.addCookie(tokenCookie);
}
}
break;
}
}
}
}
@Override
public void getAndUpdateCookie(String orcid, HttpServletRequest request, HttpServletResponse response) {
InternalSSOEntity existingCookie = internalSSODao.find(orcid);
if(existingCookie != null) {
internalSSODao.update(existingCookie.getId(), existingCookie.getToken());
HashMap<String, String> cookieValues = new HashMap<String, String>();
cookieValues.put(COOKIE_KEY_ORCID, orcid);
cookieValues.put(COOKIE_KEY_TOKEN, existingCookie.getToken());
String jsonCookie = JsonUtils.convertToJsonString(cookieValues);
Cookie tokenCookie = new Cookie(COOKIE_NAME, jsonCookie);
tokenCookie.setMaxAge(maxAgeMinutes * 60);
tokenCookie.setPath("/");
tokenCookie.setSecure(true);
tokenCookie.setHttpOnly(true);
tokenCookie.setDomain(allowedDomain.trim());
//Add new cookie to response
response.addCookie(tokenCookie);
}
}
@Override
public void deleteToken(String orcid) {
if(!PojoUtil.isEmpty(orcid)) {
// Delete the token from DB
internalSSODao.delete(orcid);
}
}
@Override
public void deleteToken(String orcid, HttpServletRequest request, HttpServletResponse response) {
this.deleteToken(orcid);
// Delete the cookie
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals(COOKIE_NAME)) {
cookie.setMaxAge(0);
cookie.setValue(StringUtils.EMPTY);
cookie.setSecure(true);
cookie.setHttpOnly(true);
cookie.setDomain(allowedDomain.trim());
response.addCookie(cookie);
}
}
}
}
@SuppressWarnings("unchecked")
@Override
public boolean verifyToken(String orcid, String cookie) {
HashMap<String, String> cookieValues = JsonUtils.readObjectFromJsonString(cookie, HashMap.class);
if(!cookieValues.containsKey(COOKIE_KEY_TOKEN)) {
return false;
}
Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, -maxAgeMinutes);
Date maxAge = c.getTime();
return internalSSODao.verify(orcid, cookieValues.get(COOKIE_KEY_TOKEN), maxAge);
}
@Override
public boolean enableCookie() {
return !allowedDomain.equals("localhost");
}
}