001/* 002 * (C) Copyright 2017-2018 Nuxeo (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 * Arnaud Kervern 018 * Thomas Roger 019 * Florent Guillaume 020 */ 021package org.nuxeo.ecm.platform.oauth2; 022 023import static java.lang.Boolean.FALSE; 024import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; 025import static org.nuxeo.ecm.platform.oauth2.Constants.TOKEN_SERVICE; 026 027import java.util.List; 028import java.util.Map; 029 030import javax.servlet.http.HttpServletRequest; 031import javax.servlet.http.HttpServletResponse; 032 033import org.apache.commons.lang3.StringUtils; 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.nuxeo.ecm.platform.api.login.UserIdentificationInfo; 037import org.nuxeo.ecm.platform.oauth2.clients.OAuth2ClientService; 038import org.nuxeo.ecm.platform.oauth2.tokens.NuxeoOAuth2Token; 039import org.nuxeo.ecm.platform.oauth2.tokens.OAuth2TokenStore; 040import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPlugin; 041import org.nuxeo.runtime.api.Framework; 042import org.nuxeo.runtime.transaction.TransactionHelper; 043 044/** 045 * OAuth2 Authentication Plugin. 046 * <p> 047 * This plugin chekcs the {@code access_token} request parameter or the {@code Authorization: Bearer} request header for 048 * a valid OAuth2 token (checked with the {@link OAuth2ClientService}). 049 * 050 * @since 10.3 051 */ 052public class NuxeoOAuth2Authenticator implements NuxeoAuthenticationPlugin { 053 054 private static final Log log = LogFactory.getLog(NuxeoOAuth2Authenticator.class); 055 056 public static final String ACCESS_TOKEN = "access_token"; 057 058 public static final String BEARER_SP = "Bearer "; 059 060 protected OAuth2TokenStore tokenStore = new OAuth2TokenStore(TOKEN_SERVICE); 061 062 @Override 063 public void initPlugin(Map<String, String> parameters) { 064 // nothing to init 065 } 066 067 @Override 068 public List<String> getUnAuthenticatedURLPrefix() { 069 return null; // NOSONAR 070 } 071 072 @Override 073 public Boolean needLoginPrompt(HttpServletRequest httpRequest) { 074 return FALSE; 075 } 076 077 @Override 078 public Boolean handleLoginPrompt(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String baseURL) { 079 return FALSE; 080 } 081 082 @Override 083 public UserIdentificationInfo handleRetrieveIdentity(HttpServletRequest request, HttpServletResponse response) { 084 String accessToken = getAccessToken(request); 085 if (accessToken == null) { 086 log.trace("OAuth2 token not found"); 087 return null; 088 } 089 NuxeoOAuth2Token token = TransactionHelper.runInTransaction(() -> tokenStore.getToken(accessToken)); 090 OAuth2ClientService clientService = Framework.getService(OAuth2ClientService.class); 091 if (token == null) { 092 log.trace("OAuth2 token unknown"); 093 return null; 094 } 095 if (token.isExpired()) { 096 log.trace("OAuth2 token expired"); 097 return null; 098 } 099 if (!clientService.hasClient(token.getClientId())) { 100 if (log.isTraceEnabled()) { 101 log.trace("OAuth2 token for unknown client: " + token.getClientId()); 102 } 103 return null; 104 } 105 106 String username = token.getNuxeoLogin(); 107 log.trace("OAuth2 token found for user: " + username); 108 return new UserIdentificationInfo(username); 109 } 110 111 protected String getAccessToken(HttpServletRequest request) { 112 String accessToken = request.getParameter(ACCESS_TOKEN); 113 if (StringUtils.isNotBlank(accessToken)) { 114 log.trace("Found access_token request parameter"); 115 return accessToken; 116 } 117 String authorization = request.getHeader(AUTHORIZATION); 118 if (authorization != null && authorization.startsWith(BEARER_SP)) { 119 log.trace("Found Authorization: Bearer request header"); 120 return authorization.substring(BEARER_SP.length()).trim(); 121 } 122 return null; 123 } 124 125}