/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.chemistry.opencmis.server.impl.browser.token; import java.net.URL; import java.security.SecureRandom; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; public class SimpleTokenHandlerSessionHelper { public static final String ATTR_CMIS_USER = "cmis-token.user"; public static final String ATTR_CMIS_AUTH_TIMESTAMP = "cmis-token.timestamp"; public static final String ATTR_CMIS_TOKEN = "cmis-token.token"; public static final String ATTR_CMIS_LOGIN_KEY = "cmis-token.token.loginkey"; public static final String ATTR_CMIS_FORM_KEY = "cmis-token.formkey"; public static final String ATTR_CMIS_APP_URL = "cmis-token.appurl"; public static final String ATTR_CMIS_APP_KEY = "cmis-token.appkey"; public static final String ATTR_SEPARATOR = "\n"; public static final String PARAM_KEY = "key"; public static final String PARAM_TOKEN = "token"; public static final String PARAM_URL = "url"; public static final String PARAM_USER = "user"; public static final String PARAM_PASSWORD = "password"; public static final String PARAM_TRUSTAPP = "trustapp"; public static final int APP_ID_BYTES = 10; public static final int APP_ID_LENGTH = APP_ID_BYTES * 2; public static final int KEY_BYTES = 20; public static final int KEY_LENGTH = KEY_BYTES * 2; public static String getApplicationIdFromKey(String key) { if (key == null || key.length() != APP_ID_LENGTH + KEY_LENGTH) { return null; } return key.substring(0, APP_ID_LENGTH); } public static String getLoginKey(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return null; } return (String) hs.getAttribute(ATTR_CMIS_LOGIN_KEY + appId); } public static void setLoginKey(HttpServletRequest request, String loginKey, String formKey, URL appURL) { HttpSession hs = request.getSession(); String appId = getApplicationIdFromKey(loginKey); hs.setAttribute(ATTR_CMIS_LOGIN_KEY + appId, loginKey); hs.setAttribute(ATTR_CMIS_FORM_KEY + appId, formKey); hs.setAttribute(ATTR_CMIS_APP_URL + appId, appURL); } public static boolean checkLoginKey(HttpServletRequest request) { HttpSession hs = request.getSession(false); if (hs == null) { return false; } String key = getKey(request); if (key == null) { return false; } String appId = getApplicationIdFromKey(key); if (appId == null) { return false; } return key.equals(hs.getAttribute(ATTR_CMIS_LOGIN_KEY + appId)); } public static void removeLoginKey(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return; } hs.removeAttribute(ATTR_CMIS_LOGIN_KEY + appId); } public static boolean checkFormKey(HttpServletRequest request) { HttpSession hs = request.getSession(false); if (hs == null) { return false; } String formKey = getKey(request); if (formKey == null) { return false; } String appId = getApplicationIdFromKey(formKey); if (appId == null) { return false; } return formKey.equals(hs.getAttribute(ATTR_CMIS_FORM_KEY + appId)); } public static void removeFormKey(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return; } hs.removeAttribute(ATTR_CMIS_FORM_KEY + appId); } public static String getUser(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return null; } return (String) hs.getAttribute(ATTR_CMIS_USER + appId); } public static void setUser(HttpServletRequest request, String appId, String user) { HttpSession hs = request.getSession(false); if (hs == null) { return; } hs.setAttribute(ATTR_CMIS_USER + appId, user); hs.setAttribute(ATTR_CMIS_AUTH_TIMESTAMP + appId, System.currentTimeMillis()); } public static String getApplicationKey(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return null; } return (String) hs.getAttribute(ATTR_CMIS_APP_KEY + appId); } public static void setApplicationKey(HttpServletRequest request, String key) { HttpSession hs = request.getSession(); String appId = getApplicationIdFromKey(key); hs.setAttribute(ATTR_CMIS_APP_KEY + appId, key); } public static boolean checkApplicationKey(HttpServletRequest request) { HttpSession hs = request.getSession(false); if (hs == null) { return false; } String key = getKey(request); if (key == null) { return false; } String appId = getApplicationIdFromKey(key); if (appId == null) { return false; } return key.equals(hs.getAttribute(ATTR_CMIS_APP_KEY + appId)); } public static void removeApplicationKey(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return; } hs.removeAttribute(ATTR_CMIS_APP_KEY + appId); hs.removeAttribute(ATTR_CMIS_APP_URL + appId); hs.removeAttribute(ATTR_CMIS_USER + appId); hs.removeAttribute(ATTR_CMIS_AUTH_TIMESTAMP + appId); } public static URL getApplicationURL(HttpServletRequest request, String appId) { HttpSession hs = request.getSession(false); if (hs == null) { return null; } return (URL) hs.getAttribute(ATTR_CMIS_APP_URL + appId); } /** * Retrieves the token from the requests and tests if this token belongs to * the current session. If the token is associated with the session, the * token will be removed from the session and cannot be reused again. * * @return <code>true</code> if the request contains a token and this token * belongs to the session, <code>false</code> otherwise */ public static boolean testAndInvalidateToken(HttpServletRequest request) { HttpSession hs = request.getSession(false); if (hs == null) { return false; } String token = getToken(request); if (token == null) { return false; } String tokenKey = ATTR_CMIS_TOKEN + token; Long tokenCreationTimestamp = (Long) hs.getAttribute(tokenKey); if (tokenCreationTimestamp != null) { // if the token exists, remove it hs.removeAttribute(tokenKey); // PARANOIA: don't accept tokens that are older than 8 hours return System.currentTimeMillis() - tokenCreationTimestamp < 8 * 60 * 60 * 1000; } return false; } /** * Adds a token to the session. */ public static void addToken(HttpServletRequest request, String token) { HttpSession hs = request.getSession(); String tokenKey = ATTR_CMIS_TOKEN + token; // set the token and retain creation timestamp hs.setAttribute(tokenKey, System.currentTimeMillis()); } /** * Gets the key parameter from the request and checks its validity. */ public static String getKey(HttpServletRequest request) { String key = request.getParameter(PARAM_KEY); return normalizeKey(key); } /** * Gets the domain parameter from the request and checks its validity. */ public static String getToken(HttpServletRequest request) { String token = request.getParameter(PARAM_TOKEN); return normalizeKey(token); } public static String normalizeKey(String key) { if (key == null) { return null; } key = key.trim(); if (key.length() != APP_ID_LENGTH + KEY_LENGTH || !key.matches("^[0-9a-f]+$")) { return null; } return key; } public static String generateAppId() { SecureRandom random = new SecureRandom(); byte[] bytes = new byte[APP_ID_BYTES]; random.nextBytes(bytes); StringBuilder sb = new StringBuilder(APP_ID_BYTES * 2); for (byte b : bytes) { String s = Integer.toHexString(b & 0xff); if (s.length() < 2) { sb.append('0'); } sb.append(s); } return sb.toString(); } public static String generateKey(String appId) { SecureRandom random = new SecureRandom(); byte[] bytes = new byte[KEY_BYTES]; random.nextBytes(bytes); StringBuilder sb = new StringBuilder(appId + KEY_BYTES * 2); for (byte b : bytes) { String s = Integer.toHexString(b & 0xff); if (s.length() < 2) { sb.append('0'); } sb.append(s); } return sb.toString(); } }