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

com.monarchapis.client.authentication.HawkV1RequestProcessor Maven / Gradle / Ivy

Go to download

A Fluent API wrapper around Apache HTTP Client that handles both synchronous and asynchronous REST calls.

The newest version!
/*
 * Copyright (C) 2015 CapTech Ventures, Inc.
 * (http://www.captechconsulting.com) All Rights Reserved.
 *
 * 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.monarchapis.client.authentication;

import java.net.URI;
import java.security.MessageDigest;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import com.monarchapis.client.rest.BaseClient;
import com.monarchapis.client.rest.RequestProcessor;
import com.monarchapis.common.util.HmacUtils;

public class HawkV1RequestProcessor implements RequestProcessor {
	private String apiKey;
	private String sharedSecret;
	private String algorithm;
	private boolean requestPayloadVerification = true;
	private AccessTokenSource accessTokenSource;

	public HawkV1RequestProcessor(String apiKey, String sharedSecret, String algorithm) {
		this(apiKey, sharedSecret, algorithm, null);
	}

	public HawkV1RequestProcessor(String apiKey, String sharedSecret, String algorithm,
			AccessTokenSource accessTokenSource) {
		if (StringUtils.isBlank(apiKey)) {
			throw new IllegalArgumentException("apiKey must not be blank or null");
		}

		if (StringUtils.isBlank(sharedSecret)) {
			throw new IllegalArgumentException("sharedSecret must not be blank or null");
		}

		if (StringUtils.isBlank(algorithm)) {
			throw new IllegalArgumentException("algorithm must not be blank or null");
		}

		this.apiKey = apiKey;
		this.sharedSecret = sharedSecret;
		this.algorithm = algorithm;
		this.accessTokenSource = accessTokenSource;
	}

	@Override
	public void processRequest(BaseClient client) {
		String accessToken = null;

		if (accessTokenSource != null) {
			accessToken = accessTokenSource.getAccessToken();
		}

		String payloadHash = requestPayloadVerification ? getHawkHash(client) : null;
		String header = getHawkHeader(client, accessToken, payloadHash, null);
		client.authorization(header);
	}

	private static String getHawkHash(BaseClient client) {
		try {
			StringBuilder sb = new StringBuilder();
			String httpContent = client.getBody();
			String mimeType = "";
			String content = "";

			if (httpContent != null) {
				mimeType = StringUtils.trimToEmpty(StringUtils.substringBefore(client.getContentType(), ";"));
				content = httpContent;
			}

			sb.append("hawk.1.payload\n");
			sb.append(mimeType);
			sb.append("\n");
			sb.append(content);
			sb.append("\n");

			MessageDigest digest = MessageDigest.getInstance("SHA-256");
			byte[] hash = digest.digest(sb.toString().getBytes("UTF-8"));
			return Base64.encodeBase64String(hash);
		} catch (Exception e) {
			throw new RuntimeException("Could not create hawk hash", e);
		}
	}

	private String getHawkHeader(BaseClient client, String accessToken, String payloadHash, String extData) {
		try {
			StringBuilder sb = new StringBuilder();

			long ts = System.currentTimeMillis() / 1000;
			String nonce = RandomStringUtils.randomAlphanumeric(6);

			URI uri = URI.create(client.getUrl());

			sb.append("hawk.1.header\n");
			sb.append(ts);
			sb.append("\n");
			sb.append(nonce);
			sb.append("\n");
			sb.append(client.getMethod());
			sb.append("\n");
			sb.append(uri.getRawPath());
			sb.append("\n");
			sb.append(uri.getHost());
			sb.append("\n");
			sb.append(uri.getPort());
			sb.append("\n");

			if (payloadHash != null) {
				sb.append(payloadHash);
			}

			sb.append("\n");

			if (extData != null) {
				sb.append(extData);
			}

			sb.append("\n");

			if (accessToken != null) {
				sb.append(apiKey);
				sb.append("\n");
			}

			String stringData = sb.toString();

			String algo = HmacUtils.getHMacAlgorithm(algorithm);
			byte[] key = sharedSecret.getBytes();
			SecretKeySpec signingKey = new SecretKeySpec(key, algo);

			Mac mac256 = Mac.getInstance(algo);
			mac256.init(signingKey);

			// compute the hmac on input data bytes
			byte[] hash = mac256.doFinal(stringData.getBytes("UTF-8"));
			String mac = Base64.encodeBase64String(hash);

			return "Hawk id=\"" + (accessToken != null ? accessToken : apiKey) + "\", ts=\"" + ts + "\", nonce=\""
					+ nonce + "\"" + (payloadHash != null ? ", hash=\"" + payloadHash + "\"" : "")
					+ (extData != null ? ", ext=\"" + extData + "\"," : "") + ", mac=\"" + mac + "\""
					+ (accessToken != null ? ", app=\"" + apiKey + "\"" : "");
		} catch (Exception e) {
			throw new RuntimeException("Could not create hawk header", e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy