Skip to content

Commit

Permalink
Merge pull request #14 from jianghaolu/ua
Browse files Browse the repository at this point in the history
Fixes for user agent and authentication
  • Loading branch information
jianghaolu committed May 19, 2016
2 parents c8ecc0f + b443c0f commit 7282bf8
Show file tree
Hide file tree
Showing 19 changed files with 402 additions and 114 deletions.
2 changes: 1 addition & 1 deletion azure-android-client-authentication/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.microsoft.aad:adal:1.1.11'
compile 'com.microsoft.rest:client-runtime:1.0.0-beta1'
compile 'com.microsoft.azure:azure-client-runtime:1.0.0-SNAPSHOT'
testCompile 'junit:junit:4.12'
testCompile 'junit:junit-dep:4.11'
deployerJars "org.apache.maven.wagon:wagon-ftp:2.10"
Expand Down
2 changes: 1 addition & 1 deletion azure-client-authentication/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ checkstyle {

dependencies {
compile 'com.microsoft.azure:adal4j:1.1.2'
compile 'com.microsoft.rest:client-runtime:1.0.0-beta1'
compile 'com.microsoft.azure:azure-client-runtime:1.0.0-SNAPSHOT'
testCompile 'junit:junit:4.12'
testCompile 'junit:junit-dep:4.11'
deployerJars "org.apache.maven.wagon:wagon-ftp:2.10"
Expand Down
6 changes: 3 additions & 3 deletions azure-client-authentication/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@

<dependencies>
<dependency>
<groupId>com.microsoft.rest</groupId>
<artifactId>client-runtime</artifactId>
<version>${parent.version}</version>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-client-runtime</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.azure.AzureEnvironment;
import com.microsoft.rest.credentials.TokenCredentials;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

Expand All @@ -30,6 +34,8 @@ public class ApplicationTokenCredentials extends TokenCredentials {
private AzureEnvironment environment;
/** The current authentication result. */
private AuthenticationResult authenticationResult;
/** The default subscription to use, if any. */
private String defaultSubscription;

/**
* Initializes a new instance of the UserTokenCredentials.
Expand All @@ -52,6 +58,103 @@ public ApplicationTokenCredentials(String clientId, String domain, String secret
}
}

/**
* Contains the keys of the settings in a Properties file to read credentials from.
*/
private enum CredentialSettings {
/** The subscription GUID. */
SUBSCRIPTION_ID("subscription"),
/** The tenant GUID or domain. */
TENANT_ID("tenant"),
/** The client id for the client application. */
CLIENT_ID("client"),
/** The client secret for the service principal. */
CLIENT_KEY("key"),
/** The management endpoint. */
MANAGEMENT_URI("managementURI"),
/** The base URL to the current Azure environment. */
BASE_URL("baseURL"),
/** The URL to Active Directory authentication. */
AUTH_URL("authURL");

/** The name of the key in the properties file. */
private final String name;

CredentialSettings(String name) {
this.name = name;
}

@Override
public String toString() {
return this.name;
}
}

/**
* @return The default subscription ID, if any
*/
public String defaultSubscriptionId() {
return defaultSubscription;
}

/**
* Set default subscription ID.
*
* @param subscriptionId the default subscription ID.
* @return the credentials object itself.
*/
public ApplicationTokenCredentials withDefaultSubscriptionId(String subscriptionId) {
this.defaultSubscription = subscriptionId;
return this;
}

/**
* Initializes the credentials based on the provided credentials file.
*
* @param credentialsFile A file with credentials, using the standard Java properties format.
* and the following keys:
* subscription=<subscription-id>
* tenant=<tenant-id>
* client=<client-id>
* key=<client-key>
* managementURI=<management-URI>
* baseURL=<base-URL>
* authURL=<authentication-URL>
* @return The credentials based on the file.
* @throws IOException exception thrown from file access errors.
*/
public static ApplicationTokenCredentials fromFile(File credentialsFile) throws IOException {
// Set defaults
Properties authSettings = new Properties();
authSettings.put(CredentialSettings.AUTH_URL.toString(), AzureEnvironment.AZURE.getAuthenticationEndpoint());
authSettings.put(CredentialSettings.BASE_URL.toString(), AzureEnvironment.AZURE.getBaseUrl());
authSettings.put(CredentialSettings.MANAGEMENT_URI.toString(), AzureEnvironment.AZURE.getTokenAudience());

// Load the credentials from the file
FileInputStream credentialsFileStream = new FileInputStream(credentialsFile);
authSettings.load(credentialsFileStream);
credentialsFileStream.close();

final String clientId = authSettings.getProperty(CredentialSettings.CLIENT_ID.toString());
final String tenantId = authSettings.getProperty(CredentialSettings.TENANT_ID.toString());
final String clientKey = authSettings.getProperty(CredentialSettings.CLIENT_KEY.toString());
final String mgmtUri = authSettings.getProperty(CredentialSettings.MANAGEMENT_URI.toString());
final String authUrl = authSettings.getProperty(CredentialSettings.AUTH_URL.toString());
final String baseUrl = authSettings.getProperty(CredentialSettings.BASE_URL.toString());
final String defaultSubscriptionId = authSettings.getProperty(CredentialSettings.SUBSCRIPTION_ID.toString());

return new ApplicationTokenCredentials(
clientId,
tenantId,
clientKey,
new AzureEnvironment(
authUrl,
mgmtUri,
true,
baseUrl)
).withDefaultSubscriptionId(defaultSubscriptionId);
}

/**
* Gets the active directory application client id.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.azure.AzureEnvironment;
import com.microsoft.rest.credentials.TokenCredentials;

import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
package com.microsoft.azure.credentials;

import com.microsoft.aad.adal4j.AuthenticationResult;

import com.microsoft.azure.AzureEnvironment;
import org.junit.Assert;

import org.junit.Test;

import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

package com.microsoft.azure;

import com.microsoft.rest.RestClient;
import com.microsoft.rest.ServiceCall;
import com.microsoft.rest.ServiceCallback;
import com.microsoft.rest.ServiceException;
Expand All @@ -27,6 +26,7 @@
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Url;

/**
Expand All @@ -44,13 +44,19 @@ public class AzureClient extends AzureServiceClient {
*/
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

/**
* The user agent from the service client that owns this Azure Client.
*/
private final String serviceClientUserAgent;

/**
* Initializes an instance of this class with customized client metadata.
*
* @param restClient the REST client to connect to Azure
* @param serviceClient the caller client that initiates the asynchronous request.
*/
public AzureClient(RestClient restClient) {
super(restClient);
public AzureClient(AzureServiceClient serviceClient) {
super(serviceClient.restClient());
this.serviceClientUserAgent = serviceClient.userAgent();
}

/**
Expand Down Expand Up @@ -647,7 +653,7 @@ private Response<ResponseBody> poll(String url) throws CloudException, IOExcepti
port = endpoint.getDefaultPort();
}
AsyncService service = restClient().retrofit().create(AsyncService.class);
Response<ResponseBody> response = service.get(endpoint.getFile()).execute();
Response<ResponseBody> response = service.get(endpoint.getFile(), serviceClientUserAgent).execute();
int statusCode = response.code();
if (statusCode != 200 && statusCode != 201 && statusCode != 202 && statusCode != 204) {
CloudException exception = new CloudException(statusCode + " is not a valid polling status code");
Expand Down Expand Up @@ -684,7 +690,7 @@ private Call<ResponseBody> pollAsync(String url, final ServiceCallback<ResponseB
port = endpoint.getDefaultPort();
}
AsyncService service = restClient().retrofit().create(AsyncService.class);
Call<ResponseBody> call = service.get(endpoint.getFile());
Call<ResponseBody> call = service.get(endpoint.getFile(), serviceClientUserAgent);
call.enqueue(new ServiceResponseCallback<ResponseBody>(callback) {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Expand Down Expand Up @@ -735,7 +741,7 @@ public void setLongRunningOperationRetryTimeout(Integer longRunningOperationRetr
*/
private interface AsyncService {
@GET
Call<ResponseBody> get(@Url String url);
Call<ResponseBody> get(@Url String url, @Header("User-Agent") String userAgent);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,30 @@
*
*/

package com.microsoft.azure.credentials;
package com.microsoft.azure;

import com.microsoft.azure.serializer.AzureJacksonMapperAdapter;
import com.microsoft.rest.RestClient;

/**
* An instance of this class describes an environment in Azure.
*/
public final class AzureEnvironment {
/**
* Base URL for calls to Azure management API.
*/
private final String baseURL;

/**
* ActiveDirectory Endpoint for the Azure Environment.
*/
private String authenticationEndpoint;

/**
* Token audience for an endpoint.
*/
private String tokenAudience;

/**
* Determines whether the authentication endpoint should
* be validated with Azure AD. Default value is true.
Expand All @@ -32,11 +42,17 @@ public final class AzureEnvironment {
* @param tokenAudience token audience for an endpoint.
* @param validateAuthority whether the authentication endpoint should
* be validated with Azure AD.
* @param baseUrl the base URL for the current environment.
*/
public AzureEnvironment(String authenticationEndpoint, String tokenAudience, boolean validateAuthority) {
public AzureEnvironment(
String authenticationEndpoint,
String tokenAudience,
boolean validateAuthority,
String baseUrl) {
this.authenticationEndpoint = authenticationEndpoint;
this.tokenAudience = tokenAudience;
this.validateAuthority = validateAuthority;
this.baseURL = baseUrl;
}

/**
Expand All @@ -45,15 +61,37 @@ public AzureEnvironment(String authenticationEndpoint, String tokenAudience, boo
public static final AzureEnvironment AZURE = new AzureEnvironment(
"https://login.windows.net/",
"https://management.core.windows.net/",
true);
true,
"https://management.azure.com/");

/**
* Provides the settings for authentication with Azure China.
*/
public static final AzureEnvironment AZURE_CHINA = new AzureEnvironment(
"https://login.chinacloudapi.cn/",
"https://management.core.chinacloudapi.cn/",
true);
true,
"https://management.chinacloudapi.cn");

/**
* Gets the base URL of the management service.
*
* @return the Base URL for the management service.
*/
public String getBaseUrl() {
return this.baseURL;
}

/**
* Gets a builder for {@link RestClient}.
*
* @return a builder for the rest client.
*/
public RestClient.Builder newRestClientBuilder() {
return new RestClient.Builder(baseURL)
.withInterceptor(new RequestIdHeaderInterceptor())
.withMapperAdapter(new AzureJacksonMapperAdapter());
}

/**
* Gets the ActiveDirectory Endpoint for the Azure Environment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
public abstract class AzureServiceClient extends ServiceClient {
protected AzureServiceClient(String baseUrl) {
this(new RestClient.Builder(baseUrl)
.withInterceptor(new RequestIdHeaderInterceptor())
.withMapperAdapter(new AzureJacksonMapperAdapter()).build());
}

Expand All @@ -28,4 +29,13 @@ protected AzureServiceClient(String baseUrl) {
protected AzureServiceClient(RestClient restClient) {
super(restClient);
}

/**
* The default User-Agent header. Override this method to override the user agent.
*
* @return the user agent string.
*/
public String userAgent() {
return "Azure-SDK-For-Java/" + getClass().getPackage().getImplementationVersion();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*
*/

package com.microsoft.azure;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import java.util.UUID;

/**
* An instance of this class puts an UUID in the request header. Azure uses
* the request id as the unique identifier for
*/
public class RequestIdHeaderInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.header("x-ms-client-request-id", UUID.randomUUID().toString())
.build();
return chain.proceed(request);
}
}
Loading

0 comments on commit 7282bf8

Please sign in to comment.