/*
* JBoss, a division of Red Hat
* Copyright 2013, Red Hat Middleware, LLC, and individual
* contributors as indicated by the @authors tag. See the
* copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.gatein.api.oauth;
import java.io.IOException;
import org.gatein.api.internal.Parameters;
import org.gatein.api.oauth.exception.OAuthApiException;
import org.gatein.api.oauth.exception.OAuthApiExceptionCode;
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;
import org.gatein.security.oauth.spi.AccessTokenContext;
import org.gatein.security.oauth.spi.OAuthProviderType;
import org.gatein.security.oauth.spi.SocialNetworkService;
import org.gatein.security.oauth.exception.OAuthException;
import org.gatein.security.oauth.exception.OAuthExceptionCode;
/**
* Basic implementation of OAuth Provider. It doesn't have full access to WebUI, so some operations are not supported
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class BasicOAuthProviderImpl implements OAuthProvider {
private final OAuthProviderType internalOAuthProvider;
private final SocialNetworkService socialNetworkService;
protected final Logger log = LoggerFactory.getLogger(getClass());
public BasicOAuthProviderImpl(OAuthProviderType internalOAuthProvider, SocialNetworkService socialNetworkService) {
Parameters.requireNonNull(internalOAuthProvider, "internalOAuthProvider");
Parameters.requireNonNull(socialNetworkService, "socialNetworkService");
this.internalOAuthProvider = internalOAuthProvider;
this.socialNetworkService = socialNetworkService;
}
@Override
public String getKey() {
return internalOAuthProvider.getKey();
}
@Override
public String getFriendlyName() {
return internalOAuthProvider.getFriendlyName();
}
@Override
public AccessToken loadAccessToken(String username) throws OAuthApiException {
try {
AccessTokenContext accessTokenContext = this.socialNetworkService.getOAuthAccessToken(this.internalOAuthProvider, username);
if (accessTokenContext == null) {
if (log.isTraceEnabled()) {
log.trace("Not found access token for user " + username + " with provider " + internalOAuthProvider);
}
return null;
} else {
return new AccessTokenImpl(accessTokenContext);
}
} catch (OAuthException oauthEx) {
throw new OAuthApiException(translateExceptionCode(oauthEx.getExceptionCode()), oauthEx.getMessage(), oauthEx);
}
}
@Override
public void saveAccessToken(String username, AccessToken accessToken) throws OAuthApiException {
AccessTokenContext accessTokenContext = getInternalAccessTokenContext(accessToken);
try {
this.socialNetworkService.updateOAuthAccessToken(this.internalOAuthProvider, username, accessTokenContext);
} catch (OAuthException oauthEx) {
throw new OAuthApiException(translateExceptionCode(oauthEx.getExceptionCode()), oauthEx.getMessage(), oauthEx);
}
}
@Override
public void removeAccessToken(String username) throws OAuthApiException {
try {
this.socialNetworkService.removeOAuthAccessToken(this.internalOAuthProvider, username);
} catch (OAuthException oauthEx) {
throw new OAuthApiException(translateExceptionCode(oauthEx.getExceptionCode()), oauthEx.getMessage(), oauthEx);
}
}
@Override
public void startOAuthWorkflow(String neededCustomScope) throws OAuthApiException, IOException {
throw new OAuthApiException(OAuthApiExceptionCode.OTHER_ERROR, "Not supported for this implementation");
}
@Override
public AccessToken validateTokenAndUpdateScopes(AccessToken accessToken) throws OAuthApiException {
AccessTokenContext accessTokenContext = getInternalAccessTokenContext(accessToken);
try {
accessTokenContext = this.internalOAuthProvider.getOauthProviderProcessor().validateTokenAndUpdateScopes(accessTokenContext);
} catch (OAuthException oauthEx) {
throw new OAuthApiException(translateExceptionCode(oauthEx.getExceptionCode()), oauthEx.getMessage(), oauthEx);
}
return new AccessTokenImpl(accessTokenContext);
}
@Override
public void revokeToken(AccessToken accessToken) throws OAuthApiException {
AccessTokenContext accessTokenContext = getInternalAccessTokenContext(accessToken);
try {
this.internalOAuthProvider.getOauthProviderProcessor().revokeToken(accessTokenContext);
} catch (OAuthException oauthEx) {
throw new OAuthApiException(translateExceptionCode(oauthEx.getExceptionCode()), oauthEx.getMessage(), oauthEx);
}
}
@Override
public <T> T getAuthorizedSocialApiObject(AccessToken accessToken, Class<T> socialApiObjectType) throws OAuthApiException {
AccessTokenContext accessTokenContext = getInternalAccessTokenContext(accessToken);
T socialApiObject = (T)this.internalOAuthProvider.getOauthProviderProcessor().getAuthorizedSocialApiObject(accessTokenContext, socialApiObjectType);
if (socialApiObject == null) {
throw new OAuthApiException(OAuthApiExceptionCode.SOCIAL_API_OBJECT_NOT_FOUND,
"Class '" + socialApiObjectType + "' not supported by processor " + this.internalOAuthProvider.getOauthProviderProcessor());
}
return socialApiObject;
}
protected OAuthProviderType getInternalOAuthProvider() {
return internalOAuthProvider;
}
// protected method, so it could be overriden if needed
protected AccessTokenContext getInternalAccessTokenContext(AccessToken accessToken) throws OAuthApiException {
AccessTokenImpl accessTokenImpl = (AccessTokenImpl)accessToken;
return accessTokenImpl.getAccessTokenContext();
}
// Translation between internal exception codes to API exception codes
private OAuthApiExceptionCode translateExceptionCode(OAuthExceptionCode internalCode) {
switch (internalCode) {
case ACCESS_TOKEN_ERROR: return OAuthApiExceptionCode.ACCESS_TOKEN_ERROR;
case IO_ERROR: return OAuthApiExceptionCode.IO_ERROR;
case TOKEN_REVOCATION_FAILED: return OAuthApiExceptionCode.TOKEN_REVOCATION_FAILED;
case PERSISTENCE_ERROR: return OAuthApiExceptionCode.PERSISTENCE_ERROR;
case DUPLICATE_OAUTH_PROVIDER_USERNAME: return OAuthApiExceptionCode.DUPLICATE_OAUTH_PROVIDER_USERNAME;
default: return OAuthApiExceptionCode.OTHER_ERROR;
}
}
}