All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oauth.signpost.AbstractOAuthProvider Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/*
 * Copyright (c) 2009 Matthias Kaeppler 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 oauth.signpost;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.exception.OAuthNotAuthorizedException;
import oauth.signpost.http.HttpParameters;
import oauth.signpost.http.HttpRequest;
import oauth.signpost.http.HttpResponse;

/**
 * ABC for all provider implementations. If you're writing a custom provider,
 * you will probably inherit from this class, since it takes a lot of work from
 * you.
 * 
 * @author Matthias Kaeppler
 */
public abstract class AbstractOAuthProvider implements OAuthProvider {

    private static final long serialVersionUID = 1L;

    private String requestTokenEndpointUrl;

    private String accessTokenEndpointUrl;

    private String authorizationWebsiteUrl;

    private HttpParameters responseParameters;

    private Map defaultHeaders;

    private boolean isOAuth10a;

    private transient OAuthProviderListener listener;

    public AbstractOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl,
            String authorizationWebsiteUrl) {
        this.requestTokenEndpointUrl = requestTokenEndpointUrl;
        this.accessTokenEndpointUrl = accessTokenEndpointUrl;
        this.authorizationWebsiteUrl = authorizationWebsiteUrl;
        this.responseParameters = new HttpParameters();
        this.defaultHeaders = new HashMap();
    }

    public synchronized String retrieveRequestToken(OAuthConsumer consumer, String callbackUrl,
            String... customOAuthParams) throws OAuthMessageSignerException,
            OAuthNotAuthorizedException, OAuthExpectationFailedException,
            OAuthCommunicationException {

        // invalidate current credentials, if any
        consumer.setTokenWithSecret(null, null);

        // 1.0a expects the callback to be sent while getting the request token.
        // 1.0 service providers would simply ignore this parameter.
        HttpParameters params = new HttpParameters();
        params.putAll(customOAuthParams, true);
        params.put(OAuth.OAUTH_CALLBACK, callbackUrl, true);

        retrieveToken(consumer, requestTokenEndpointUrl, params);

        String callbackConfirmed = responseParameters.getFirst(OAuth.OAUTH_CALLBACK_CONFIRMED);
        responseParameters.remove(OAuth.OAUTH_CALLBACK_CONFIRMED);
        isOAuth10a = Boolean.TRUE.toString().equals(callbackConfirmed);

        // 1.0 service providers expect the callback as part of the auth URL,
        // Do not send when 1.0a.
        if (isOAuth10a) {
            return OAuth.addQueryParameters(authorizationWebsiteUrl, OAuth.OAUTH_TOKEN,
                consumer.getToken());
        } else {
            return OAuth.addQueryParameters(authorizationWebsiteUrl, OAuth.OAUTH_TOKEN,
                consumer.getToken(), OAuth.OAUTH_CALLBACK, callbackUrl);
        }
    }

    public synchronized void retrieveAccessToken(OAuthConsumer consumer, String oauthVerifier,
            String... customOAuthParams) throws OAuthMessageSignerException,
            OAuthNotAuthorizedException, OAuthExpectationFailedException,
            OAuthCommunicationException {

        if (consumer.getToken() == null || consumer.getTokenSecret() == null) {
            throw new OAuthExpectationFailedException(
                    "Authorized request token or token secret not set. "
                            + "Did you retrieve an authorized request token before?");
        }

        HttpParameters params = new HttpParameters();
        params.putAll(customOAuthParams, true);

        if (isOAuth10a && oauthVerifier != null) {
            params.put(OAuth.OAUTH_VERIFIER, oauthVerifier, true);
        }
        retrieveToken(consumer, accessTokenEndpointUrl, params);
    }

    /**
     * 

* Implemented by subclasses. The responsibility of this method is to * contact the service provider at the given endpoint URL and fetch a * request or access token. What kind of token is retrieved solely depends * on the URL being used. *

*

* Correct implementations of this method must guarantee the following * post-conditions: *

    *
  • the {@link OAuthConsumer} passed to this method must have a valid * {@link OAuth#OAUTH_TOKEN} and {@link OAuth#OAUTH_TOKEN_SECRET} set by * calling {@link OAuthConsumer#setTokenWithSecret(String, String)}
  • *
  • {@link #getResponseParameters()} must return the set of query * parameters served by the service provider in the token response, with all * OAuth specific parameters being removed
  • *
*

* * @param consumer * the {@link OAuthConsumer} that should be used to sign the request * @param endpointUrl * the URL at which the service provider serves the OAuth token that * is to be fetched * @param customOAuthParams * you can pass custom OAuth parameters here (such as oauth_callback * or oauth_verifier) which will go directly into the signer, i.e. * you don't have to put them into the request first. * @throws OAuthMessageSignerException * if signing the token request fails * @throws OAuthCommunicationException * if a network communication error occurs * @throws OAuthNotAuthorizedException * if the server replies 401 - Unauthorized * @throws OAuthExpectationFailedException * if an expectation has failed, e.g. because the server didn't * reply in the expected format */ protected void retrieveToken(OAuthConsumer consumer, String endpointUrl, HttpParameters customOAuthParams) throws OAuthMessageSignerException, OAuthCommunicationException, OAuthNotAuthorizedException, OAuthExpectationFailedException { Map defaultHeaders = getRequestHeaders(); if (consumer.getConsumerKey() == null || consumer.getConsumerSecret() == null) { throw new OAuthExpectationFailedException("Consumer key or secret not set"); } HttpRequest request = null; HttpResponse response = null; try { request = createRequest(endpointUrl); for (String header : defaultHeaders.keySet()) { request.setHeader(header, defaultHeaders.get(header)); } if (customOAuthParams != null && !customOAuthParams.isEmpty()) { consumer.setAdditionalParameters(customOAuthParams); } if (this.listener != null) { this.listener.prepareRequest(request); } consumer.sign(request); if (this.listener != null) { this.listener.prepareSubmission(request); } response = sendRequest(request); int statusCode = response.getStatusCode(); boolean requestHandled = false; if (this.listener != null) { requestHandled = this.listener.onResponseReceived(request, response); } if (requestHandled) { return; } if (statusCode >= 300) { handleUnexpectedResponse(statusCode, response); } HttpParameters responseParams = OAuth.decodeForm(response.getContent()); String token = responseParams.getFirst(OAuth.OAUTH_TOKEN); String secret = responseParams.getFirst(OAuth.OAUTH_TOKEN_SECRET); responseParams.remove(OAuth.OAUTH_TOKEN); responseParams.remove(OAuth.OAUTH_TOKEN_SECRET); setResponseParameters(responseParams); if (token == null || secret == null) { throw new OAuthExpectationFailedException( "Request token or token secret not set in server reply. " + "The service provider you use is probably buggy."); } consumer.setTokenWithSecret(token, secret); } catch (OAuthNotAuthorizedException e) { throw e; } catch (OAuthExpectationFailedException e) { throw e; } catch (Exception e) { throw new OAuthCommunicationException(e); } finally { try { closeConnection(request, response); } catch (Exception e) { throw new OAuthCommunicationException(e); } } } protected void handleUnexpectedResponse(int statusCode, HttpResponse response) throws Exception { if (response == null) { return; } BufferedReader reader = new BufferedReader(new InputStreamReader(response.getContent())); StringBuilder responseBody = new StringBuilder(); String line = reader.readLine(); while (line != null) { responseBody.append(line); line = reader.readLine(); } switch (statusCode) { case 401: throw new OAuthNotAuthorizedException(responseBody.toString()); default: throw new OAuthCommunicationException("Service provider responded in error: " + statusCode + " (" + response.getReasonPhrase() + ")", responseBody.toString()); } } /** * Overrride this method if you want to customize the logic for building a * request object for the given endpoint URL. * * @param endpointUrl * the URL to which the request will go * @return the request object * @throws Exception * if something breaks */ protected abstract HttpRequest createRequest(String endpointUrl) throws Exception; /** * Override this method if you want to customize the logic for how the given * request is sent to the server. * * @param request * the request to send * @return the response to the request * @throws Exception * if something breaks */ protected abstract HttpResponse sendRequest(HttpRequest request) throws Exception; /** * Called when the connection is being finalized after receiving the * response. Use this to do any cleanup / resource freeing. * * @param request * the request that has been sent * @param response * the response that has been received * @throws Exception * if something breaks */ protected void closeConnection(HttpRequest request, HttpResponse response) throws Exception { // NOP } public HttpParameters getResponseParameters() { return responseParameters; } /** * Returns a single query parameter as served by the service provider in a * token reply. You must call {@link #setResponseParameters} with the set of * parameters before using this method. * * @param key * the parameter name * @return the parameter value */ protected String getResponseParameter(String key) { return responseParameters.getFirst(key); } public void setResponseParameters(HttpParameters parameters) { this.responseParameters = parameters; } public void setOAuth10a(boolean isOAuth10aProvider) { this.isOAuth10a = isOAuth10aProvider; } public boolean isOAuth10a() { return isOAuth10a; } public String getRequestTokenEndpointUrl() { return this.requestTokenEndpointUrl; } public String getAccessTokenEndpointUrl() { return this.accessTokenEndpointUrl; } public String getAuthorizationWebsiteUrl() { return this.authorizationWebsiteUrl; } public void setRequestHeader(String header, String value) { defaultHeaders.put(header, value); } public Map getRequestHeaders() { return defaultHeaders; } public void setListener(OAuthProviderListener listener) { this.listener = listener; } public void removeListener(OAuthProviderListener listener) { this.listener = null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy