Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,59 +91,7 @@ public String getToken(Request request) throws IOException {
}
return this.currentToken;
}
public CompletableFuture<String> GetTokenAsync() throws IOException, URISyntaxException {
return this.GetTokenAsync(false);
}

/**
* Apply the credentials to the HTTP request.
* @param request The HTTP request.
*/
public CompletableFuture<Response> ProcessHttpRequestAsync(boolean applyCredentials, String httpVerb, String url) throws InvalidParameterException, IOException, URISyntaxException {
return ProcessHttpRequestAsync(applyCredentials, httpVerb, url, null);
}
public CompletableFuture<Response> ProcessHttpRequestAsync(boolean applyCredentials, String httpVerb, String url, RequestBody body) throws InvalidParameterException, IOException, URISyntaxException {
Request.Builder httpRequestBuilder = new Request.Builder();
switch (httpVerb.toLowerCase()) {
case "get":
httpRequestBuilder.get();
break;
case "post":
if (body == null)
throw new InvalidParameterException("Attempting to POST with no body provided");
httpRequestBuilder.post(body);
break;
case "delete":
if (body == null)
httpRequestBuilder.delete();
else
httpRequestBuilder.delete(body);
break;

default:
throw new InvalidParameterException(String.format("Do not support %s http verb yet", httpVerb));

}
httpRequestBuilder.url(url);

// Resolve the token if required
if (ShouldSetToken(url))
httpRequestBuilder.addHeader("Authorization", await(GetTokenAsync()));

Request request = httpRequestBuilder.build();

// Convert to CompletableFuture
OkHttpClient client = this.client;
if (applyCredentials) {
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
this.applyCredentialsFilter(clientBuilder);
client = clientBuilder.build();
}
Call call = client.newCall(request);
ResponseFuture result = new ResponseFuture(call);
call.enqueue(result);
return result.future;
}


private boolean ShouldSetToken(String url)
Expand All @@ -157,85 +105,6 @@ private boolean ShouldSetToken(String url)



public CompletableFuture<String> GetTokenAsync(boolean forceRefresh) throws IOException, URISyntaxException {
if (forceRefresh == false) {
// check the global cache for the token. If we have it, and it's valid, we're done.
OAuthResponse oAuthToken = null;
boolean found = false;
synchronized (this.cacheSync) {
if (this.cache.containsKey(this.getTokenCacheKey())) {
oAuthToken = this.cache.get(this.getTokenCacheKey());
found = true;
}
}
// we have the token. Is it valid?
if (found && oAuthToken.getExpirationTime().getMillis() > DateTime.now(DateTimeZone.UTC).getMillis())
{
return completedFuture(oAuthToken.getAccessToken());
}
}
// We need to refresh the token, because:
// 1. The user requested it via the forceRefresh parameter
// 2. We have it, but it's expired
// 3. We don't have it in the cache.

OAuthResponse token = await(this.RefreshTokenAsync());
synchronized (cacheSync)
{
this.cache.put(getTokenCacheKey(), token);
}

return completedFuture(token.getAccessToken());
}

private CompletableFuture<Response> PostAsync(String endpoint, HashMap<String, String> content) throws JsonProcessingException, URISyntaxException {
String bodyText = this.mapper.writeValueAsString(content);

RequestBody body = RequestBody.create(this.FORM_ENCODE, this.MakeFormBody(content));
Request request = new Request.Builder()
.url(endpoint)
.post(body)
.build();
Call call = client.newCall(request);
ResponseFuture result = new ResponseFuture(call);
call.enqueue(result);
return result.future;
}
private String MakeFormBody(HashMap<String, String> values) throws URISyntaxException, JsonProcessingException {
String formBody = values.keySet().stream()
.map(key -> {
try {
return key + "=" + URLEncoder.encode(values.get(key), StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
})
.collect(joining("&", "", ""));
return formBody;
}

// Corresponds to https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-authentication?view=azure-bot-service-4.0
// Step 1: Request an access token from the MSA/AAD v2 login service
private CompletableFuture<OAuthResponse> RefreshTokenAsync() throws IOException, URISyntaxException {
HashMap<String, String> content = new HashMap<String, String>();
content.put("grant_type", "client_credentials");
content.put("client_id", (this.appId==null) ? "" : this.appId);
content.put("client_secret", (this.appPassword==null) ? "" : this.appPassword );
content.put("scope", this.OAuthScope);

try (Response response = await(this.PostAsync(this.OAuthEndpoint, content)))
{
ResponseBody body = null;
if (response.code() < 200 || response.code() >= 300 )
throw new IOException(String.format("Bad response : %s", response.code()) );
body = response.body();
OAuthResponse oauthresponse = this.mapper.readValue(body.string(), OAuthResponse.class);
DateTime modifiedExpiration = DateTime.now(DateTimeZone.UTC).plusSeconds(oauthresponse.getExpiresIn()).minusSeconds(60);
oauthresponse.withExpirationTime(modifiedExpiration);
return completedFuture(oauthresponse);
}
}

@Override
public void applyCredentialsFilter(OkHttpClient.Builder clientBuilder) {
clientBuilder.interceptors().add(new MicrosoftAppCredentialsInterceptor(this));
Expand Down
Loading