/*
* Copyright (c) 2009-2010 Lockheed Martin Corporation
*
* 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.
*/
package org.eurekastreams.server.service.opensocial.oauth;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthProblemException;
import org.apache.commons.logging.Log;
import org.apache.shindig.auth.SecurityToken;
import org.apache.shindig.social.opensocial.oauth.OAuthDataStore;
import org.apache.shindig.social.opensocial.oauth.OAuthEntry;
import org.eurekastreams.commons.actions.context.service.ServiceActionContext;
import org.eurekastreams.commons.actions.service.ServiceAction;
import org.eurekastreams.commons.exceptions.ExecutionException;
import org.eurekastreams.commons.logging.LogFactory;
import org.eurekastreams.commons.server.service.ActionController;
import org.eurekastreams.server.action.principal.PrincipalPopulatorTransWrapper;
import org.eurekastreams.server.action.request.opensocial.CreateOAuthRequestTokenRequest;
import org.eurekastreams.server.action.response.opensocial.SecurityTokenResponse;
import com.google.inject.Inject;
import com.google.inject.name.Named;
/**
* {@link OAuthDataStore} implementation that is used during both 2 and 3-legged OAuth authorizations from Shindig.
* These methods are called
*/
public class OAuthDataStoreImpl implements OAuthDataStore
{
/**
* Local instance of logger.
*/
private Log logger = LogFactory.make();
/**
* Instance of the {@link ActionController} for this class.
*/
@Inject
private ActionController actionController;
/**
* Instance of the {@link PrincipalPopulatorTransWrapper} for the OpenSocialPrincipalPopulator.
*/
@Inject
private PrincipalPopulatorTransWrapper principalPopulator;
/**
* Instance of the CreateOauthRequestToken Service Action.
*/
private final ServiceAction createOAuthRequestTokenAction;
/**
* Instance of the AuthorizeOAuthToken Service Action.
*/
private final ServiceAction authorizeOAuthTokenAction;
/**
* Instance of the UpdateRequestToAccessToken Service Action.
*/
private final ServiceAction updateRequestToAccessTokenAction;
/**
* Instance of the GetOAuthEntryByToken Service Action.
*/
private final ServiceAction getOAuthEntryByTokenAction;
/**
* Instance of the DisableOAuthToken Service Action.
*/
private final ServiceAction disableOAuthTokenAction;
/**
* Instance of the RemoveOAuthToken Service Action.
*/
private final ServiceAction removeOAuthTokenAction;
/**
* Instance of the GetOauthConsumerByConsumerKeyAction Service Action.
*/
private final ServiceAction getOAuthConsumerByConsumerKeyAction;
/**
* Instance of the GetSecurityToken For Conumer Request Service Action.
*/
private final ServiceAction getSecurityTokenForConsumerRequestAction;
/**
* Constructor.
*
* @param inCreateOAuthRequestTokenAction
* - instance of {@link ServiceAction} for CreateOAuthRequestToken Service Action.
* @param inAuthorizeOAuthTokenAction
* - instance of {@link ServiceAction} for OAuthAuthorize.
* @param inUpdateRequestToAccessTokenAction
* - instance of UpdateRequestToAccessToken {@link ServiceAction}.
* @param inGetOAuthEntryByTokenAction
* - instance of GetOAuthEntryByToken {@link ServiceAction}.
* @param inDisableOAuthTokenAction
* - instance of DisableOAuthToken {@link ServiceAction}.
* @param inRemoveOAuthTokenAction
* - instance of RemoveOAuthToken {@link ServiceAction}.
* @param inGetOAuthConsumerByConsumerKeyAction
* - instance of GetOAuthConsumerByConsumerKey {@link ServiceAction}.
* @param inGetSecurityTokenForConsumerRequestAction
* - instance of GetSecurityTokenForConsumerRequest {@link ServiceAction}.
*/
@Inject
public OAuthDataStoreImpl(@Named("createOAuthRequestToken") final ServiceAction inCreateOAuthRequestTokenAction,
@Named("authorizeOAuthToken") final ServiceAction inAuthorizeOAuthTokenAction,
@Named("updateRequestToAccessToken") final ServiceAction inUpdateRequestToAccessTokenAction,
@Named("getOAuthEntryByToken") final ServiceAction inGetOAuthEntryByTokenAction,
@Named("disableOAuthToken") final ServiceAction inDisableOAuthTokenAction,
@Named("removeOAuthToken") final ServiceAction inRemoveOAuthTokenAction,
@Named("getOAuthConsumerByConsumerKey") final ServiceAction inGetOAuthConsumerByConsumerKeyAction,
@Named("getSecurityTokenForConsumerRequest") final ServiceAction inGetSecurityTokenForConsumerRequestAction)
{
createOAuthRequestTokenAction = inCreateOAuthRequestTokenAction;
authorizeOAuthTokenAction = inAuthorizeOAuthTokenAction;
updateRequestToAccessTokenAction = inUpdateRequestToAccessTokenAction;
getOAuthEntryByTokenAction = inGetOAuthEntryByTokenAction;
disableOAuthTokenAction = inDisableOAuthTokenAction;
removeOAuthTokenAction = inRemoveOAuthTokenAction;
getOAuthConsumerByConsumerKeyAction = inGetOAuthConsumerByConsumerKeyAction;
getSecurityTokenForConsumerRequestAction = inGetSecurityTokenForConsumerRequestAction;
}
/**
* Setter.
*
* @param inServiceActionController
* - instance of the {@link ActionController}.
*/
public void setServiceActionController(final ActionController inServiceActionController)
{
actionController = inServiceActionController;
}
/**
* Setter.
*
* @param inPrincipalPopulatorTransWrapper
* - instance of {@link PrincipalPopulatorTransWrapper}.
*/
public void setPrincipalPopulatorTransWrapper(final PrincipalPopulatorTransWrapper inPrincipalPopulatorTransWrapper)
{
principalPopulator = inPrincipalPopulatorTransWrapper;
}
/**
* Creates a request token for a new OAuth request.
*
* @param consumerKey
* the consumer key for this request.
* @param oauthVersion
* the version of the oauth protocol used in this request.
* @param signedCallbackUrl
* the callback url (needed for OAuth 1.0 A).
* @return the entry containing the new token.
* @throws OAuthProblemException
* thrown when token could not be persisted.
*/
public OAuthEntry generateRequestToken(final String consumerKey, final String oauthVersion,
final String signedCallbackUrl) throws OAuthProblemException
{
try
{
CreateOAuthRequestTokenRequest currentRequest = new CreateOAuthRequestTokenRequest(consumerKey,
oauthVersion, signedCallbackUrl);
ServiceActionContext currentContext = new ServiceActionContext(currentRequest, null);
return (OAuthEntry) actionController.execute(currentContext, createOAuthRequestTokenAction);
}
catch (Exception ex)
{
logger.error("Error occurred persisting request token information", ex);
throw new OAuthProblemException("Unable to persist request token information");
}
}
/**
* Authorize the access token.
*
* @param entry
* the entry to authorize.
* @param userId
* the user making the request.
* @throws OAuthProblemException
* thrown when the token could not be persisted.
*/
public void authorizeToken(final OAuthEntry entry, final String userId) throws OAuthProblemException
{
try
{
ServiceActionContext currentContext = new ServiceActionContext(entry.getToken(), principalPopulator
.getPrincipal(entry.getUserId(), ""));
actionController.execute(currentContext, authorizeOAuthTokenAction);
}
catch (ExecutionException ex)
{
logger.error("Error occurred authorizing token", ex);
throw new OAuthProblemException("Unable to authorize token");
}
}
/**
* Exchange a request token for an access token.
*
* @param entry
* the entry to authorize.
* @return the entry with the access token.
* @throws OAuthProblemException
* thrown when the token could not be persisted.
*/
public OAuthEntry convertToAccessToken(final OAuthEntry entry) throws OAuthProblemException
{
try
{
ServiceActionContext currentContext = new ServiceActionContext(entry, principalPopulator.getPrincipal(entry
.getUserId(), ""));
return (OAuthEntry) actionController.execute(currentContext, updateRequestToAccessTokenAction);
}
catch (Exception ex)
{
logger.error("Error occurred converting request token to access token", ex);
throw new OAuthProblemException("Unable to convert request token to access token");
}
}
/**
* Return the consumer for a given key.
*
* @param consumerKey
* the key.
* @return the found consumer.
* @throws OAuthProblemException
* thrown when there was a problem retrieving the consumer information.
*/
public OAuthConsumer getConsumer(final String consumerKey) throws OAuthProblemException
{
OAuthConsumer consumer = null;
try
{
ServiceActionContext currentContext = new ServiceActionContext(consumerKey, null);
consumer = (OAuthConsumer) actionController.execute(currentContext, getOAuthConsumerByConsumerKeyAction);
}
catch (Exception ex)
{
logger.error("Error occurred retrieving consumer with provided key.", ex);
throw new OAuthProblemException("Unable to retrieve consumer with provided information.");
}
return consumer;
}
/**
* Get an entry for a specific oauth token.
*
* @param oauthToken
* the token.
* @return the associated entry.
*/
public OAuthEntry getEntry(final String oauthToken)
{
OAuthEntry entry = null;
try
{
ServiceActionContext currentContext = new ServiceActionContext(oauthToken, null);
entry = (OAuthEntry) actionController.execute(currentContext, getOAuthEntryByTokenAction);
}
catch (Exception ex)
{
logger.error("Error occurred retrieving OAuthEntry based on the token.", ex);
}
return entry;
}
/**
* Marks a token as disabled.
*
* @param entry
* the OAuthEntry to disable.
*/
public void disableToken(final OAuthEntry entry)
{
try
{
ServiceActionContext currentContext = new ServiceActionContext(entry.getToken(), null);
actionController.execute(currentContext, disableOAuthTokenAction);
}
catch (Exception ex)
{
logger.error("Error occurred disabling token.", ex);
}
}
/**
* Deletes a token.
*
* @param entry
* the OAuthEntry to remove.
*/
public void removeToken(final OAuthEntry entry)
{
try
{
ServiceActionContext currentContext = new ServiceActionContext(entry.getToken(), null);
actionController.execute(currentContext, removeOAuthTokenAction);
}
catch (Exception ex)
{
logger.error("Error occurred removing token.", ex);
}
}
/**
* Return the proper security token for a 2 legged oauth request that has been validated for the given consumerKey.
* App specific checks like making sure the requested user has the app installed are handled by the authorization
* strategy of the ServiceAction being executed.
*
* @param consumerKey
* the consumer making the oauth request.
* @param userId
* the userId for this request.
* @return the found securitytoken.
* @throws OAuthProblemException
* thrown when the consumer key was not found.
*/
public SecurityToken getSecurityTokenForConsumerRequest(final String consumerKey, final String userId)
throws OAuthProblemException
{
SecurityTokenResponse response = null;
try
{
// Currently, this supports two legged oauth with "reverse call home" where the server hosting an
// application
// wishes to request information about a user that has their application installed on their start page.
ServiceActionContext currentContext = new ServiceActionContext(consumerKey, principalPopulator
.getPrincipal(userId, ""));
response = (SecurityTokenResponse) actionController.execute(currentContext,
getSecurityTokenForConsumerRequestAction);
}
catch (Exception ex)
{
logger.error("Error occurred retrieving security token for Consumer Request.", ex);
throw new OAuthProblemException("Error occurred retrieving security token for Consumer Request.");
}
return response != null ? response.getSecurityToken() : null;
}
}