Package com.google.wave.api.oauth.impl

Source Code of com.google.wave.api.oauth.impl.OAuthServiceImpl

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 com.google.wave.api.oauth.impl;

import com.google.wave.api.Wavelet;
import com.google.wave.api.oauth.LoginFormHandler;
import com.google.wave.api.oauth.OAuthService;

import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import net.oauth.client.OAuthClient;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

/**
* Implements the OAuthService interface. {@link OAuthService}
*
* @author kimwhite@google.com (Kimberly White)
* @author elizabethford@google.com (Elizabeth Ford)
*/
public class OAuthServiceImpl implements OAuthService {

  /** Writes application logs. */
  private static final Logger LOG = Logger.getLogger(OAuthServiceImpl.class.getName());

  /** Key for OAuth request token query parameter. */
  private static final String TOKEN_KEY = "oauth_token";

  /** Key for OAuth callback url query parameter. */
  private static final String CALLBACK_KEY = "oauth_callback";

  /** Key to force user to enter credentials. */
  private static final String FORCE_LOGIN_KEY = "force_login";

  /** Key for HTTP GET method. */
  private static final String GET = "GET";

  /** Key for HTTP POST method. */
  private static final String POST = "POST";

  /** Key for Datastore object. Consists of wave creator id and wave id. */
  private final String userRecordKey;

  /** OpenAuth client used to negotiate request/access tokens. */
  private final OAuthClient oauthClient;

  /** OpenAuth accessor that stores request/access/secret tokens. */
  private final OAuthAccessor accessor;

  /** Persistence Manager Factory to retrieve and store Datastore objects. */
  private final PersistenceManagerFactory pmf;

  /**
   * Factory method. Initializes OAuthServiceProvider with necessary tokens and
   * urls.
   *
   * @param userRecordKey key consisting of user id and wave id.
   * @param consumerKey service provider OAuth consumer key.
   * @param consumerSecret service provider OAuth consumer secret.
   * @param requestTokenUrl url to get service provider request token.
   * @param authorizeUrl url to service provider authorize page.
   * @param callbackUrl url to callback page.
   * @param accessTokenUrl url to get service provider access token.
   * @return OAuthService instance.
   */
  public static OAuthService newInstance(String userRecordKey, String consumerKey,
      String consumerSecret, String requestTokenUrl, String authorizeUrl, String callbackUrl,
      String accessTokenUrl) {
    OAuthServiceProvider provider =
        new OAuthServiceProvider(requestTokenUrl, authorizeUrl, accessTokenUrl);
    OAuthConsumer consumer = new OAuthConsumer(callbackUrl, consumerKey, consumerSecret, provider);
    OAuthAccessor accessor = new OAuthAccessor(consumer);
    OAuthClient client = new OAuthClient(new OpenSocialHttpClient());
    PersistenceManagerFactory pmf = SingletonPersistenceManagerFactory.get();
    return new OAuthServiceImpl(accessor, client, pmf, userRecordKey);
  }

  /**
   * Initializes necessary OAuthClient and accessor objects for OAuth handling.
   *
   * @param accessor Used to store tokesn for OAuth authorization.
   * @param client Handles OAuth authorization.
   * @param pmf Manages datastore fetching and storing.
   * @param recordKey User id for datastore object.
   */
  OAuthServiceImpl(OAuthAccessor accessor, OAuthClient client,
      PersistenceManagerFactory pmf, String recordKey) {
    this.userRecordKey = recordKey;
    this.pmf = pmf;
    this.accessor = accessor;
    this.oauthClient = client;
  }

  @Override
  public boolean checkAuthorization(Wavelet wavelet, LoginFormHandler loginForm) {

    OAuthUser user = retrieveUserProfile();

    // Return true if the user already has an access token.
    if (user != null && user.getAccessToken() != null) {
      return true;
    }

    // If the user doesn't have an access token but already has a request token,
    // exchange the tokens.
    if (user != null && user.getRequestToken() != null) {
      String accessToken = exchangeTokens(user);
      if (accessToken != null) {
        // Yay, we're authorized.
        return true;
      }
    }

    // Need to login.
    String requestToken = getAndStoreRequestToken();
    LOG.info("Request token: " + requestToken);
    buildAuthUrl();
    loginForm.renderLogin(userRecordKey, wavelet);
    return false;
  }

  @Override
  public boolean hasAuthorization() {
    OAuthUser user = retrieveUserProfile();
    return (user != null && user.getAccessToken() != null);
  }

  /**
   * Applies for a request token from the service provider.
   *
   * @return the request token.
   */
  private String getAndStoreRequestToken() {
    // Get the request token.
    try {
      oauthClient.getRequestToken(accessor);
    } catch (IOException e) {
      LOG.severe("Could not reach service provider to get request token: " + e);
    } catch (OAuthException e) {
      LOG.severe("Unable to fetch request token. Authentication error: " + e);
    } catch (URISyntaxException e) {
      LOG.severe("Unable to fetch request token. Invalid url: " + e);
    }

    // Store request token in Datastore via a tokenData object.
    String requestToken = accessor.requestToken;
    storeUserProfile(new OAuthUser(userRecordKey, requestToken));

    return accessor.requestToken;
  }

