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

com.here.account.auth.OAuth1Signer Maven / Gradle / Ivy

Go to download

here-oauth-client is for clients of the HERE AAA, and supports OAuth2.0 grant_types=client_credentials

The newest version!
/*
 * Copyright (c) 2016 HERE Europe B.V.
 * 
 * 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.here.account.auth;

import com.here.account.http.HttpProvider;
import com.here.account.http.HttpProvider.HttpRequest;
import com.here.account.util.Clock;
import com.here.account.util.OAuthConstants;
import com.here.account.util.SettableSystemClock;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Appends the 
 * The OAuth 1.0 Protocol 
 * signature to the HTTP request.
 * This request signer computes the signature components of the 
 * "OAuth" auth-scheme and adds them as the Authorization header value.
 * 
 * 

* See also * * HTTP Authentication Scheme Registry for a list of authschemes. * * @author kmccrack */ public class OAuth1Signer implements HttpProvider.HttpRequestAuthorizer { /** * HERE Account recommends 6-character nonces. */ private static final int NONCE_LENGTH = 6; private final Clock clock; /** * HERE client accessKeyId. Becomes the value of oauth_consumer_key in the * Authorization: OAuth header. */ private final String consumerKey; /** * HERE client accessKeySecret. Used to calculate the oauth_signature in the * Authorization: OAuth header. */ private final String consumerSecret; private final SignatureMethod signatureMethod; /** * Construct the OAuth signer based on accessKeyId and accessKeySecret. * * @param accessKeyId the HERE client accessKeyId. Becomes the value of oauth_consumer_key in * the Authorization: OAuth header. * @param accessKeySecret the HERE client accessKeySecret. Used to calculate the oauth_signature * in the Authorization: OAuth header. */ public OAuth1Signer(String accessKeyId, String accessKeySecret) { this(new SettableSystemClock(), accessKeyId, accessKeySecret); } /** * Construct the OAuth signer based on clock, accessKeyId, and accessKeySecret. * Use this if you want to inject your own clock, such as during unit tests. * * @param clock the implementation of a clock you want to use * @param accessKeyId the HERE clientId. Becomes the value of oauth_consumer_key in * the Authorization: OAuth header. * @param accessKeySecret the HERE clientSecret. Used to calculate the oauth_signature * in the Authorization: OAuth header. */ public OAuth1Signer(Clock clock, String accessKeyId, String accessKeySecret) { this(clock, accessKeyId, accessKeySecret, SignatureMethod.HMACSHA256); } /** * * @param consumerKey the identity of the caller, sent in plaintext. * Becomes the value of oauth_consumer_key in * the Authorization: OAuth header. * @param consumerSecret secret of the caller, or private key of the caller. * Used to calculate the oauth_signature * in the Authorization: OAuth header. * @param signatureMethod the choice of signature algorithm to use. */ public OAuth1Signer(String consumerKey, String consumerSecret, SignatureMethod signatureMethod) { this(new SettableSystemClock(), consumerKey, consumerSecret, signatureMethod); } /** * Construct the OAuth signer based on clock, consumerKey, consumerSecret, * and signatureMethod. * * @param clock the implementation of a clock you want to use * @param consumerKey the identity of the caller, sent in plaintext. * Becomes the value of oauth_consumer_key in * the Authorization: OAuth header. * @param consumerSecret secret of the caller, or private key of the caller. * Used to calculate the oauth_signature * in the Authorization: OAuth header. * @param signatureMethod the choice of signature algorithm to use. */ public OAuth1Signer(Clock clock, String consumerKey, String consumerSecret, SignatureMethod signatureMethod) { this.clock = clock; this.consumerKey = consumerKey; this.consumerSecret = consumerSecret; this.signatureMethod = signatureMethod; } /** * The source of entropy for OAuth1.0 nonce values. * File bytes with entropy for OAuth1.0 nonce values. * Note the OAuth1.0 spec specifically tells us we do not need to use a SecureRandom * number generator. * * @param bytes the byte array in which to stick the nonce value */ protected void nextBytes(byte[] bytes) { ThreadLocalRandom.current().nextBytes(bytes);; } /** * Extract query parameters from a raw query string. * * @param query is the raw query string as a substring from the URL. * @return map containing list of query parameters. */ protected Map> getQueryParams(String query) { Map> queryParams = new HashMap<>(); String[] kvPairs = query.split("&"); for (String kvPair : kvPairs) { int ix = kvPair.indexOf("="); String key = kvPair; String value = ""; if (ix != -1) { key = kvPair.substring(0, ix); value = kvPair.substring(ix + 1); } try { key = URLDecoder.decode(key, OAuthConstants.UTF_8_STRING); value = URLDecoder.decode(value, OAuthConstants.UTF_8_STRING); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(e); } List values = queryParams.get(key); if (values == null) { values = new ArrayList<>(); queryParams.put(key, values); } values.add(value); } return queryParams; } /** * For cases where there is no Content-Type: application/x-www-form-urlencoded, * and no request token, call this method to get the Authorization Header Value * for a single request. * *

* Computes the OAuth1 Authorization header value including all required components of the * OAuth type. * See also the OAuth 1.0 * Authorization Header * Section. * *

* Note that the client accessKeySecret, once configured on this object, does not leave this method, * as signatures are used in its place on the wire. * * @param method * @return */ private String getAuthorizationHeaderValue(String method, String url, Map> formParams) { SignatureCalculator calculator = getSignatureCalculator(); // timestamp. // the number of seconds since January 1, 1970 00:00:00 GMT long timestamp = clock.currentTimeMillis() / 1000L; // choose the first 6 chars from base64 alphabet byte[] bytes = new byte[NONCE_LENGTH]; nextBytes(bytes); String nonce = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes).substring(0, NONCE_LENGTH); int qPos = url.indexOf('?'); Map> queryParams = null; if (qPos != -1) { String query = url.substring(qPos + 1); queryParams = getQueryParams(query); url = url.substring(0, qPos); } String computedSignature = calculator.calculateSignature(method, url, timestamp, nonce, signatureMethod, formParams, queryParams); return calculator.constructAuthHeader(computedSignature, nonce, timestamp, signatureMethod); } /** * Gets the signature calculator, given that we don't use a user auth, and we do use * the configured client accessKeyId, client accessKeySecret pair. * * @return */ SignatureCalculator getSignatureCalculator() { // client accessKeyId is "Client Identifier" a.k.a. "oauth_consumer_key" in the OAuth1.0 spec // client accessKeySecret is "Client Shared-Secret" , which becomes the client shared-secret component // of the HMAC-SHA1 key per http://tools.ietf.org/html/rfc5849#section-3.4.2. SignatureCalculator calculator = new SignatureCalculator(consumerKey, consumerSecret); return calculator; } /** * {@inheritDoc} */ @Override public void authorize(HttpRequest httpRequest, String method, String url, Map> formParams) { String authorizationHeaderValue = getAuthorizationHeaderValue(method, url, formParams); httpRequest.addAuthorizationHeader(authorizationHeaderValue); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy