001/* 002 * (C) Copyright 2006-2008 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 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.oauth.tokens; 023 024import java.io.Serializable; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 029import java.util.UUID; 030 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.DocumentModelList; 035import org.nuxeo.ecm.directory.DirectoryException; 036import org.nuxeo.ecm.directory.Session; 037import org.nuxeo.ecm.directory.api.DirectoryService; 038import org.nuxeo.runtime.api.Framework; 039import org.nuxeo.runtime.model.DefaultComponent; 040 041/** 042 * Service implementation for {@link OAuthTokenStore}. 043 * <p> 044 * This service is responsible for managing storage of the {@link OAuthToken}. A simple SQL Directory is used for ACCESS 045 * Token whereas a simple in memory storage is used for REQUEST Tokens. 046 * 047 * @author tiry 048 */ 049public class OAuthTokenStoreImpl extends DefaultComponent implements OAuthTokenStore { 050 051 protected static final Log log = LogFactory.getLog(OAuthTokenStoreImpl.class); 052 053 public static final String DIRECTORY_NAME = "oauthTokens"; 054 055 protected Map<String, OAuthToken> requestTokenStore = new HashMap<String, OAuthToken>(); 056 057 @Override 058 public OAuthToken addVerifierToRequestToken(String token, Long duration) { 059 NuxeoOAuthToken rToken = (NuxeoOAuthToken) getRequestToken(token); 060 if (rToken != null) { 061 rToken.verifier = "NX-VERIF-" + UUID.randomUUID().toString(); 062 rToken.durationInMinutes = duration; 063 } 064 return rToken; 065 } 066 067 @Override 068 public OAuthToken createAccessTokenFromRequestToken(OAuthToken requestToken) { 069 NuxeoOAuthToken aToken = new NuxeoOAuthToken((NuxeoOAuthToken) requestToken); 070 String token = "NX-AT-" + UUID.randomUUID().toString(); 071 aToken.token = token; 072 aToken.tokenSecret = "NX-ATS-" + UUID.randomUUID().toString(); 073 aToken.type = OAuthToken.Type.ACCESS; 074 075 try { 076 aToken = storeAccessTokenAsDirectoryEntry(aToken); 077 removeRequestToken(requestToken.getToken()); 078 return aToken; 079 } catch (DirectoryException e) { 080 log.error("Error during directory persistence", e); 081 return null; 082 } 083 } 084 085 @Override 086 public NuxeoOAuthToken getClientAccessToken(String appId, String owner) { 087 DirectoryService ds = Framework.getService(DirectoryService.class); 088 try (Session session = ds.open(DIRECTORY_NAME)) { 089 Map<String, Serializable> filter = new HashMap<String, Serializable>(); 090 filter.put("appId", appId); 091 filter.put("clientId", owner); 092 filter.put("clientToken", 1); 093 DocumentModelList entries = session.query(filter); 094 if (entries.size() == 0) { 095 return null; 096 } 097 if (entries.size() > 1) { 098 log.error("Found several tokens"); 099 } 100 return getTokenFromDirectoryEntry(entries.get(0)); 101 } 102 } 103 104 @Override 105 public void removeClientAccessToken(String appId, String owner) { 106 DirectoryService ds = Framework.getService(DirectoryService.class); 107 try (Session session = ds.open(DIRECTORY_NAME)) { 108 Map<String, Serializable> filter = new HashMap<String, Serializable>(); 109 filter.put("appId", appId); 110 filter.put("clientId", owner); 111 filter.put("clientToken", 1); 112 DocumentModelList entries = session.query(filter); 113 if (entries.size() == 0) { 114 return; 115 } 116 if (entries.size() > 1) { 117 log.error("Found several tokens"); 118 } 119 session.deleteEntry(entries.get(0)); 120 } 121 } 122 123 @Override 124 public void storeClientAccessToken(String consumerKey, String callBack, String token, String tokenSecret, 125 String appId, String owner) { 126 NuxeoOAuthToken aToken = new NuxeoOAuthToken(consumerKey, callBack); 127 aToken.token = token; 128 aToken.tokenSecret = tokenSecret; 129 if (appId != null) { 130 aToken.appId = appId; 131 } 132 133 aToken.clientToken = true; 134 aToken.clientId = owner; 135 try { 136 aToken = storeAccessTokenAsDirectoryEntry(aToken); 137 } catch (DirectoryException e) { 138 log.error("Error during directory persistence", e); 139 } 140 } 141 142 protected NuxeoOAuthToken getTokenFromDirectory(String token) { 143 DirectoryService ds = Framework.getService(DirectoryService.class); 144 try (Session session = ds.open(DIRECTORY_NAME)) { 145 DocumentModel entry = session.getEntry(token); 146 if (entry == null) { 147 return null; 148 } 149 return getTokenFromDirectoryEntry(entry); 150 } 151 } 152 153 protected NuxeoOAuthToken getTokenFromDirectoryEntry(DocumentModel entry) { 154 return new NuxeoOAuthToken(entry); 155 } 156 157 protected NuxeoOAuthToken storeAccessTokenAsDirectoryEntry(NuxeoOAuthToken aToken) { 158 DirectoryService ds = Framework.getService(DirectoryService.class); 159 try (Session session = ds.open(DIRECTORY_NAME)) { 160 DocumentModel entry = session.getEntry(aToken.getToken()); 161 if (entry == null) { 162 Map<String, Object> init = new HashMap<String, Object>(); 163 init.put("token", aToken.getToken()); 164 entry = session.createEntry(init); 165 } 166 167 aToken.updateEntry(entry); 168 session.updateEntry(entry); 169 170 return getTokenFromDirectoryEntry(session.getEntry(aToken.getToken())); 171 } 172 } 173 174 @Override 175 public OAuthToken createRequestToken(String consumerKey, String callBack) { 176 177 NuxeoOAuthToken rToken = new NuxeoOAuthToken(consumerKey, callBack); 178 String token = "NX-RT-" + consumerKey + "-" + UUID.randomUUID().toString(); 179 rToken.token = token; 180 rToken.tokenSecret = "NX-RTS-" + consumerKey + UUID.randomUUID().toString(); 181 rToken.type = OAuthToken.Type.REQUEST; 182 requestTokenStore.put(token, rToken); 183 184 return rToken; 185 } 186 187 @Override 188 public OAuthToken getAccessToken(String token) { 189 190 try { 191 return getTokenFromDirectory(token); 192 } catch (DirectoryException e) { 193 log.error("Error while accessing Token SQL storage", e); 194 return null; 195 } 196 } 197 198 @Override 199 public OAuthToken getRequestToken(String token) { 200 return requestTokenStore.get(token); 201 } 202 203 @Override 204 public List<OAuthToken> listAccessTokenForConsumer(String consumerKey) { 205 List<OAuthToken> result = new ArrayList<OAuthToken>(); 206 207 DirectoryService ds = Framework.getService(DirectoryService.class); 208 try (Session session = ds.open(DIRECTORY_NAME)) { 209 Map<String, Serializable> filter = new HashMap<String, Serializable>(); 210 filter.put("consumerKey", consumerKey); 211 filter.put("clientToken", 0); 212 DocumentModelList entries = session.query(filter); 213 for (DocumentModel entry : entries) { 214 result.add(new NuxeoOAuthToken(entry)); 215 } 216 } catch (DirectoryException e) { 217 log.error("Error during token listing", e); 218 } 219 return result; 220 } 221 222 @Override 223 public List<OAuthToken> listAccessTokenForUser(String login) { 224 List<OAuthToken> result = new ArrayList<OAuthToken>(); 225 DirectoryService ds = Framework.getService(DirectoryService.class); 226 try (Session session = ds.open(DIRECTORY_NAME)) { 227 Map<String, Serializable> filter = new HashMap<>(); 228 filter.put("nuxeoLogin", login); 229 filter.put("clientToken", 0); 230 DocumentModelList entries = session.query(filter); 231 for (DocumentModel entry : entries) { 232 result.add(new NuxeoOAuthToken(entry)); 233 } 234 } catch (DirectoryException e) { 235 log.error("Error during token listing", e); 236 } 237 return result; 238 } 239 240 @Override 241 public void removeAccessToken(String token) { 242 DirectoryService ds = Framework.getService(DirectoryService.class); 243 try (Session session = ds.open(DIRECTORY_NAME)) { 244 session.deleteEntry(token); 245 } 246 } 247 248 @Override 249 public void removeRequestToken(String token) { 250 requestTokenStore.remove(token); 251 } 252 253}