  /**
   * Builds the url to authenticate the request token with necessary query
   * parameters and stores in Datastore.
   */
  private void buildAuthUrl() {
    OAuthUser userProfile = retrieveUserProfile();
    OpenSocialUrl url = new OpenSocialUrl(accessor.consumer.serviceProvider.userAuthorizationURL);
    url.addQueryStringParameter(TOKEN_KEY, userProfile.getRequestToken());
    url.addQueryStringParameter(CALLBACK_KEY, accessor.consumer.callbackURL);
    url.addQueryStringParameter(FORCE_LOGIN_KEY, "true");
    userProfile.setAuthUrl(url.toString());
    storeUserProfile(userProfile);
  }

  /**
   * Exchanges a signed request token for an access token from the service
   * provider and stores it in the user profile if access token is successfully
   * acquired.
   *
   * @return String of the access token, might return null if failed.
   */
  private String exchangeTokens(OAuthUser userProfile) {
    // Re-initialize an accessor with the request token and secret token.
    // Request token needs to be in access token field for exchange to work.
    accessor.accessToken = userProfile.getRequestToken();
    accessor.tokenSecret = accessor.consumer.consumerSecret;

    // Perform the exchange.
    String accessToken = null;
    String tokenSecret = null;
    try {
      OAuthMessage message =
          oauthClient.invoke(accessor, GET, accessor.consumer.serviceProvider.accessTokenURL, null);
      accessToken = message.getToken();
      tokenSecret = message.getParameter(OAuth.OAUTH_TOKEN_SECRET);
    } catch (IOException e) {
      LOG.warning("Failed to retrieve access token: " + e.getMessage());
    } catch (OAuthException e) {
      LOG.warning("Failed to retrieve access token: " + e.getMessage());
    } catch (URISyntaxException e) {
      throw new RuntimeException(e);
    }

    if (accessToken != null) {
      // Store the access token in the user profile object and put profile back
      // in the datastore.
      userProfile.setAccessToken(accessToken);
      userProfile.setTokenSecret(tokenSecret);
      storeUserProfile(userProfile);
    }
    return accessToken;
  }

  @Override
  public String post(String url, Map<String, String> parameters) throws OAuthServiceException {
    return requestResources(url, POST, parameters);
  }

  @Override
  public String get(String url, Map<String, String> parameters) throws OAuthServiceException {
    return requestResources(url, GET, parameters);
  }

  /**
   * Get secure resources from the service provider.
   *
   * @param url service provider resource url.
   * @param method Http method.
   * @param parameters service provider parameters.
   * @return String of the service provider response message.
   * @throws OAuthServiceException the HTTP response code was not OK
   */
  private String requestResources(String url, String method, Map<String, String> parameters)
      throws OAuthServiceException {

    // Convert parameters to OAuth parameters.
    Collection<OAuth.Parameter> queryParameters = new ArrayList<OAuth.Parameter>();
    for (Map.Entry<String, String> parameter : parameters.entrySet()) {
      queryParameters.add(new OAuth.Parameter(parameter.getKey(), parameter.getValue()));
    }

    // Set the accessor's access token with the access token in Datastore.
    OAuthUser userProfile = retrieveUserProfile();
    accessor.accessToken = userProfile.getAccessToken();
    accessor.tokenSecret = userProfile.getTokenSecret();

    // Send request and receive response from service provider.
    String messageString = "";
    OAuthMessage message;
    try {
      message = oauthClient.invoke(accessor, method, url, queryParameters);
      messageString = message.readBodyAsString();
    } catch (IOException e) {
      LOG.severe("Response message has no body: " + e);
      throw new OAuthServiceException(e);
    } catch (URISyntaxException e) {
      LOG.severe("Unable to fetch resources. Invalid url: " + e);
      throw new OAuthServiceException(e);
    } catch (OAuthException e){
      throw new OAuthServiceException(e);
    }
    return messageString;
  }

  /**
   * Stores user-specific oauth token information in Datastore.
   *
   * @param user profile consisting of user's request token, access token, and
   *        consumer secret.
   */
  private void storeUserProfile(OAuthUser user) {
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      pm.makePersistent(user);
    } finally {
      pm.close();
    }
  }

  /**
   * Retrieves user's oauth information from Datastore.
   *
   * @return the user profile (or null if not found).
   */
  private OAuthUser retrieveUserProfile() {
    PersistenceManager pm = pmf.getPersistenceManager();
    OAuthUser userProfile = null;
    try {
      userProfile = pm.getObjectById(OAuthUser.class, userRecordKey);
    } catch (JDOObjectNotFoundException e) {
      LOG.info("Datastore object not yet initialized with key: " + userRecordKey);
    } finally {
      pm.close();
    }
    return userProfile;
  }
}
TOP

Related Classes of com.google.wave.api.oauth.impl.OAuthServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.