com.twitter.hbc.httpclient.auth.OAuth1.java Source code

Java tutorial

Introduction

Here is the source code for com.twitter.hbc.httpclient.auth.OAuth1.java

Source

/**
 * Copyright 2013 Twitter, Inc.
 * 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 com.twitter.hbc.httpclient.auth;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpHeaders;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.AbstractHttpClient;

import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.twitter.hbc.core.HttpConstants;
import com.twitter.joauth.Normalizer;
import com.twitter.joauth.OAuthParams;
import com.twitter.joauth.Request.Pair;
import com.twitter.joauth.Signer;
import com.twitter.joauth.UrlCodec;

public class OAuth1 implements Authentication {

    private final Normalizer normalizer;
    private final Signer signer;

    private final String consumerKey;
    private final String consumerSecret;
    private final String token;
    private final String tokenSecret;

    private final SecureRandom secureRandom;

    public OAuth1(String consumerKey, String consumerSecret, String token, String tokenSecret) {
        this.consumerKey = Preconditions.checkNotNull(consumerKey);
        this.consumerSecret = Preconditions.checkNotNull(consumerSecret);

        this.token = Preconditions.checkNotNull(token);
        this.tokenSecret = Preconditions.checkNotNull(tokenSecret);

        this.normalizer = Normalizer.getStandardNormalizer();
        this.signer = Signer.getStandardSigner();

        this.secureRandom = new SecureRandom();
    }

    @Override
    public void setupConnection(AbstractHttpClient client) {
    }

    @Override
    public void signRequest(HttpUriRequest request, String postParams) {
        // TODO: this is a little odd: we already encoded the values earlier, but using URLEncodedUtils.parse will decode the values,
        // which we will encode again.
        List<NameValuePair> httpGetParams = URLEncodedUtils.parse(request.getURI().getRawQuery(), Charsets.UTF_8);
        List<Pair> javaParams = new ArrayList<Pair>(httpGetParams.size());
        for (NameValuePair params : httpGetParams) {
            Pair tuple = new Pair(UrlCodec.encode(params.getName()), UrlCodec.encode(params.getValue()));
            javaParams.add(tuple);
        }

        if (postParams != null) {
            List<NameValuePair> httpPostParams = URLEncodedUtils.parse(postParams, Charsets.UTF_8);

            for (NameValuePair params : httpPostParams) {
                Pair tuple = new Pair(UrlCodec.encode(params.getName()), UrlCodec.encode(params.getValue()));
                javaParams.add(tuple);
            }
        }

        long timestampSecs = generateTimestamp();
        String nonce = generateNonce();

        OAuthParams.OAuth1Params oAuth1Params = new OAuthParams.OAuth1Params(token, consumerKey, nonce,
                timestampSecs, Long.toString(timestampSecs), "", OAuthParams.HMAC_SHA1, OAuthParams.ONE_DOT_OH);

        int port = request.getURI().getPort();
        if (port <= 0) {
            // getURI can return a -1 for a port
            if (request.getURI().getScheme().equalsIgnoreCase(HttpConstants.HTTP_SCHEME)) {
                port = HttpConstants.DEFAULT_HTTP_PORT;
            } else if (request.getURI().getScheme().equalsIgnoreCase(HttpConstants.HTTPS_SCHEME)) {
                port = HttpConstants.DEFAULT_HTTPS_PORT;
            } else {
                throw new IllegalStateException("Bad URI scheme: " + request.getURI().getScheme());
            }
        }

        String normalized = normalizer.normalize(request.getURI().getScheme(), request.getURI().getHost(), port,
                request.getMethod().toUpperCase(), request.getURI().getPath(), javaParams, oAuth1Params);

        String signature;
        try {
            signature = signer.getString(normalized, tokenSecret, consumerSecret);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }

        Map<String, String> oauthHeaders = new HashMap<String, String>();
        oauthHeaders.put(OAuthParams.OAUTH_CONSUMER_KEY, quoted(consumerKey));
        oauthHeaders.put(OAuthParams.OAUTH_TOKEN, quoted(token));
        oauthHeaders.put(OAuthParams.OAUTH_SIGNATURE, quoted(signature));
        oauthHeaders.put(OAuthParams.OAUTH_SIGNATURE_METHOD, quoted(OAuthParams.HMAC_SHA1));
        oauthHeaders.put(OAuthParams.OAUTH_TIMESTAMP, quoted(Long.toString(timestampSecs)));
        oauthHeaders.put(OAuthParams.OAUTH_NONCE, quoted(nonce));
        oauthHeaders.put(OAuthParams.OAUTH_VERSION, quoted(OAuthParams.ONE_DOT_OH));
        String header = Joiner.on(", ").withKeyValueSeparator("=").join(oauthHeaders);

        request.setHeader(HttpHeaders.AUTHORIZATION, "OAuth " + header);

    }

    private String quoted(String str) {
        return "\"" + str + "\"";
    }

    private long generateTimestamp() {
        long timestamp = System.currentTimeMillis();
        return timestamp / 1000;
    }

    private String generateNonce() {
        return Long.toString(Math.abs(secureRandom.nextLong())) + System.currentTimeMillis();
    }
}