com.monarchapis.client.authentication.HawkV1RequestProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rest-client Show documentation
Show all versions of rest-client Show documentation
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);
}
}
}