001/* 002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Antoine Taillefer 018 */ 019package org.nuxeo.ecm.platform.ui.web.auth.token; 020 021import java.util.List; 022import java.util.Map; 023 024import javax.servlet.http.Cookie; 025import javax.servlet.http.HttpServletRequest; 026import javax.servlet.http.HttpServletResponse; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.ecm.platform.api.login.UserIdentificationInfo; 031import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPlugin; 032import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPluginLogoutExtension; 033import org.nuxeo.ecm.platform.usermanager.UserManager; 034import org.nuxeo.ecm.platform.web.common.CookieHelper; 035import org.nuxeo.ecm.tokenauth.service.TokenAuthenticationService; 036import org.nuxeo.runtime.api.Framework; 037 038/** 039 * Handles authentication with a token sent as a request header. 040 * <p> 041 * The user is retrieved with the {@link TokenAuthenticationService}. 042 * 043 * @author Antoine Taillefer (ataillefer@nuxeo.com) 044 * @since 5.7 045 */ 046public class TokenAuthenticator implements NuxeoAuthenticationPlugin, NuxeoAuthenticationPluginLogoutExtension { 047 048 public static final String ALLOW_ANONYMOUS_KEY = "allowAnonymous"; 049 050 private static final Log log = LogFactory.getLog(TokenAuthenticator.class); 051 052 protected static final String TOKEN_HEADER = "X-Authentication-Token"; 053 054 protected static final String TOKEN_PARAM = "token"; 055 056 protected boolean allowAnonymous = false; 057 058 @Override 059 public Boolean handleLoginPrompt(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String baseURL) { 060 return false; 061 } 062 063 @Override 064 public UserIdentificationInfo handleRetrieveIdentity(HttpServletRequest httpRequest, 065 HttpServletResponse httpResponse) { 066 067 String token = getTokenFromRequest(httpRequest); 068 069 if (token == null) { 070 log.debug(String.format("Found no '%s' header in the request.", TOKEN_HEADER)); 071 return null; 072 } 073 074 String userName = getUserByToken(token); 075 if (userName == null) { 076 log.debug(String.format("No user bound to the token '%s' (maybe it has been revoked), returning null.", 077 token)); 078 return null; 079 } 080 // Don't retrieve identity for anonymous user unless 'allowAnonymous' parameter is explicitly set to true in 081 // the authentication plugin configuration 082 UserManager userManager = Framework.getService(UserManager.class); 083 if (userManager != null && userName.equals(userManager.getAnonymousUserId()) && !allowAnonymous) { 084 log.debug("Anonymous user is not allowed to get authenticated by token, returning null."); 085 return null; 086 } 087 088 Cookie cookie = CookieHelper.createCookie(httpRequest, TOKEN_HEADER, token); 089 httpResponse.addCookie(cookie); 090 091 return new UserIdentificationInfo(userName); 092 } 093 094 /** 095 * Gets the token from the request if present else null. 096 * 097 * @since 5.9.2 098 */ 099 private String getTokenFromRequest(HttpServletRequest httpRequest) { 100 String token = httpRequest.getHeader(TOKEN_HEADER); 101 102 if (token == null) { 103 token = httpRequest.getParameter(TOKEN_PARAM); 104 } 105 106 // If we don't find the token in request header, let's check in cookies 107 if (token == null && httpRequest.getCookies() != null) { 108 Cookie cookie = getTokenCookie(httpRequest); 109 if (cookie != null) { 110 return cookie.getValue(); 111 } 112 } 113 return token; 114 } 115 116 /** 117 * Returns the token from the cookies if found else null. 118 * 119 * @since 5.9.2 120 */ 121 private Cookie getTokenCookie(HttpServletRequest httpRequest) { 122 Cookie[] cookies = httpRequest.getCookies(); 123 if (cookies != null) { 124 for (Cookie cookie : cookies) { 125 if (cookie.getName().equals(TOKEN_HEADER)) { 126 return cookie; 127 } 128 } 129 } 130 return null; 131 } 132 133 @Override 134 public Boolean needLoginPrompt(HttpServletRequest httpRequest) { 135 return false; 136 } 137 138 @Override 139 public void initPlugin(Map<String, String> parameters) { 140 if (parameters.containsKey(ALLOW_ANONYMOUS_KEY)) { 141 allowAnonymous = Boolean.valueOf(parameters.get(ALLOW_ANONYMOUS_KEY)); 142 } 143 } 144 145 @Override 146 public List<String> getUnAuthenticatedURLPrefix() { 147 return null; 148 } 149 150 protected String getUserByToken(String token) { 151 152 TokenAuthenticationService tokenAuthService = Framework.getService(TokenAuthenticationService.class); 153 return tokenAuthService.getUserName(token); 154 } 155 156 @Override 157 public Boolean handleLogout(HttpServletRequest httpRequest, HttpServletResponse httpResponse) { 158 Cookie cookie = getTokenCookie(httpRequest); 159 if (cookie != null) { 160 cookie.setValue(""); 161 httpResponse.addCookie(cookie); 162 } 163 return false; 164 } 165}