Skip to content

Commit e1142ef

Browse files
authored
Check for not HTTPS instead of is HTTP (Azure#37454)
Check for not HTTPS instead of HTTP
1 parent aa3a102 commit e1142ef

File tree

8 files changed

+158
-215
lines changed

8 files changed

+158
-215
lines changed

sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CustomBearerTokenAuthenticationPolicy.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
public class CustomBearerTokenAuthenticationPolicy implements HttpPipelinePolicy {
2424
private static final ClientLogger LOGGER = new ClientLogger(CustomBearerTokenAuthenticationPolicy.class);
2525
private static final String BEARER = "Bearer";
26+
private static final HttpHeaderName X_FORWARDED_HOST = HttpHeaderName.fromString("X-FORWARDED-HOST");
2627

2728
private final String[] scopes;
2829
private final String acsEndpoint;
@@ -92,10 +93,11 @@ public boolean authorizeRequestOnChallengeSync(HttpPipelineCallContext context,
9293

9394
@Override
9495
public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
95-
addHeaders(context.getHttpRequest().getHeaders());
96-
if ("http".equals(context.getHttpRequest().getUrl().getProtocol())) {
96+
if (!"https".equals(context.getHttpRequest().getUrl().getProtocol())) {
9797
return Mono.error(new RuntimeException("token credentials require a URL using the HTTPS protocol scheme"));
9898
}
99+
addHeaders(context.getHttpRequest().getHeaders());
100+
99101
HttpPipelineNextPolicy nextPolicy = next.clone();
100102

101103
return authorizeRequest(context)
@@ -125,11 +127,12 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
125127

126128
@Override
127129
public HttpResponse processSync(HttpPipelineCallContext context, HttpPipelineNextSyncPolicy next) {
128-
addHeaders(context.getHttpRequest().getHeaders());
129-
if ("http".equals(context.getHttpRequest().getUrl().getProtocol())) {
130+
if (!"https".equals(context.getHttpRequest().getUrl().getProtocol())) {
130131
throw LOGGER.logExceptionAsError(
131132
new RuntimeException("token credentials require a URL using the HTTPS protocol scheme"));
132133
}
134+
addHeaders(context.getHttpRequest().getHeaders());
135+
133136
HttpPipelineNextSyncPolicy nextPolicy = next.clone();
134137

135138
authorizeRequestSync(context);
@@ -193,7 +196,7 @@ private static void setAuthorizationHeader(HttpHeaders headers, String token) {
193196

194197
private void addHeaders(HttpHeaders headers) {
195198
if (acsEndpoint != null) {
196-
headers.set(HttpHeaderName.fromString("X-FORWARDED-HOST"), acsEndpoint);
199+
headers.set(X_FORWARDED_HOST, acsEndpoint);
197200
}
198201
}
199202
}

sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/implementation/CustomHmacAuthenticationPolicy.java

Lines changed: 48 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,43 @@
22
// Licensed under the MIT License.
33
package com.azure.communication.callautomation.implementation;
44

5-
import java.net.URL;
6-
import java.nio.ByteBuffer;
7-
import java.nio.charset.StandardCharsets;
8-
import java.security.InvalidKeyException;
9-
import java.security.MessageDigest;
10-
import java.security.NoSuchAlgorithmException;
11-
import java.time.OffsetDateTime;
12-
import java.time.ZoneOffset;
13-
import java.time.format.DateTimeFormatter;
14-
import java.util.Arrays;
15-
import java.util.Base64;
16-
import java.util.HashMap;
17-
import java.util.Locale;
18-
import java.util.Map;
19-
import java.util.Objects;
20-
import java.util.stream.Collectors;
21-
225
import com.azure.core.credential.AzureKeyCredential;
6+
import com.azure.core.http.HttpHeaderName;
7+
import com.azure.core.http.HttpHeaders;
238
import com.azure.core.http.HttpPipelineCallContext;
249
import com.azure.core.http.HttpPipelineNextPolicy;
2510
import com.azure.core.http.HttpResponse;
2611
import com.azure.core.http.policy.HttpPipelinePolicy;
27-
2812
import com.azure.core.util.logging.ClientLogger;
2913
import reactor.core.Exceptions;
3014
import reactor.core.publisher.Flux;
3115
import reactor.core.publisher.Mono;
3216

3317
import javax.crypto.Mac;
3418
import javax.crypto.spec.SecretKeySpec;
19+
import java.net.URL;
20+
import java.nio.ByteBuffer;
21+
import java.nio.charset.StandardCharsets;
22+
import java.security.InvalidKeyException;
23+
import java.security.MessageDigest;
24+
import java.security.NoSuchAlgorithmException;
25+
import java.time.OffsetDateTime;
26+
import java.time.ZoneOffset;
27+
import java.time.format.DateTimeFormatter;
28+
import java.util.Base64;
29+
import java.util.Locale;
30+
import java.util.Objects;
3531

3632
/**
3733
* HttpPipelinePolicy to append CommunicationClient required headers
3834
*/
3935
public final class CustomHmacAuthenticationPolicy implements HttpPipelinePolicy {
40-
private static final String X_MS_DATE_HEADER = "x-ms-date";
41-
private static final String X_MS_STRING_TO_SIGN_HEADER = "x-ms-hmac-string-to-sign-base64";
42-
private static final String HOST_HEADER = "host";
43-
private static final String CONTENT_HASH_HEADER = "x-ms-content-sha256";
44-
// Order of the headers are important here for generating correct signature
45-
private static final String[] SIGNED_HEADERS = new String[]{X_MS_DATE_HEADER, HOST_HEADER, CONTENT_HASH_HEADER};
46-
47-
private static final String AUTHORIZATIONHEADERNAME = "Authorization";
48-
private static final String HMACSHA256FORMAT = "HMAC-SHA256 SignedHeaders=%s&Signature=%s";
36+
private static final ClientLogger LOGGER = new ClientLogger(CustomHmacAuthenticationPolicy.class);
37+
private static final HttpHeaderName X_FORWARDED_HOST = HttpHeaderName.fromString("X-FORWARDED-HOST");
38+
private static final HttpHeaderName X_MS_DATE_HEADER = HttpHeaderName.fromString("x-ms-date");
39+
private static final HttpHeaderName X_MS_STRING_TO_SIGN_HEADER
40+
= HttpHeaderName.fromString("x-ms-hmac-string-to-sign-base64");
41+
private static final HttpHeaderName CONTENT_HASH_HEADER = HttpHeaderName.fromString("x-ms-content-sha256");
4942

5043
// Previously DateTimeFormatter.RFC_1123_DATE_TIME was being used. There
5144
// was an issue with the day of month part. RFC_1123_DATE_TIME does not
@@ -58,7 +51,6 @@ public final class CustomHmacAuthenticationPolicy implements HttpPipelinePolicy
5851

5952
private final AzureKeyCredential credential;
6053
private final String acsResource;
61-
private final ClientLogger logger = new ClientLogger(CustomHmacAuthenticationPolicy.class);
6254

6355
/**
6456
* Created with a non-null client credential
@@ -77,7 +69,7 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
7769
? Flux.just(ByteBuffer.allocate(0))
7870
: context.getHttpRequest().getBody();
7971

80-
if ("http".equals(context.getHttpRequest().getUrl().getProtocol())) {
72+
if (!"https".equals(context.getHttpRequest().getUrl().getProtocol())) {
8173
return Mono.error(
8274
new RuntimeException("AzureKeyCredential requires a URL using the HTTPS protocol scheme"));
8375
}
@@ -88,13 +80,17 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
8880
.map(alternativeUrl -> (URL) alternativeUrl)
8981
.orElse(context.getHttpRequest().getUrl());
9082

91-
return appendAuthorizationHeaders(
92-
hostnameToSignWith,
93-
context.getHttpRequest().getHttpMethod().toString(),
94-
contents)
95-
.flatMap(headers -> {
96-
headers.entrySet().forEach(
97-
header -> context.getHttpRequest().setHeader(header.getKey(), header.getValue()));
83+
return contents.collect(() -> {
84+
try {
85+
return MessageDigest.getInstance("SHA-256");
86+
} catch (NoSuchAlgorithmException e) {
87+
throw LOGGER.logExceptionAsError(Exceptions.propagate(e));
88+
}
89+
}, MessageDigest::update)
90+
.flatMap(messageDigest -> {
91+
addAuthenticationHeaders(acsResource, hostnameToSignWith,
92+
context.getHttpRequest().getHttpMethod().toString(), messageDigest,
93+
context.getHttpRequest().getHeaders());
9894

9995
return next.process();
10096
});
@@ -103,38 +99,20 @@ public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineN
10399
}
104100
}
105101

106-
private Mono<Map<String, String>> appendAuthorizationHeaders(URL url, String httpMethod, Flux<ByteBuffer> contents) {
107-
return contents.collect(() -> {
108-
try {
109-
return MessageDigest.getInstance("SHA-256");
110-
} catch (NoSuchAlgorithmException e) {
111-
throw logger.logExceptionAsError(Exceptions.propagate(e));
112-
}
113-
}, MessageDigest::update)
114-
.map(messageDigest -> addAuthenticationHeaders(url, httpMethod, messageDigest));
115-
}
116-
117-
private Map<String, String> addAuthenticationHeaders(final URL url,
118-
final String httpMethod,
119-
final MessageDigest messageDigest) {
120-
final Map<String, String> headers = new HashMap<>();
121-
102+
private void addAuthenticationHeaders(String acsResource, URL url, String httpMethod,
103+
MessageDigest messageDigest, HttpHeaders headers) {
122104
final String contentHash = Base64.getEncoder().encodeToString(messageDigest.digest());
123-
headers.put("X-FORWARDED-HOST", acsResource);
124-
headers.put(HOST_HEADER, acsResource);
125-
headers.put(CONTENT_HASH_HEADER, contentHash);
126-
String utcNow = OffsetDateTime.now(ZoneOffset.UTC)
127-
.format(HMAC_DATETIMEFORMATTER_PATTERN);
128-
headers.put(X_MS_DATE_HEADER, utcNow);
129-
addSignatureHeader(url, httpMethod, headers);
130-
return headers;
105+
headers.set(X_FORWARDED_HOST, acsResource);
106+
headers.set(HttpHeaderName.HOST, acsResource);
107+
headers.set(CONTENT_HASH_HEADER, contentHash);
108+
String xMsDate = OffsetDateTime.now(ZoneOffset.UTC).format(HMAC_DATETIMEFORMATTER_PATTERN);
109+
headers.set(X_MS_DATE_HEADER, xMsDate);
110+
addSignatureHeader(url, httpMethod, headers, xMsDate, acsResource, contentHash);
131111
}
132112

133-
private void addSignatureHeader(final URL url, final String httpMethod, final Map<String, String> httpHeaders) {
134-
final String signedHeaderNames = String.join(";", SIGNED_HEADERS);
135-
final String signedHeaderValues = Arrays.stream(SIGNED_HEADERS)
136-
.map(httpHeaders::get)
137-
.collect(Collectors.joining(";"));
113+
private void addSignatureHeader(URL url, String httpMethod, HttpHeaders headers, String xMsDate, String host,
114+
String xMsContentSha256) {
115+
String signedHeaderValues = xMsDate + ";" + host + ";" + xMsContentSha256;
138116

139117
String pathAndQuery = url.getPath();
140118
if (url.getQuery() != null) {
@@ -152,13 +130,15 @@ private void addSignatureHeader(final URL url, final String httpMethod, final Ma
152130
sha256HMAC = Mac.getInstance("HmacSHA256");
153131
sha256HMAC.init(new SecretKeySpec(key, "HmacSHA256"));
154132
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
155-
throw logger.logExceptionAsError(new RuntimeException(e));
133+
throw LOGGER.logExceptionAsError(new RuntimeException(e));
156134
}
157135

158136
final String signature =
159137
Base64.getEncoder().encodeToString(sha256HMAC.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)));
160-
httpHeaders.put(AUTHORIZATIONHEADERNAME, String.format(HMACSHA256FORMAT, signedHeaderNames, signature));
161-
httpHeaders.put(X_MS_STRING_TO_SIGN_HEADER, Base64.getEncoder().encodeToString(stringToSign.getBytes(StandardCharsets.UTF_8)));
138+
String authorization = "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=" + signature;
139+
headers.set(HttpHeaderName.AUTHORIZATION, authorization);
140+
headers.set(X_MS_STRING_TO_SIGN_HEADER,
141+
Base64.getEncoder().encodeToString(stringToSign.getBytes(StandardCharsets.UTF_8)));
162142
}
163143

164144
}

0 commit comments

Comments
 (0)