/* * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * Nuxeo - initial API and implementation * * $Id$ */ package org.nuxeo.ecm.platform.oauth.tokens; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.directory.DirectoryException; import org.nuxeo.ecm.directory.Session; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.model.DefaultComponent; /** * Service implementation for {@link OAuthTokenStore}. * <p> * This service is responsible for managing storage of the {@link OAuthToken}. A simple SQL Directory is used for ACCESS * Token whereas a simple in memory storage is used for REQUEST Tokens. * * @author tiry */ public class OAuthTokenStoreImpl extends DefaultComponent implements OAuthTokenStore { protected static final Log log = LogFactory.getLog(OAuthTokenStoreImpl.class); public static final String DIRECTORY_NAME = "oauthTokens"; protected Map<String, OAuthToken> requestTokenStore = new HashMap<String, OAuthToken>(); @Override public OAuthToken addVerifierToRequestToken(String token, Long duration) { NuxeoOAuthToken rToken = (NuxeoOAuthToken) getRequestToken(token); if (rToken != null) { rToken.verifier = "NX-VERIF-" + UUID.randomUUID().toString(); rToken.durationInMinutes = duration; } return rToken; } @Override public OAuthToken createAccessTokenFromRequestToken(OAuthToken requestToken) { NuxeoOAuthToken aToken = new NuxeoOAuthToken((NuxeoOAuthToken) requestToken); String token = "NX-AT-" + UUID.randomUUID().toString(); aToken.token = token; aToken.tokenSecret = "NX-ATS-" + UUID.randomUUID().toString(); aToken.type = OAuthToken.Type.ACCESS; try { aToken = storeAccessTokenAsDirectoryEntry(aToken); removeRequestToken(requestToken.getToken()); return aToken; } catch (DirectoryException e) { log.error("Error during directory persistence", e); return null; } } @Override public NuxeoOAuthToken getClientAccessToken(String appId, String owner) { DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { Map<String, Serializable> filter = new HashMap<String, Serializable>(); filter.put("appId", appId); filter.put("clientId", owner); filter.put("clientToken", 1); DocumentModelList entries = session.query(filter); if (entries.size() == 0) { return null; } if (entries.size() > 1) { log.error("Found several tokens"); } return getTokenFromDirectoryEntry(entries.get(0)); } } @Override public void removeClientAccessToken(String appId, String owner) { DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { Map<String, Serializable> filter = new HashMap<String, Serializable>(); filter.put("appId", appId); filter.put("clientId", owner); filter.put("clientToken", 1); DocumentModelList entries = session.query(filter); if (entries.size() == 0) { return; } if (entries.size() > 1) { log.error("Found several tokens"); } session.deleteEntry(entries.get(0)); } } @Override public void storeClientAccessToken(String consumerKey, String callBack, String token, String tokenSecret, String appId, String owner) { NuxeoOAuthToken aToken = new NuxeoOAuthToken(consumerKey, callBack); aToken.token = token; aToken.tokenSecret = tokenSecret; if (appId != null) { aToken.appId = appId; } aToken.clientToken = true; aToken.clientId = owner; try { aToken = storeAccessTokenAsDirectoryEntry(aToken); } catch (DirectoryException e) { log.error("Error during directory persistence", e); } } protected NuxeoOAuthToken getTokenFromDirectory(String token) { DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { DocumentModel entry = session.getEntry(token); if (entry == null) { return null; } return getTokenFromDirectoryEntry(entry); } } protected NuxeoOAuthToken getTokenFromDirectoryEntry(DocumentModel entry) { return new NuxeoOAuthToken(entry); } protected NuxeoOAuthToken storeAccessTokenAsDirectoryEntry(NuxeoOAuthToken aToken) { DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { DocumentModel entry = session.getEntry(aToken.getToken()); if (entry == null) { Map<String, Object> init = new HashMap<String, Object>(); init.put("token", aToken.getToken()); entry = session.createEntry(init); } aToken.updateEntry(entry); session.updateEntry(entry); return getTokenFromDirectoryEntry(session.getEntry(aToken.getToken())); } } @Override public OAuthToken createRequestToken(String consumerKey, String callBack) { NuxeoOAuthToken rToken = new NuxeoOAuthToken(consumerKey, callBack); String token = "NX-RT-" + consumerKey + "-" + UUID.randomUUID().toString(); rToken.token = token; rToken.tokenSecret = "NX-RTS-" + consumerKey + UUID.randomUUID().toString(); rToken.type = OAuthToken.Type.REQUEST; requestTokenStore.put(token, rToken); return rToken; } @Override public OAuthToken getAccessToken(String token) { try { return getTokenFromDirectory(token); } catch (DirectoryException e) { log.error("Error while accessing Token SQL storage", e); return null; } } @Override public OAuthToken getRequestToken(String token) { return requestTokenStore.get(token); } @Override public List<OAuthToken> listAccessTokenForConsumer(String consumerKey) { List<OAuthToken> result = new ArrayList<OAuthToken>(); DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { Map<String, Serializable> filter = new HashMap<String, Serializable>(); filter.put("consumerKey", consumerKey); filter.put("clientToken", 0); DocumentModelList entries = session.query(filter); for (DocumentModel entry : entries) { result.add(new NuxeoOAuthToken(entry)); } } catch (DirectoryException e) { log.error("Error during token listing", e); } return result; } @Override public List<OAuthToken> listAccessTokenForUser(String login) { List<OAuthToken> result = new ArrayList<OAuthToken>(); DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { Map<String, Serializable> filter = new HashMap<>(); filter.put("nuxeoLogin", login); filter.put("clientToken", 0); DocumentModelList entries = session.query(filter); for (DocumentModel entry : entries) { result.add(new NuxeoOAuthToken(entry)); } } catch (DirectoryException e) { log.error("Error during token listing", e); } return result; } @Override public void removeAccessToken(String token) { DirectoryService ds = Framework.getService(DirectoryService.class); try (Session session = ds.open(DIRECTORY_NAME)) { session.deleteEntry(token); } } @Override public void removeRequestToken(String token) { requestTokenStore.remove(token); } }