package com.ibm.sbt.services.endpoints; import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.HttpContext; import com.ibm.commons.Platform; import com.ibm.commons.runtime.Context; import com.ibm.commons.runtime.RuntimeConstants; import com.ibm.commons.util.StringUtil; import com.ibm.sbt.security.authentication.oauth.OAuthException; import com.ibm.sbt.security.authentication.oauth.consumer.AccessToken; import com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler; import com.ibm.sbt.security.authentication.oauth.consumer.OAuth2Handler; import com.ibm.sbt.security.authentication.oauth.consumer.servlet.OAClientAuthentication; import com.ibm.sbt.services.client.ClientServicesException; import com.ibm.sbt.services.endpoints.js.JSReference; import com.ibm.sbt.util.SBTException; /** * Bean that provides authentication via OAuth2. * <p> * </p> * * @author Manish Kataria */ public class OAuth2Endpoint extends AbstractEndpoint { protected OAuth2Handler oAuthHandler; public OAuth2Endpoint(){ this.oAuthHandler = new OAuth2Handler(); } protected OAuth2Endpoint(OAuth2Handler handler) { this.oAuthHandler = handler; } /** * Force login of the specified user using the cached credentials if available. * If not cached credential are available or these are invalid the login will fail. * * @param user * @return true if the specified user was logged in using their cached credentials * @throws ClientServicesException */ public boolean login(String user) throws ClientServicesException { this.oAuthHandler.setUserId(user); if (isAuthenticated()) { return isAuthenticationValid(); } return false; } @Override public void checkValid() throws SBTException { super.checkValid(); // Looks OK with C4? if (StringUtil.isEmpty(oAuthHandler.getConsumerKey())) { throw new SBTException(null, "The Endpoint consumer key is empty for {0}", getClass()); } if (StringUtil.isEmpty(oAuthHandler.getConsumerSecret())) { throw new SBTException(null, "The Endpoint consumer secret is empty for {0}", getClass()); } if (StringUtil.isEmpty(oAuthHandler.getAccessTokenURL())) { throw new SBTException(null, "The Endpoint access token URL is empty for {0}", getClass()); } if (StringUtil.isEmpty(oAuthHandler.getAuthorizationURL())) { throw new SBTException(null, "The Endpoint authorization URL is empty for {0}", getClass()); } } /* * * @see com.ibm.sbt.services.endpoints.Endpoint#isAuthenticated() Checks in token store if we already * have a token for this application id. */ @Override public boolean isAuthenticated() throws ClientServicesException { try { return oAuthHandler.acquireToken(false) != null; } catch (OAuthException ex) { throw new ClientServicesException(ex); } } @Override public void authenticate(boolean force) throws ClientServicesException { try { oAuthHandler.acquireToken(true, false); } catch (OAuthException ex) { throw new ClientServicesException(ex); } } @Override /** * This gets called from Basic Proxy and decorates the HttpClient object with required security headers for OAuth2.0 implementation. */ public void initialize(DefaultHttpClient httpClient) throws ClientServicesException { try { AccessToken accesstoken = oAuthHandler.acquireToken(false); if (accesstoken != null) { HttpRequestInterceptor oauthInterceptor = new OAuth2Interceptor(accesstoken); httpClient.addRequestInterceptor(oauthInterceptor, 0); } } catch (OAuthException e) {} } private static class OAuth2Interceptor implements HttpRequestInterceptor { private final AccessToken token; public OAuth2Interceptor(AccessToken token) { this.token = token; } @Override public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { // Add Security headers try { if (null == token.getAccessToken()) { return; } } catch (Exception e) { Platform.getInstance().log(e); return; } // Remove any existing authorization headers which can cause oauth requests to fail if(request.containsHeader("authorization")){ Header[] header = request.getHeaders("authorization"); for (int i = 0; i < header.length; i++) { request.removeHeader(header[i]); } } String authorizationheader = "Bearer " + token.getAccessToken(); request.addHeader("Authorization", authorizationheader); } } // Methods to populate properties from endpoint definition in managedbean @Override public void setUrl(String url) { super.setUrl(url); // Make the URL the service name if not already set if (StringUtil.isEmpty(oAuthHandler.getServerUrl())) { oAuthHandler.setServerUrl(url); } } public void setAppId(String appId) { oAuthHandler.setAppId(appId); } public void setAuthorizationURL(String authorizationURL) { oAuthHandler.setAuthorizationURL(authorizationURL); } public void setAccessTokenURL(String accessTokenURL) { oAuthHandler.setAccessTokenURL(accessTokenURL); } public void setConsumerKey(String consumerKey) { oAuthHandler.setConsumerKey(consumerKey); } public void setConsumerSecret(String consumerSecret) { oAuthHandler.setConsumerSecret(consumerSecret); } public String getServiceName() { return oAuthHandler.getServiceName(); } public void setServiceName(String serviceName) { oAuthHandler.setServiceName(serviceName); } public String getAppId() { return oAuthHandler.getAppId(); } public String getAccessTokenURL() { return oAuthHandler.getAccessTokenURL(); } public String getAuthorizationURL() { return oAuthHandler.getAuthorizationURL(); } public String getConsumerKey() { return oAuthHandler.getConsumerKey(); } public String getConsumerSecret() { return oAuthHandler.getConsumerSecret(); } @Override public String getCredentialStore() { return oAuthHandler.getCredentialStore(); } @Override public void setCredentialStore(String credentialStore) { oAuthHandler.setCredentialStore(credentialStore); } @Override public String getAuthType() { return "oauth2.0"; } @Override public boolean isForceTrustSSLCertificate() { return oAuthHandler.isForceTrustSSLCertificate(); } @Override public void setForceTrustSSLCertificate(boolean forceTrustSSLCertificate) { oAuthHandler.setForceTrustSSLCertificate(forceTrustSSLCertificate); } @Override public JSReference getAuthenticator(String endpointName, String sbtUrl) { Context ctx = Context.get(); JSReference reference = new JSReference("sbt/authenticator/OAuth"); StringBuilder b = new StringBuilder(); RuntimeConstants.get().appendBaseProxyUrl(b, ctx); b.append("/"); b.append(OAClientAuthentication.URL_PATH); b.append('/'); b.append(endpointName); String url = b.toString(); reference.getProperties().put("url", url); return reference; } @Override public void logout() throws OAuthException { oAuthHandler.deleteToken(); } public OAuth2Handler getHandler(){ return oAuthHandler; } protected void setHandler(OAuth2Handler handler){ this.oAuthHandler = handler; } }