diff --git a/README.md b/README.md
index a103c05a..0ea970a4 100644
--- a/README.md
+++ b/README.md
@@ -12,25 +12,29 @@ Quick links:
| --- | --- | --- | --- |
## Install
-Current version - 1.2.0
+
+The library supports the following Java environments:
+- Java 8 (or higher)
+
+Current version - 1.3.0
You can find the changes for each version in the [change log](https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/master/changelog.txt).
You can get the msal4j package through Maven or Gradle.
### Maven
-
+Find [the latest package in the Maven repository](https://mvnrepository.com/artifact/com.microsoft.azure/msal4j).
```
com.microsoft.azure
msal4j
- 1.2.0
+ 1.3.0
```
### Gradle
```
-compile group: 'com.microsoft.azure', name: 'msal4j', version: '1.2.0'
+compile group: 'com.microsoft.azure', name: 'msal4j', version: '1.3.0'
```
## Usage
diff --git a/changelog.txt b/changelog.txt
index b99f5ee8..edeab1d3 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,9 @@
+Version 1.3.0
+=============
+- Added option to pass in AAD instance discovery data
+- Removed runtime dependency on commons-codec.commons-codec, org.apache.commons.commons-text, org.apache.httpcomponents.httpclient, com.google.code.gson
+- Added runtime dependency on com.fasterxml.jackson.databind
+
Version 1.2.0
=============
- Added support for ADFS 2019
diff --git a/lombok.config b/lombok.config
new file mode 100644
index 00000000..f902278d
--- /dev/null
+++ b/lombok.config
@@ -0,0 +1 @@
+lombok.anyConstructor.addConstructorProperties=true
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index cf5940a9..40bb2d4b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.microsoft.azure
msal4j
- 1.2.0
+ 1.3.0
jar
msal4j
@@ -38,33 +38,31 @@
oauth2-oidc-sdk
6.5
-
- com.google.code.gson
- gson
- 2.8.5
-
org.slf4j
slf4j-api
- 1.7.21
-
-
- commons-codec
- commons-codec
- 1.11
-
-
- org.apache.commons
- commons-text
- 1.7
+ 1.7.28
org.projectlombok
lombok
1.18.6
+ provided
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.10.1
+
+
+
+ org.apache.commons
+ commons-text
+ 1.7
+ test
+
org.testng
testng
@@ -99,6 +97,7 @@
org.apache.httpcomponents
httpclient
4.5.9
+ test
com.microsoft.azure
diff --git a/src/integrationtest/java/labapi/App.java b/src/integrationtest/java/labapi/App.java
index 21d8a1a0..be3830b8 100644
--- a/src/integrationtest/java/labapi/App.java
+++ b/src/integrationtest/java/labapi/App.java
@@ -3,28 +3,28 @@
package labapi;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
@Getter
public class App {
- @SerializedName("appType")
+ @JsonProperty("appType")
String appType;
- @SerializedName("appName")
+ @JsonProperty("appName")
String appName;
- @SerializedName("appId")
+ @JsonProperty("appId")
String appId;
- @SerializedName("redirectUri")
+ @JsonProperty("redirectUri")
String redirectUri;
- @SerializedName("authority")
+ @JsonProperty("authority")
String authority;
- @SerializedName("labName")
+ @JsonProperty("labName")
String labName;
}
diff --git a/src/integrationtest/java/labapi/Lab.java b/src/integrationtest/java/labapi/Lab.java
index bd365bac..bae558e8 100644
--- a/src/integrationtest/java/labapi/Lab.java
+++ b/src/integrationtest/java/labapi/Lab.java
@@ -3,26 +3,26 @@
package labapi;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
@Getter
public class Lab {
- @SerializedName("labName")
+ @JsonProperty("labName")
String labName;
- @SerializedName("domain")
+ @JsonProperty("domain")
String domain;
- @SerializedName("tenantId")
+ @JsonProperty("tenantId")
String tenantId;
- @SerializedName("federationProvider")
+ @JsonProperty("federationProvider")
String federationProvider;
- @SerializedName("azureEnvironment")
+ @JsonProperty("azureEnvironment")
String azureEnvironment;
- @SerializedName("authority")
+ @JsonProperty("authority")
String authority;
}
diff --git a/src/integrationtest/java/labapi/LabService.java b/src/integrationtest/java/labapi/LabService.java
index 029fa18f..57898afd 100644
--- a/src/integrationtest/java/labapi/LabService.java
+++ b/src/integrationtest/java/labapi/LabService.java
@@ -3,7 +3,9 @@
package labapi;
-import com.google.gson.Gson;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.aad.msal4j.*;
import java.net.MalformedURLException;
@@ -16,6 +18,17 @@ public class LabService {
static ConfidentialClientApplication labApp;
+ static ObjectMapper mapper = new ObjectMapper()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+ static T convertJsonToObject(final String json, final Class clazz) {
+ try {
+ return mapper.readValue(json, clazz);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("JsonProcessingException: " + e.getMessage(), e);
+ }
+ }
+
static void initLabApp() throws MalformedURLException {
KeyVaultSecretsProvider keyVaultSecretsProvider = new KeyVaultSecretsProvider();
@@ -44,7 +57,7 @@ User getUser(UserQueryParameters query){
String result = HttpClientHelper.sendRequestToLab(
LabConstants.LAB_USER_ENDPOINT, queryMap, getLabAccessToken());
- User[] users = new Gson().fromJson(result, User[].class);
+ User[] users = convertJsonToObject(result, User[].class);
User user = users[0];
user.setPassword(getUserSecret(user.getLabName()));
if (query.parameters.containsKey(UserQueryParameters.FEDERATION_PROVIDER)) {
@@ -62,7 +75,7 @@ public static App getApp(String appId){
try {
String result = HttpClientHelper.sendRequestToLab(
LabConstants.LAB_APP_ENDPOINT, appId, getLabAccessToken());
- App[] apps = new Gson().fromJson(result, App[].class);
+ App[] apps = convertJsonToObject(result, App[].class);
return apps[0];
} catch (Exception ex) {
throw new RuntimeException("Error getting app from lab: " + ex.getMessage());
@@ -74,7 +87,7 @@ public static Lab getLab(String labId) {
try {
result = HttpClientHelper.sendRequestToLab(
LabConstants.LAB_LAB_ENDPOINT, labId, getLabAccessToken());
- Lab[] labs = new Gson().fromJson(result, Lab[].class);
+ Lab[] labs = convertJsonToObject(result, Lab[].class);
return labs[0];
} catch (Exception ex) {
throw new RuntimeException("Error getting lab from lab: " + ex.getMessage());
@@ -89,7 +102,7 @@ private String getUserSecret(String labName){
result = HttpClientHelper.sendRequestToLab(
LabConstants.LAB_USER_SECRET_ENDPOINT, queryMap, getLabAccessToken());
- return new Gson().fromJson(result, UserSecret.class).value;
+ return convertJsonToObject(result, UserSecret.class).value;
} catch (Exception ex) {
throw new RuntimeException("Error getting user secret from lab: " + ex.getMessage());
}
diff --git a/src/integrationtest/java/labapi/User.java b/src/integrationtest/java/labapi/User.java
index d9decfa9..ead4be82 100644
--- a/src/integrationtest/java/labapi/User.java
+++ b/src/integrationtest/java/labapi/User.java
@@ -3,53 +3,53 @@
package labapi;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
public class User
{
- @SerializedName("appId")
+ @JsonProperty("appId")
private String appId;
- @SerializedName("objectId")
+ @JsonProperty("objectId")
private String objectId;
- @SerializedName("userType")
+ @JsonProperty("userType")
private String userType;
- @SerializedName("displayName")
+ @JsonProperty("displayName")
private String displayName;
- @SerializedName("licenses")
+ @JsonProperty("licenses")
private String licenses;
- @SerializedName("upn")
+ @JsonProperty("upn")
private String upn;
- @SerializedName("mfa")
+ @JsonProperty("mfa")
private String mfa;
- @SerializedName("protectionPolicy")
+ @JsonProperty("protectionPolicy")
private String protectionPolicy;
- @SerializedName("homeDomain")
+ @JsonProperty("homeDomain")
private String homeDomain;
- @SerializedName("homeUPN")
+ @JsonProperty("homeUPN")
private String homeUPN;
- @SerializedName("b2cProvider")
+ @JsonProperty("b2cProvider")
private String b2cProvider;
- @SerializedName("labName")
+ @JsonProperty("labName")
private String labName;
- @SerializedName("lastUpdatedBy")
+ @JsonProperty("lastUpdatedBy")
private String lastUpdatedBy;
- @SerializedName("lastUpdatedDate")
+ @JsonProperty("lastUpdatedDate")
private String lastUpdatedDate;
@Setter
diff --git a/src/integrationtest/java/labapi/UserSecret.java b/src/integrationtest/java/labapi/UserSecret.java
index 0a74f561..e33f47e2 100644
--- a/src/integrationtest/java/labapi/UserSecret.java
+++ b/src/integrationtest/java/labapi/UserSecret.java
@@ -3,13 +3,13 @@
package labapi;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
public class UserSecret {
- @SerializedName("secret")
+ @JsonProperty("secret")
String secret;
- @SerializedName("value")
+ @JsonProperty("value")
String value;
}
diff --git a/src/integrationtest/java/labapi/UserType.java b/src/integrationtest/java/labapi/UserType.java
index 0ff84d9f..45000479 100644
--- a/src/integrationtest/java/labapi/UserType.java
+++ b/src/integrationtest/java/labapi/UserType.java
@@ -3,8 +3,6 @@
package labapi;
-import com.google.gson.annotations.SerializedName;
-
public class UserType {
public static final String CLOUD = "cloud";
public static final String FEDERATED = "federated";
diff --git a/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscovery.java b/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryProvider.java
similarity index 55%
rename from src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscovery.java
rename to src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryProvider.java
index e6a8ff6e..84bab38d 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscovery.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryProvider.java
@@ -3,9 +3,6 @@
package com.microsoft.aad.msal4j;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
@@ -13,11 +10,17 @@
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
-class AadInstanceDiscovery {
- private static final Logger log = LoggerFactory.getLogger(AadInstanceDiscovery.class);
+class AadInstanceDiscoveryProvider {
+
+ private final static String DEFAULT_TRUSTED_HOST = "login.microsoftonline.com";
+ private final static String AUTHORIZE_ENDPOINT_TEMPLATE = "https://{host}/{tenant}/oauth2/v2.0/authorize";
+ private final static String INSTANCE_DISCOVERY_ENDPOINT_TEMPLATE = "https://{host}/common/discovery/instance";
+ private final static String INSTANCE_DISCOVERY_REQUEST_PARAMETERS_TEMPLATE = "?api-version=1.1&authorization_endpoint={authorizeEndpoint}";
final static TreeSet TRUSTED_HOSTS_SET = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+ static ConcurrentHashMap cache = new ConcurrentHashMap<>();
+
static {
TRUSTED_HOSTS_SET.addAll(Arrays.asList(
"login.windows.net",
@@ -28,14 +31,19 @@ class AadInstanceDiscovery {
"login.microsoftonline.us"));
}
- private final static String DEFAULT_TRUSTED_HOST = "login.microsoftonline.com";
+ static InstanceDiscoveryMetadataEntry getMetadataEntry(URL authorityUrl,
+ boolean validateAuthority,
+ MsalRequest msalRequest,
+ ServiceBundle serviceBundle) {
- private final static String AUTHORIZE_ENDPOINT_TEMPLATE = "https://{host}/{tenant}/oauth2/v2.0/authorize";
- private final static String INSTANCE_DISCOVERY_ENDPOINT_TEMPLATE = "https://{host}/common/discovery/instance";
- private final static String INSTANCE_DISCOVERY_REQUEST_PARAMETERS_TEMPLATE =
- "?api-version=1.1&authorization_endpoint={authorizeEndpoint}";
+ InstanceDiscoveryMetadataEntry result = cache.get(authorityUrl.getAuthority());
- static ConcurrentHashMap cache = new ConcurrentHashMap<>();
+ if (result == null) {
+ doInstanceDiscoveryAndCache(authorityUrl, validateAuthority, msalRequest, serviceBundle);
+ }
+
+ return cache.get(authorityUrl.getAuthority());
+ }
static Set getAliases(String host){
if(cache.containsKey(host)){
@@ -46,6 +54,38 @@ static Set getAliases(String host){
}
}
+ static AadInstanceDiscoveryResponse parseInstanceDiscoveryMetadata(String instanceDiscoveryJson) {
+
+ AadInstanceDiscoveryResponse aadInstanceDiscoveryResponse;
+ try {
+ aadInstanceDiscoveryResponse = JsonHelper.convertJsonToObject(
+ instanceDiscoveryJson,
+ AadInstanceDiscoveryResponse.class);
+
+ } catch(Exception ex){
+ throw new MsalClientException("Error parsing instance discovery response. Data must be " +
+ "in valid JSON format. For more information, see https://aka.ms/msal4j-instance-discovery",
+ AuthenticationErrorCode.INVALID_INSTANCE_DISCOVERY_METADATA);
+ }
+
+ return aadInstanceDiscoveryResponse;
+ }
+
+ static void cacheInstanceDiscoveryMetadata(String host,
+ AadInstanceDiscoveryResponse aadInstanceDiscoveryResponse) {
+
+ if (aadInstanceDiscoveryResponse.metadata() != null) {
+ for (InstanceDiscoveryMetadataEntry entry : aadInstanceDiscoveryResponse.metadata()) {
+ for (String alias: entry.aliases()) {
+ cache.put(alias, entry);
+ }
+ }
+ }
+ cache.putIfAbsent(host, InstanceDiscoveryMetadataEntry.builder().
+ preferredCache(host).
+ preferredNetwork(host).build());
+ }
+
private static String getAuthorizeEndpoint(String host, String tenant) {
return AUTHORIZE_ENDPOINT_TEMPLATE.
replace("{host}", host).
@@ -60,9 +100,9 @@ private static String getInstanceDiscoveryEndpoint(String host) {
replace("{host}", discoveryHost);
}
- private static InstanceDiscoveryResponse sendInstanceDiscoveryRequest
- (URL authorityUrl, MsalRequest msalRequest,
- ServiceBundle serviceBundle) {
+ private static AadInstanceDiscoveryResponse sendInstanceDiscoveryRequest(URL authorityUrl,
+ MsalRequest msalRequest,
+ ServiceBundle serviceBundle) {
String instanceDiscoveryRequestUrl = getInstanceDiscoveryEndpoint(authorityUrl.getAuthority()) +
INSTANCE_DISCOVERY_REQUEST_PARAMETERS_TEMPLATE.replace("{authorizeEndpoint}",
@@ -74,52 +114,32 @@ private static String getInstanceDiscoveryEndpoint(String host) {
instanceDiscoveryRequestUrl,
msalRequest.headers().getReadonlyHeaderMap());
- IHttpResponse httpResponse= HttpHelper.executeHttpRequest(httpRequest, msalRequest.requestContext(), serviceBundle);
+ IHttpResponse httpResponse= HttpHelper.executeHttpRequest(
+ httpRequest,
+ msalRequest.requestContext(),
+ serviceBundle);
- return JsonHelper.convertJsonToObject(httpResponse.body(), InstanceDiscoveryResponse.class);
+ return JsonHelper.convertJsonToObject(httpResponse.body(), AadInstanceDiscoveryResponse.class);
}
- private static void validate(InstanceDiscoveryResponse instanceDiscoveryResponse) {
- if (StringHelper.isBlank(instanceDiscoveryResponse.tenantDiscoveryEndpoint())) {
- throw new MsalServiceException(instanceDiscoveryResponse);
- }
- }
-
- private static void doInstanceDiscoveryAndCache
- (URL authorityUrl, boolean validateAuthority, MsalRequest msalRequest, ServiceBundle serviceBundle) throws Exception {
+ private static void doInstanceDiscoveryAndCache(URL authorityUrl,
+ boolean validateAuthority,
+ MsalRequest msalRequest,
+ ServiceBundle serviceBundle) {
- InstanceDiscoveryResponse instanceDiscoveryResponse =
+ AadInstanceDiscoveryResponse aadInstanceDiscoveryResponse =
sendInstanceDiscoveryRequest(authorityUrl, msalRequest, serviceBundle);
if (validateAuthority) {
- validate(instanceDiscoveryResponse);
- }
-
- cacheInstanceDiscoveryMetadata(authorityUrl.getAuthority(), instanceDiscoveryResponse);
- }
-
- static InstanceDiscoveryMetadataEntry GetMetadataEntry
- (URL authorityUrl, boolean validateAuthority, MsalRequest msalRequest, ServiceBundle serviceBundle) throws Exception {
-
- InstanceDiscoveryMetadataEntry result = cache.get(authorityUrl.getAuthority());
-
- if (result == null) {
- doInstanceDiscoveryAndCache(authorityUrl, validateAuthority, msalRequest, serviceBundle);
+ validate(aadInstanceDiscoveryResponse);
}
- return cache.get(authorityUrl.getAuthority());
+ cacheInstanceDiscoveryMetadata(authorityUrl.getAuthority(), aadInstanceDiscoveryResponse);
}
- private static void cacheInstanceDiscoveryMetadata(String host, InstanceDiscoveryResponse instanceDiscoveryResponse) {
- if (instanceDiscoveryResponse.metadata() != null) {
- for (InstanceDiscoveryMetadataEntry entry : instanceDiscoveryResponse.metadata()) {
- for (String alias : entry.aliases) {
- cache.put(alias, entry);
- }
- }
+ private static void validate(AadInstanceDiscoveryResponse aadInstanceDiscoveryResponse) {
+ if (StringHelper.isBlank(aadInstanceDiscoveryResponse.tenantDiscoveryEndpoint())) {
+ throw new MsalServiceException(aadInstanceDiscoveryResponse);
}
- cache.putIfAbsent(host, InstanceDiscoveryMetadataEntry.builder().
- preferredCache(host).
- preferredNetwork(host).build());
}
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryResponse.java b/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryResponse.java
similarity index 62%
rename from src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryResponse.java
rename to src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryResponse.java
index c98eba4f..c940c24d 100644
--- a/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryResponse.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryResponse.java
@@ -3,30 +3,30 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.Accessors;
@Accessors(fluent = true)
@Getter(AccessLevel.PACKAGE)
-class InstanceDiscoveryResponse {
+class AadInstanceDiscoveryResponse {
- @SerializedName("tenant_discovery_endpoint")
+ @JsonProperty("tenant_discovery_endpoint")
private String tenantDiscoveryEndpoint;
- @SerializedName("metadata")
+ @JsonProperty("metadata")
private InstanceDiscoveryMetadataEntry[] metadata;
- @SerializedName("error_description")
+ @JsonProperty("error_description")
private String errorDescription;
- @SerializedName("error_codes")
+ @JsonProperty("error_codes")
private long[] errorCodes;
- @SerializedName("error")
+ @JsonProperty("error")
private String error;
- @SerializedName("correlation_id")
+ @JsonProperty("correlation_id")
private String correlationId;
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/AccessTokenCacheEntity.java b/src/main/java/com/microsoft/aad/msal4j/AccessTokenCacheEntity.java
index 17062226..9ce03de4 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AccessTokenCacheEntity.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AccessTokenCacheEntity.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -16,22 +16,22 @@
@Setter
class AccessTokenCacheEntity extends Credential {
- @SerializedName("credential_type")
+ @JsonProperty("credential_type")
private String credentialType;
- @SerializedName("realm")
+ @JsonProperty("realm")
protected String realm;
- @SerializedName("target")
+ @JsonProperty("target")
private String target;
- @SerializedName("cached_at")
+ @JsonProperty("cached_at")
private String cachedAt;
- @SerializedName("expires_on")
+ @JsonProperty("expires_on")
private String expiresOn;
- @SerializedName("extended_expires_on")
+ @JsonProperty("extended_expires_on")
private String extExpiresOn;
String getKey() {
diff --git a/src/main/java/com/microsoft/aad/msal4j/AccountCacheEntity.java b/src/main/java/com/microsoft/aad/msal4j/AccountCacheEntity.java
index c22b4e47..23ba4113 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AccountCacheEntity.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AccountCacheEntity.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import lombok.experimental.Accessors;
@@ -20,33 +20,33 @@ class AccountCacheEntity implements Serializable {
static final String MSSTS_ACCOUNT_TYPE = "MSSTS";
static final String ADFS_ACCOUNT_TYPE = "ADFS";
- @SerializedName("home_account_id")
+ @JsonProperty("home_account_id")
protected String homeAccountId;
- @SerializedName("environment")
+ @JsonProperty("environment")
protected String environment;
@EqualsAndHashCode.Exclude
- @SerializedName("realm")
+ @JsonProperty("realm")
protected String realm;
- @SerializedName("local_account_id")
+ @JsonProperty("local_account_id")
protected String localAccountId;
- @SerializedName("username")
+ @JsonProperty("username")
protected String username;
- @SerializedName("name")
+ @JsonProperty("name")
protected String name;
- @SerializedName("client_info")
+ @JsonProperty("client_info")
protected String clientInfoStr;
ClientInfo clientInfo() {
return ClientInfo.createFromJson(clientInfoStr);
}
- @SerializedName("authority_type")
+ @JsonProperty("authority_type")
protected String authorityType;
String getKey() {
diff --git a/src/main/java/com/microsoft/aad/msal4j/AccountsSupplier.java b/src/main/java/com/microsoft/aad/msal4j/AccountsSupplier.java
index dcc58f4a..92eaf642 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AccountsSupplier.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AccountsSupplier.java
@@ -23,11 +23,11 @@ class AccountsSupplier implements Supplier> {
public Set get() {
try {
InstanceDiscoveryMetadataEntry instanceDiscoveryData =
- AadInstanceDiscovery.GetMetadataEntry
- (new URL(clientApplication.authority()),
- clientApplication.validateAuthority(),
- msalRequest,
- clientApplication.getServiceBundle());
+ AadInstanceDiscoveryProvider.getMetadataEntry(
+ new URL(clientApplication.authority()),
+ clientApplication.validateAuthority(),
+ msalRequest,
+ clientApplication.getServiceBundle());
return clientApplication.tokenCache.getAccounts
(clientApplication.clientId(), instanceDiscoveryData.aliases);
diff --git a/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByAuthorizationGrantSupplier.java b/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByAuthorizationGrantSupplier.java
index a967adbf..f9ad2980 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByAuthorizationGrantSupplier.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByAuthorizationGrantSupplier.java
@@ -7,11 +7,11 @@
import com.nimbusds.oauth2.sdk.AuthorizationGrant;
import com.nimbusds.oauth2.sdk.ResourceOwnerPasswordCredentialsGrant;
import com.nimbusds.oauth2.sdk.SAML2BearerGrant;
-import org.apache.commons.codec.binary.Base64;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
class AcquireTokenByAuthorizationGrantSupplier extends AuthenticationResultSupplier {
@@ -93,10 +93,10 @@ private AuthorizationGrant getSAMLAuthorizationGrant(WSTrustResponse response) t
AuthorizationGrant updatedGrant;
if (response.isTokenSaml2()) {
updatedGrant = new SAML2BearerGrant(new Base64URL(
- Base64.encodeBase64String(response.getToken().getBytes(StandardCharsets.UTF_8))));
+ Base64.getEncoder().encodeToString(response.getToken().getBytes(StandardCharsets.UTF_8))));
} else {
updatedGrant = new SAML11BearerGrant(new Base64URL(
- Base64.encodeBase64String(response.getToken()
+ Base64.getEncoder().encodeToString(response.getToken()
.getBytes(StandardCharsets.UTF_8))));
}
return updatedGrant;
diff --git a/src/main/java/com/microsoft/aad/msal4j/AppMetadataCacheEntity.java b/src/main/java/com/microsoft/aad/msal4j/AppMetadataCacheEntity.java
index 6cb2fc5b..3c1eeb45 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AppMetadataCacheEntity.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AppMetadataCacheEntity.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -18,13 +18,13 @@ class AppMetadataCacheEntity {
public static final String APP_METADATA_CACHE_ENTITY_ID = "appmetadata";
- @SerializedName("client_id")
+ @JsonProperty("client_id")
private String clientId;
- @SerializedName("environment")
+ @JsonProperty("environment")
private String environment;
- @SerializedName("family_id")
+ @JsonProperty("family_id")
private String familyId;
String getKey(){
diff --git a/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java b/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java
index d1638a81..d4cb0158 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java
@@ -46,6 +46,12 @@ public class AuthenticationErrorCode {
*/
public final static String CACHE_MISS = "cache_miss";
+ /**
+ * Not able to parse instance discovery metadata. Ensure data is in valid JSON format, and that
+ * it contains relevant fields. For more information, see https://aka.ms/msal4j-instance-discovery
+ */
+ public final static String INVALID_INSTANCE_DISCOVERY_METADATA = "invalid_instance_discovery_metadata";
+
/**
* Unknown error occurred
*/
diff --git a/src/main/java/com/microsoft/aad/msal4j/AuthenticationResult.java b/src/main/java/com/microsoft/aad/msal4j/AuthenticationResult.java
index 30381276..44885c2e 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AuthenticationResult.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AuthenticationResult.java
@@ -45,8 +45,8 @@ private IdToken getIdTokenObj() {
}
try {
String idTokenJson = JWTParser.parse(idToken).getParsedParts()[1].decodeToString();
- return JsonHelper.convertJsonToObject(idTokenJson, IdToken.class);
+ return JsonHelper.convertJsonToObject(idTokenJson, IdToken.class);
} catch (ParseException e) {
e.printStackTrace();
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/AuthenticationResultSupplier.java b/src/main/java/com/microsoft/aad/msal4j/AuthenticationResultSupplier.java
index 389dff24..60c1887e 100644
--- a/src/main/java/com/microsoft/aad/msal4j/AuthenticationResultSupplier.java
+++ b/src/main/java/com/microsoft/aad/msal4j/AuthenticationResultSupplier.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import org.apache.commons.codec.binary.Base64;
+import java.util.Base64;
import java.io.UnsupportedEncodingException;
import java.net.URI;
@@ -29,9 +29,11 @@ Authority getAuthorityWithPrefNetworkHost(String authority) throws Exception {
URL authorityUrl = new URL(authority);
InstanceDiscoveryMetadataEntry discoveryMetadataEntry =
- AadInstanceDiscovery.GetMetadataEntry
- (authorityUrl, clientApplication.validateAuthority(), msalRequest,
- clientApplication.getServiceBundle());
+ AadInstanceDiscoveryProvider.getMetadataEntry(
+ authorityUrl,
+ clientApplication.validateAuthority(),
+ msalRequest,
+ clientApplication.getServiceBundle());
URL updatedAuthorityUrl =
new URL(authorityUrl.getProtocol(), discoveryMetadataEntry.preferredNetwork, authorityUrl.getFile());
@@ -154,7 +156,7 @@ private String computeSha256Hash(String input) {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(input.getBytes("UTF-8"));
byte[] hash = digest.digest();
- return Base64.encodeBase64URLSafeString(hash);
+ return Base64.getUrlEncoder().encodeToString(hash);
}
catch (NoSuchAlgorithmException | UnsupportedEncodingException ex){
clientApplication.log.warn(LogHelper.createMessage(
diff --git a/src/main/java/com/microsoft/aad/msal4j/ClientApplicationBase.java b/src/main/java/com/microsoft/aad/msal4j/ClientApplicationBase.java
index b01202b8..4b344e54 100644
--- a/src/main/java/com/microsoft/aad/msal4j/ClientApplicationBase.java
+++ b/src/main/java/com/microsoft/aad/msal4j/ClientApplicationBase.java
@@ -28,6 +28,8 @@ abstract class ClientApplicationBase implements IClientApplicationBase {
protected Logger log;
protected ClientAuthentication clientAuthentication;
+ protected Authority authenticationAuthority;
+ private ServiceBundle serviceBundle;
@Accessors(fluent = true)
@Getter
@@ -37,8 +39,6 @@ abstract class ClientApplicationBase implements IClientApplicationBase {
@Getter
private String authority;
- protected Authority authenticationAuthority;
-
@Accessors(fluent = true)
@Getter
private boolean validateAuthority;
@@ -51,8 +51,6 @@ abstract class ClientApplicationBase implements IClientApplicationBase {
@Getter
private boolean logPii;
- private ServiceBundle serviceBundle;
-
@Accessors(fluent = true)
@Getter(AccessLevel.PACKAGE)
private Consumer>> telemetryConsumer;
@@ -77,6 +75,10 @@ abstract class ClientApplicationBase implements IClientApplicationBase {
@Getter
private String applicationVersion;
+ @Accessors(fluent = true)
+ @Getter
+ private AadInstanceDiscoveryResponse aadAadInstanceDiscoveryResponse;
+
@Override
public CompletableFuture acquireToken(AuthorizationCodeParameters parameters) {
@@ -177,7 +179,7 @@ AuthenticationResult acquireTokenCommon(MsalRequest msalRequest, Authority reque
if(authenticationAuthority.authorityType.equals(AuthorityType.AAD)){
InstanceDiscoveryMetadataEntry instanceDiscoveryMetadata =
- AadInstanceDiscovery.GetMetadataEntry(
+ AadInstanceDiscoveryProvider.getMetadataEntry(
requestAuthority.canonicalAuthorityUrl(),
validateAuthority,
msalRequest,
@@ -244,6 +246,7 @@ abstract static class Builder> {
private String applicationName;
private String applicationVersion;
private ITokenCacheAccessAspect tokenCacheAccessAspect;
+ private AadInstanceDiscoveryResponse aadInstanceDiscoveryResponse;
/**
* Constructor to create instance of Builder of client application
@@ -298,7 +301,10 @@ public T b2cAuthority(String val) throws MalformedURLException{
/**
* Set a boolean value telling the application if the authority needs to be verified
- * against a list of known authorities.
+ * against a list of known authorities. Authority is only validated when:
+ * 1 - It is an Azure Active Directory authority (not B2C or ADFS)
+ * 2 - Instance discovery metadata is not set via {@link ClientApplicationBase#aadAadInstanceDiscoveryResponse}
+ *
* The default value is true.
*
* @param val a boolean value for validateAuthority
@@ -449,6 +455,27 @@ public T setTokenCacheAccessAspect(ITokenCacheAccessAspect val) {
return self();
}
+ /**
+ * Sets instance discovery response data which will be used for determining tenant discovery
+ * endpoint and authority aliases.
+ *
+ * Note that authority validation is not done even if {@link ClientApplicationBase#validateAuthority}
+ * is set to true.
+ *
+ * For more information, see
+ * https://aka.ms/msal4j-instance-discovery
+ * @param val JSON formatted value of response from AAD instance discovery endpoint
+ * @return instance of the Builder on which method was called
+ */
+ public T aadInstanceDiscoveryResponse(String val) {
+ validateNotNull("aadInstanceDiscoveryResponse", val);
+
+ aadInstanceDiscoveryResponse =
+ AadInstanceDiscoveryProvider.parseInstanceDiscoveryMetadata(val);
+
+ return self();
+ }
+
private static Authority createDefaultAADAuthority() {
Authority authority;
try {
@@ -481,5 +508,12 @@ private static Authority createDefaultAADAuthority() {
new TelemetryManager(telemetryConsumer, builder.onlySendFailureTelemetry));
authenticationAuthority = builder.authenticationAuthority;
tokenCache = new TokenCache(builder.tokenCacheAccessAspect);
+ aadAadInstanceDiscoveryResponse = builder.aadInstanceDiscoveryResponse;
+
+ if(aadAadInstanceDiscoveryResponse != null){
+ AadInstanceDiscoveryProvider.cacheInstanceDiscoveryMetadata(
+ authenticationAuthority.host,
+ aadAadInstanceDiscoveryResponse);
+ }
}
}
\ No newline at end of file
diff --git a/src/main/java/com/microsoft/aad/msal4j/ClientCertificate.java b/src/main/java/com/microsoft/aad/msal4j/ClientCertificate.java
index c5e3a40f..37d93722 100644
--- a/src/main/java/com/microsoft/aad/msal4j/ClientCertificate.java
+++ b/src/main/java/com/microsoft/aad/msal4j/ClientCertificate.java
@@ -22,7 +22,7 @@
import lombok.Getter;
import lombok.experimental.Accessors;
-import org.apache.commons.codec.binary.Base64;
+import java.util.Base64;
final class ClientCertificate implements IClientCertificate {
@@ -72,12 +72,12 @@ else if("sun.security.mscapi.RSAPrivateKey".equals(key.getClass().getName()) ||
public String publicCertificateHash()
throws CertificateEncodingException, NoSuchAlgorithmException {
- return Base64.encodeBase64String(ClientCertificate
+ return Base64.getEncoder().encodeToString(ClientCertificate
.getHash(this.publicCertificate.getEncoded()));
}
public String publicCertificate() throws CertificateEncodingException {
- return Base64.encodeBase64String(this.publicCertificate.getEncoded());
+ return Base64.getEncoder().encodeToString(this.publicCertificate.getEncoded());
}
static ClientCertificate create(final InputStream pkcs12Certificate, final String password)
diff --git a/src/main/java/com/microsoft/aad/msal4j/ClientInfo.java b/src/main/java/com/microsoft/aad/msal4j/ClientInfo.java
index 098b54bd..2f7ee222 100644
--- a/src/main/java/com/microsoft/aad/msal4j/ClientInfo.java
+++ b/src/main/java/com/microsoft/aad/msal4j/ClientInfo.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.nimbusds.jose.util.StandardCharset;
import lombok.AccessLevel;
import lombok.Getter;
@@ -13,10 +13,10 @@
@Getter(AccessLevel.PACKAGE)
class ClientInfo {
- @SerializedName("uid")
+ @JsonProperty("uid")
private String uniqueIdentifier;
- @SerializedName("utid")
+ @JsonProperty("utid")
private String unqiueTenantIdentifier;
public static ClientInfo createFromJson(String clientInfoJsonBase64Encoded){
diff --git a/src/main/java/com/microsoft/aad/msal4j/Credential.java b/src/main/java/com/microsoft/aad/msal4j/Credential.java
index ca2370f9..b73c7d67 100644
--- a/src/main/java/com/microsoft/aad/msal4j/Credential.java
+++ b/src/main/java/com/microsoft/aad/msal4j/Credential.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -13,15 +13,15 @@
@Setter
class Credential {
- @SerializedName("home_account_id")
+ @JsonProperty("home_account_id")
protected String homeAccountId;
- @SerializedName("environment")
+ @JsonProperty("environment")
protected String environment;
- @SerializedName("client_id")
+ @JsonProperty("client_id")
protected String clientId;
- @SerializedName("secret")
+ @JsonProperty("secret")
protected String secret;
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/DeviceCode.java b/src/main/java/com/microsoft/aad/msal4j/DeviceCode.java
index 548f8702..8af17104 100644
--- a/src/main/java/com/microsoft/aad/msal4j/DeviceCode.java
+++ b/src/main/java/com/microsoft/aad/msal4j/DeviceCode.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
@@ -20,37 +20,37 @@ public final class DeviceCode {
/**
* code which user needs to provide when authenticating at the verification URI
*/
- @SerializedName("user_code")
+ @JsonProperty("user_code")
private String userCode;
/**
* code which should be included in the request for the access token
*/
- @SerializedName("device_code")
+ @JsonProperty("device_code")
private String deviceCode;
/**
* URI where user can authenticate
*/
- @SerializedName("verification_uri")
+ @JsonProperty("verification_uri")
private String verificationUri;
/**
* expiration time of device code in seconds.
*/
- @SerializedName("expires_in")
+ @JsonProperty("expires_in")
private long expiresIn;
/**
* interval at which the STS should be polled at
*/
- @SerializedName("interval")
+ @JsonProperty("interval")
private long interval;
/**
* message which should be displayed to the user.
*/
- @SerializedName("message")
+ @JsonProperty("message")
private String message;
@Getter(AccessLevel.PROTECTED)
diff --git a/src/main/java/com/microsoft/aad/msal4j/ErrorResponse.java b/src/main/java/com/microsoft/aad/msal4j/ErrorResponse.java
index 7ecede74..064215e7 100644
--- a/src/main/java/com/microsoft/aad/msal4j/ErrorResponse.java
+++ b/src/main/java/com/microsoft/aad/msal4j/ErrorResponse.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -16,27 +16,27 @@ class ErrorResponse {
private Integer statusCode;
private String statusMessage;
- @SerializedName("error")
+ @JsonProperty("error")
protected String error;
- @SerializedName("error_description")
+ @JsonProperty("error_description")
protected String errorDescription;
- @SerializedName("error_codes")
+ @JsonProperty("error_codes")
protected long[] errorCodes;
- @SerializedName("suberror")
+ @JsonProperty("suberror")
protected String subError;
- @SerializedName("trace_id")
+ @JsonProperty("trace_id")
protected String traceId;
- @SerializedName("timestamp")
+ @JsonProperty("timestamp")
protected String timestamp;
- @SerializedName("correlation_id")
+ @JsonProperty("correlation_id")
protected String correlation_id;
- @SerializedName("claims")
+ @JsonProperty("claims")
private String claims;
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/Event.java b/src/main/java/com/microsoft/aad/msal4j/Event.java
index 6baf2598..330ae60f 100644
--- a/src/main/java/com/microsoft/aad/msal4j/Event.java
+++ b/src/main/java/com/microsoft/aad/msal4j/Event.java
@@ -8,7 +8,6 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
-import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@@ -45,7 +44,7 @@ static String scrubTenant(URI uri){
if(!uri.isAbsolute()){
throw new IllegalArgumentException("Requires an absolute URI");
}
- if(!AadInstanceDiscovery.TRUSTED_HOSTS_SET.contains(uri.getHost())){
+ if(!AadInstanceDiscoveryProvider.TRUSTED_HOSTS_SET.contains(uri.getHost())){
return null;
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/IdToken.java b/src/main/java/com/microsoft/aad/msal4j/IdToken.java
index ead4e635..b5ee6a0a 100644
--- a/src/main/java/com/microsoft/aad/msal4j/IdToken.java
+++ b/src/main/java/com/microsoft/aad/msal4j/IdToken.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.nimbusds.jwt.JWTClaimsSet;
import java.text.ParseException;
@@ -23,40 +23,40 @@ class IdToken {
static final String UPN = "upn";
static final String UNIQUE_NAME = "unique_name";
- @SerializedName("iss")
+ @JsonProperty("iss")
protected String issuer;
- @SerializedName("sub")
+ @JsonProperty("sub")
protected String subject;
- @SerializedName("aud")
+ @JsonProperty("aud")
protected String audience ;
- @SerializedName("exp")
+ @JsonProperty("exp")
protected Long expirationTime;
- @SerializedName("iat")
+ @JsonProperty("iat")
protected Long issuedAt;
- @SerializedName("nbf")
+ @JsonProperty("nbf")
protected Long notBefore;
- @SerializedName("name")
+ @JsonProperty("name")
protected String name;
- @SerializedName("preferred_username")
+ @JsonProperty("preferred_username")
protected String preferredUsername;
- @SerializedName("oid")
+ @JsonProperty("oid")
protected String objectIdentifier;
- @SerializedName("tid")
+ @JsonProperty("tid")
protected String tenantIdentifier;
- @SerializedName("upn")
+ @JsonProperty("upn")
protected String upn;
- @SerializedName("unique_name")
+ @JsonProperty("unique_name")
protected String uniqueName;
static IdToken createFromJWTClaims(final JWTClaimsSet claims) throws ParseException {
diff --git a/src/main/java/com/microsoft/aad/msal4j/IdTokenCacheEntity.java b/src/main/java/com/microsoft/aad/msal4j/IdTokenCacheEntity.java
index 5aae730e..21052f8a 100644
--- a/src/main/java/com/microsoft/aad/msal4j/IdTokenCacheEntity.java
+++ b/src/main/java/com/microsoft/aad/msal4j/IdTokenCacheEntity.java
@@ -3,9 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
-import com.microsoft.aad.msal4j.Constants;
-import com.microsoft.aad.msal4j.Credential;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -18,10 +16,10 @@
@Setter
class IdTokenCacheEntity extends Credential {
- @SerializedName("credential_type")
+ @JsonProperty("credential_type")
private String credentialType;
- @SerializedName("realm")
+ @JsonProperty("realm")
protected String realm;
String getKey(){
diff --git a/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryMetadataEntry.java b/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryMetadataEntry.java
index e0f12cea..a8a52a57 100644
--- a/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryMetadataEntry.java
+++ b/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryMetadataEntry.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
@@ -16,25 +16,12 @@
@Builder
class InstanceDiscoveryMetadataEntry {
- @SerializedName("preferred_network")
+ @JsonProperty("preferred_network")
String preferredNetwork;
- @SerializedName("preferred_cache")
+ @JsonProperty("preferred_cache")
String preferredCache;
- @SerializedName("aliases")
+ @JsonProperty("aliases")
Set aliases;
-
- public static class InstanceDiscoveryMetadataEntryBuilder{
- public InstanceDiscoveryMetadataEntryBuilder aliases(String[] aliasesArray) {
- Set set = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
-
- if(aliasesArray != null){
- set.addAll(Arrays.asList(aliasesArray));
- }
- aliases = Collections.unmodifiableSet(set);
-
- return this;
- }
- }
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/JsonHelper.java b/src/main/java/com/microsoft/aad/msal4j/JsonHelper.java
index 53634c9c..d453d285 100644
--- a/src/main/java/com/microsoft/aad/msal4j/JsonHelper.java
+++ b/src/main/java/com/microsoft/aad/msal4j/JsonHelper.java
@@ -3,25 +3,30 @@
package com.microsoft.aad.msal4j;
-import java.io.Reader;
-import java.io.StringReader;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.json.JsonReadFeature;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-/**
- *
- */
class JsonHelper {
- /**
- *
- * @param json
- * @param clazz
- * @return
- */
+ static ObjectMapper mapper;
+
+ static {
+ mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ }
+
static T convertJsonToObject(final String json, final Class clazz) {
- final Reader reader = new StringReader(json);
- final Gson gson = new GsonBuilder().create();
- return gson.fromJson(reader, clazz);
+ try {
+ return mapper.readValue(json, clazz);
+ } catch (JsonProcessingException e) {
+ throw new MsalClientException(e);
+ }
}
}
diff --git a/src/main/java/com/microsoft/aad/msal4j/MsalServiceException.java b/src/main/java/com/microsoft/aad/msal4j/MsalServiceException.java
index 8c8aa3a4..61d7b36b 100644
--- a/src/main/java/com/microsoft/aad/msal4j/MsalServiceException.java
+++ b/src/main/java/com/microsoft/aad/msal4j/MsalServiceException.java
@@ -79,7 +79,7 @@ public MsalServiceException(
* Initializes a new instance of the exception class
* @param discoveryResponse response object from instance discovery network call
*/
- public MsalServiceException(final InstanceDiscoveryResponse discoveryResponse){
+ public MsalServiceException(final AadInstanceDiscoveryResponse discoveryResponse){
super(discoveryResponse.errorDescription(), discoveryResponse.error());
this.correlationId = discoveryResponse.correlationId();
diff --git a/src/main/java/com/microsoft/aad/msal4j/RefreshTokenCacheEntity.java b/src/main/java/com/microsoft/aad/msal4j/RefreshTokenCacheEntity.java
index ce619b00..cd9be21e 100644
--- a/src/main/java/com/microsoft/aad/msal4j/RefreshTokenCacheEntity.java
+++ b/src/main/java/com/microsoft/aad/msal4j/RefreshTokenCacheEntity.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -16,10 +16,10 @@
@Setter
class RefreshTokenCacheEntity extends Credential {
- @SerializedName("credential_type")
+ @JsonProperty("credential_type")
private String credentialType;
- @SerializedName("family_id")
+ @JsonProperty("family_id")
private String family_id;
boolean isFamilyRT(){
diff --git a/src/main/java/com/microsoft/aad/msal4j/RemoveAccountRunnable.java b/src/main/java/com/microsoft/aad/msal4j/RemoveAccountRunnable.java
index 1651a117..6979b02e 100644
--- a/src/main/java/com/microsoft/aad/msal4j/RemoveAccountRunnable.java
+++ b/src/main/java/com/microsoft/aad/msal4j/RemoveAccountRunnable.java
@@ -21,7 +21,8 @@ class RemoveAccountRunnable implements Runnable {
@Override
public void run() {
try {
- Set aliases = AadInstanceDiscovery.getAliases(clientApplication.authenticationAuthority.host());
+ Set aliases = AadInstanceDiscoveryProvider.getAliases(
+ clientApplication.authenticationAuthority.host());
clientApplication.tokenCache.removeAccount
(clientApplication.clientId(), account, aliases);
diff --git a/src/main/java/com/microsoft/aad/msal4j/TokenCache.java b/src/main/java/com/microsoft/aad/msal4j/TokenCache.java
index 63f54078..4ee6e011 100644
--- a/src/main/java/com/microsoft/aad/msal4j/TokenCache.java
+++ b/src/main/java/com/microsoft/aad/msal4j/TokenCache.java
@@ -3,9 +3,10 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.*;
-import com.google.gson.annotations.SerializedName;
-import com.google.gson.internal.LinkedTreeMap;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
@@ -38,20 +39,20 @@ public TokenCache(ITokenCacheAccessAspect tokenCacheAccessAspect) {
public TokenCache() {
}
- @SerializedName("AccessToken")
- Map accessTokens = new LinkedTreeMap<>();
+ @JsonProperty("AccessToken")
+ Map accessTokens = new LinkedHashMap<>();
- @SerializedName("RefreshToken")
- Map refreshTokens = new LinkedTreeMap<>();
+ @JsonProperty("RefreshToken")
+ Map refreshTokens = new LinkedHashMap<>();
- @SerializedName("IdToken")
- Map idTokens = new LinkedTreeMap<>();
+ @JsonProperty("IdToken")
+ Map idTokens = new LinkedHashMap<>();
- @SerializedName("Account")
- Map accounts = new LinkedTreeMap<>();
+ @JsonProperty("Account")
+ Map accounts = new LinkedHashMap<>();
- @SerializedName("AppMetadata")
- Map appMetadata = new LinkedTreeMap<>();
+ @JsonProperty("AppMetadata")
+ Map appMetadata = new LinkedHashMap<>();
transient ITokenCacheAccessAspect tokenCacheAccessAspect;
@@ -63,9 +64,8 @@ public void deserialize(String data) {
return;
}
serializedCachedSnapshot = data;
- Gson gson = new GsonBuilder().create();
- TokenCache deserializedCache = gson.fromJson(data, TokenCache.class);
+ TokenCache deserializedCache = JsonHelper.convertJsonToObject(data, TokenCache.class);
lock.writeLock().lock();
try {
@@ -79,47 +79,48 @@ public void deserialize(String data) {
}
}
- private static void mergeJsonObjects(JsonObject old, JsonObject update) {
+ private static void mergeJsonObjects(JsonNode old, JsonNode update) {
mergeRemovals(old, update);
mergeUpdates(old, update);
}
- private static void mergeUpdates(JsonObject old, JsonObject update) {
- for (Map.Entry uEntry : update.entrySet()) {
- String key = uEntry.getKey();
- JsonElement uValue = uEntry.getValue();
+ private static void mergeUpdates(JsonNode old, JsonNode update) {
+ Iterator fieldNames = update.fieldNames();
+ while (fieldNames.hasNext()) {
+ String uKey = fieldNames.next();
+ JsonNode uValue = update.get(uKey);
// add new property
- if (!old.has(key)) {
- if (!uValue.isJsonNull() &&
- !(uValue.isJsonObject() && uValue.getAsJsonObject().size() == 0)) {
- old.add(key, uValue);
+ if (!old.has(uKey)) {
+ if (!uValue.isNull() &&
+ !(uValue.isObject() && uValue.size() == 0)) {
+ ((ObjectNode)old).set(uKey, uValue);
}
}
// merge old and new property
else {
- JsonElement oValue = old.get(key);
- if (uValue.isJsonObject()) {
- mergeUpdates(oValue.getAsJsonObject(), uValue.getAsJsonObject());
+ JsonNode oValue = old.get(uKey);
+ if (uValue.isObject()) {
+ mergeUpdates(oValue, uValue);
} else {
- old.add(key, uValue);
+ ((ObjectNode)old).set(uKey, uValue);
}
}
}
}
- private static void mergeRemovals(JsonObject old, JsonObject update) {
+ private static void mergeRemovals(JsonNode old, JsonNode update) {
Set msalEntities =
new HashSet<>(Arrays.asList("Account", "AccessToken", "RefreshToken", "IdToken", "AppMetadata"));
for (String msalEntity : msalEntities) {
- JsonObject oldEntries = old.getAsJsonObject(msalEntity);
- JsonObject newEntries = update.getAsJsonObject(msalEntity);
+ JsonNode oldEntries = old.get(msalEntity);
+ JsonNode newEntries = update.get(msalEntity);
if (oldEntries != null) {
- Iterator> iterator = oldEntries.entrySet().iterator();
+ Iterator> iterator = oldEntries.fields();
while (iterator.hasNext()) {
- Map.Entry oEntry = iterator.next();
+ Map.Entry oEntry = iterator.next();
String key = oEntry.getKey();
if (newEntries == null || !newEntries.has(key)) {
@@ -135,15 +136,18 @@ public String serialize() {
lock.readLock().lock();
try {
if (!StringHelper.isBlank(serializedCachedSnapshot)) {
- JsonObject cache = new JsonParser().parse(serializedCachedSnapshot).getAsJsonObject();
- JsonObject update = new Gson().toJsonTree(this).getAsJsonObject();
+ JsonNode cache = JsonHelper.mapper.readTree(serializedCachedSnapshot);
+ JsonNode update = JsonHelper.mapper.valueToTree(this);
mergeJsonObjects(cache, update);
- return cache.toString();
+ return JsonHelper.mapper.writeValueAsString(cache);
}
- return new GsonBuilder().create().toJson(this);
- } finally {
+ return JsonHelper.mapper.writeValueAsString(this);
+ }
+ catch (JsonProcessingException e) {
+ throw new MsalClientException(e);
+ }finally {
lock.readLock().unlock();
}
}
@@ -454,12 +458,16 @@ private boolean isMatchingScopes(AccessTokenCacheEntity accessTokenCacheEntity,
).findAny();
}
- AuthenticationResult getCachedAuthenticationResult
- (IAccount account, Authority authority, Set scopes, String clientId) {
+ AuthenticationResult getCachedAuthenticationResult(
+ IAccount account,
+ Authority authority,
+ Set scopes,
+ String clientId) {
+
AuthenticationResult.AuthenticationResultBuilder builder = AuthenticationResult.builder();
builder.environment(authority.host());
- Set environmentAliases = AadInstanceDiscovery.getAliases(account.environment());
+ Set environmentAliases = AadInstanceDiscoveryProvider.getAliases(account.environment());
try (CacheAspect cacheAspect = new CacheAspect(
TokenCacheAccessContext.builder().
@@ -517,11 +525,14 @@ private boolean isMatchingScopes(AccessTokenCacheEntity accessTokenCacheEntity,
return builder.build();
}
- AuthenticationResult getCachedAuthenticationResult
- (Authority authority, Set scopes, String clientId) {
+ AuthenticationResult getCachedAuthenticationResult(
+ Authority authority,
+ Set scopes,
+ String clientId) {
+
AuthenticationResult.AuthenticationResultBuilder builder = AuthenticationResult.builder();
- Set environmentAliases = AadInstanceDiscovery.getAliases(authority.host);
+ Set environmentAliases = AadInstanceDiscoveryProvider.getAliases(authority.host);
builder.environment(authority.host());
try (CacheAspect cacheAspect = new CacheAspect(
diff --git a/src/main/java/com/microsoft/aad/msal4j/UserDiscoveryResponse.java b/src/main/java/com/microsoft/aad/msal4j/UserDiscoveryResponse.java
index 26b15742..f4cbcdc6 100644
--- a/src/main/java/com/microsoft/aad/msal4j/UserDiscoveryResponse.java
+++ b/src/main/java/com/microsoft/aad/msal4j/UserDiscoveryResponse.java
@@ -3,7 +3,7 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.annotations.SerializedName;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.Accessors;
@@ -12,22 +12,22 @@
@Getter(AccessLevel.PACKAGE)
class UserDiscoveryResponse {
- @SerializedName("ver")
+ @JsonProperty("ver")
private float version;
- @SerializedName("account_type")
+ @JsonProperty("account_type")
private String accountType;
- @SerializedName("federation_metadata_url")
+ @JsonProperty("federation_metadata_url")
private String federationMetadataUrl;
- @SerializedName("federation_protocol")
+ @JsonProperty("federation_protocol")
private String federationProtocol;
- @SerializedName("federation_active_auth_url")
+ @JsonProperty("federation_active_auth_url")
private String federationActiveAuthUrl;
- @SerializedName("cloud_audience_urn")
+ @JsonProperty("cloud_audience_urn")
private String cloudAudienceUrn;
boolean isAccountFederated() {
diff --git a/src/main/java/com/microsoft/aad/msal4j/WSTrustRequest.java b/src/main/java/com/microsoft/aad/msal4j/WSTrustRequest.java
index adf9b8df..17be34fe 100644
--- a/src/main/java/com/microsoft/aad/msal4j/WSTrustRequest.java
+++ b/src/main/java/com/microsoft/aad/msal4j/WSTrustRequest.java
@@ -3,8 +3,6 @@
package com.microsoft.aad.msal4j;
-import org.apache.commons.text.StringEscapeUtils;
-
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -186,6 +184,32 @@ static StringBuilder buildMessage(String address, String username,
return messageBuilder;
}
+ static String escapeXMLElementData(String data){
+ StringBuilder sb = new StringBuilder();
+ for(char ch : data.toCharArray()){
+ switch (ch){
+ case '<':
+ sb.append("<");
+ break;
+ case '>':
+ sb.append(">");
+ break;
+ case '\"':
+ sb.append(""");
+ break;
+ case '\'':
+ sb.append("'");
+ break;
+ case '&':
+ sb.append("&");
+ break;
+ default:
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
private static StringBuilder buildSecurityHeader(
StringBuilder securityHeaderBuilder, String username,
String password, WSTrustVersion version) {
@@ -193,8 +217,8 @@ private static StringBuilder buildSecurityHeader(
StringBuilder messageCredentialsBuilder = new StringBuilder(
MAX_EXPECTED_MESSAGE_SIZE);
String guid = UUID.randomUUID().toString();
- username = StringEscapeUtils.escapeXml10(username);
- password = StringEscapeUtils.escapeXml10(password);
+ username = escapeXMLElementData(username);
+ password = escapeXMLElementData(password);
DateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
diff --git a/src/samples/msal-b2c-web-sample/pom.xml b/src/samples/msal-b2c-web-sample/pom.xml
index d6255c87..ae544f7b 100644
--- a/src/samples/msal-b2c-web-sample/pom.xml
+++ b/src/samples/msal-b2c-web-sample/pom.xml
@@ -23,7 +23,7 @@
com.microsoft.azure
msal4j
- 1.2.0
+ 1.3.0
com.nimbusds
diff --git a/src/samples/msal-obo-sample/pom.xml b/src/samples/msal-obo-sample/pom.xml
index ce0e3e5b..151c4d6d 100644
--- a/src/samples/msal-obo-sample/pom.xml
+++ b/src/samples/msal-obo-sample/pom.xml
@@ -23,7 +23,7 @@
com.microsoft.azure
msal4j
- 1.2.0
+ 1.3.0
com.nimbusds
diff --git a/src/samples/msal-web-sample/pom.xml b/src/samples/msal-web-sample/pom.xml
index cf874d9b..947e215c 100644
--- a/src/samples/msal-web-sample/pom.xml
+++ b/src/samples/msal-web-sample/pom.xml
@@ -23,7 +23,7 @@
com.microsoft.azure
msal4j
- 1.2.0
+ 1.3.0
com.nimbusds
diff --git a/src/test/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryTest.java b/src/test/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryTest.java
new file mode 100644
index 00000000..774a23b4
--- /dev/null
+++ b/src/test/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryTest.java
@@ -0,0 +1,138 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.aad.msal4j;
+
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.net.URL;
+
+@PrepareForTest(AadInstanceDiscoveryProvider.class)
+public class AadInstanceDiscoveryTest extends PowerMockTestCase {
+
+ @BeforeMethod
+ public void setup(){
+ AadInstanceDiscoveryProvider.cache.clear();
+ }
+
+ @Test
+ public void aadInstanceDiscoveryTest_NotSetByDeveloper() throws Exception {
+ PublicClientApplication app = PublicClientApplication.builder("client_id")
+ .correlationId("correlation_id")
+ .authority("https://login.microsoftonline.com/my_tenant")
+ .build();
+
+ AuthorizationCodeParameters parameters = AuthorizationCodeParameters.builder(
+ "code", new URI("http://my.redirect.com")).build();
+
+ MsalRequest msalRequest = new AuthorizationCodeRequest(
+ parameters,
+ app,
+ new RequestContext(app, PublicApi.ACQUIRE_TOKEN_BY_AUTHORIZATION_CODE));
+
+ URL authority = new URL(app.authority());
+
+ String instanceDiscoveryData = TestHelper.readResource(
+ this.getClass(),
+ "/instance_discovery_data/aad_instance_discovery_response_valid.json");
+
+ AadInstanceDiscoveryResponse expectedResponse = JsonHelper.convertJsonToObject(
+ instanceDiscoveryData,
+ AadInstanceDiscoveryResponse.class);
+
+ PowerMock.mockStaticPartial(AadInstanceDiscoveryProvider.class, "sendInstanceDiscoveryRequest");
+
+ PowerMock.expectPrivate(
+ AadInstanceDiscoveryProvider.class,
+ "sendInstanceDiscoveryRequest",
+ authority,
+ msalRequest,
+ app.getServiceBundle()).andReturn(expectedResponse);
+
+ PowerMock.replay(AadInstanceDiscoveryProvider.class);
+
+ InstanceDiscoveryMetadataEntry entry = AadInstanceDiscoveryProvider.getMetadataEntry(
+ new URL(app.authority()),
+ false,
+ msalRequest,
+ app.getServiceBundle());
+
+ PowerMock.verify(AadInstanceDiscoveryProvider.class);
+
+ Assert.assertEquals(entry.preferredNetwork(), "login.microsoftonline.com");
+ Assert.assertEquals(entry.preferredCache(), "login.windows.net");
+ Assert.assertEquals(entry.aliases().size(), 4);
+ Assert.assertTrue(entry.aliases().contains("login.microsoftonline.com"));
+ Assert.assertTrue(entry.aliases().contains("login.windows.net"));
+ Assert.assertTrue(entry.aliases().contains("login.microsoft.com"));
+ Assert.assertTrue(entry.aliases().contains("sts.windows.net"));
+ }
+
+ @Test
+ public void aadInstanceDiscoveryTest_responseSetByDeveloper_validResponse() throws Exception{
+
+ String instanceDiscoveryResponse = TestHelper.readResource(
+ this.getClass(),
+ "/instance_discovery_data/aad_instance_discovery_response_valid.json");
+
+ PublicClientApplication app = PublicClientApplication.builder("client_id")
+ .aadInstanceDiscoveryResponse(instanceDiscoveryResponse)
+ .build();
+
+ AuthorizationCodeParameters parameters = AuthorizationCodeParameters.builder(
+ "code", new URI("http://my.redirect.com")).build();
+
+ MsalRequest msalRequest = new AuthorizationCodeRequest(
+ parameters,
+ app,
+ new RequestContext(app, PublicApi.ACQUIRE_TOKEN_BY_AUTHORIZATION_CODE));
+
+ URL authority = new URL(app.authority());
+
+ PowerMock.mockStaticPartial(
+ AadInstanceDiscoveryProvider.class,
+ "sendInstanceDiscoveryRequest");
+
+ // throw exception if we try to get metadata from network.
+ PowerMock.expectPrivate(
+ AadInstanceDiscoveryProvider.class,
+ "sendInstanceDiscoveryRequest",
+ authority,
+ msalRequest,
+ app.getServiceBundle()).andThrow(new AssertionError()).anyTimes();
+
+ PowerMock.replay(AadInstanceDiscoveryProvider.class);
+
+ InstanceDiscoveryMetadataEntry entry = AadInstanceDiscoveryProvider.getMetadataEntry(
+ authority,
+ false,
+ msalRequest,
+ app.getServiceBundle());
+
+ Assert.assertEquals(entry.preferredNetwork(), "login.microsoftonline.com");
+ Assert.assertEquals(entry.preferredCache(), "login.windows.net");
+ Assert.assertEquals(entry.aliases().size(), 4);
+ Assert.assertTrue(entry.aliases().contains("login.microsoftonline.com"));
+ Assert.assertTrue(entry.aliases().contains("login.windows.net"));
+ Assert.assertTrue(entry.aliases().contains("login.microsoft.com"));
+ Assert.assertTrue(entry.aliases().contains("sts.windows.net"));
+ }
+
+ @Test(expectedExceptions = MsalClientException.class)
+ public void aadInstanceDiscoveryTest_responseSetByDeveloper_invalidJson() throws Exception{
+
+ String instanceDiscoveryResponse = TestHelper.readResource(
+ this.getClass(),
+ "/instance_discovery_data/aad_instance_discovery_response_invalid_json.json");
+
+ PublicClientApplication app = PublicClientApplication.builder("client_id")
+ .aadInstanceDiscoveryResponse(instanceDiscoveryResponse)
+ .build();
+ }
+}
diff --git a/src/test/java/com/microsoft/aad/msal4j/AuthorityTest.java b/src/test/java/com/microsoft/aad/msal4j/AuthorityTest.java
index a19830be..91717e94 100644
--- a/src/test/java/com/microsoft/aad/msal4j/AuthorityTest.java
+++ b/src/test/java/com/microsoft/aad/msal4j/AuthorityTest.java
@@ -12,7 +12,7 @@
@Test(groups = { "checkin" })
@PrepareForTest({ AADAuthority.class, HttpHelper.class,
- JsonHelper.class, InstanceDiscoveryResponse.class })
+ JsonHelper.class, AadInstanceDiscoveryResponse.class })
public class AuthorityTest extends AbstractMsalTests {
@Test
diff --git a/src/test/java/com/microsoft/aad/msal4j/CacheFormatTests.java b/src/test/java/com/microsoft/aad/msal4j/CacheFormatTests.java
index b3ce00d2..06bb84b4 100644
--- a/src/test/java/com/microsoft/aad/msal4j/CacheFormatTests.java
+++ b/src/test/java/com/microsoft/aad/msal4j/CacheFormatTests.java
@@ -3,7 +3,8 @@
package com.microsoft.aad.msal4j;
-import com.google.gson.GsonBuilder;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
@@ -24,6 +25,9 @@
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.sql.Time;
+import java.time.Duration;
+import java.time.Instant;
import java.util.*;
public class CacheFormatTests extends AbstractMsalTests {
@@ -187,7 +191,7 @@ private void validateAccessTokenCacheEntity(String folder, String tokenResponse,
String keyExpected = readResource(folder + AT_CACHE_ENTITY_KEY);
Assert.assertEquals(keyActual, keyExpected);
- String valueActual = new GsonBuilder().create().toJson(tokenCache.accessTokens.get(keyActual));
+ String valueActual = JsonHelper.mapper.writeValueAsString(tokenCache.accessTokens.get(keyActual));
String valueExpected = readResource(folder + AT_CACHE_ENTITY);
JSONObject tokenResponseJsonObj = JSONObjectUtils.parse(tokenResponse);
@@ -207,7 +211,7 @@ private void validateRefreshTokenCacheEntity(String folder, TokenCache tokenCach
String keyExpected = readResource(folder + RT_CACHE_ENTITY_KEY);
Assert.assertEquals(actualKey, keyExpected);
- String actualValue = new GsonBuilder().create().toJson(tokenCache.refreshTokens.get(actualKey));
+ String actualValue = JsonHelper.mapper.writeValueAsString(tokenCache.refreshTokens.get(actualKey));
String valueExpected = readResource(folder + RT_CACHE_ENTITY);
JSONAssert.assertEquals(valueExpected, actualValue, JSONCompareMode.STRICT);
}
@@ -243,7 +247,7 @@ private void validateIdTokenCacheEntity(String folder, TokenCache tokenCache)
String keyExpected = readResource(folder + ID_TOKEN_CACHE_ENTITY_KEY);
Assert.assertEquals(actualKey, keyExpected);
- String actualValue = new GsonBuilder().create().toJson(tokenCache.idTokens.get(actualKey));
+ String actualValue = JsonHelper.mapper.writeValueAsString(tokenCache.idTokens.get(actualKey));
String valueExpected = readResource(folder + ID_TOKEN_CACHE_ENTITY);
JSONAssert.assertEquals(valueExpected, actualValue,
new IdTokenComparator(JSONCompareMode.STRICT, folder));
@@ -258,7 +262,7 @@ private void validateAccountCacheEntity(String folder, TokenCache tokenCache)
String keyExpected = readResource(folder + ACCOUNT_CACHE_ENTITY_KEY);
Assert.assertEquals(actualKey, keyExpected);
- String actualValue = new GsonBuilder().create().toJson(tokenCache.accounts.get(actualKey));
+ String actualValue = JsonHelper.mapper.writeValueAsString(tokenCache.accounts.get(actualKey));
String valueExpected = readResource(folder + ACCOUNT_CACHE_ENTITY);
JSONAssert.assertEquals(valueExpected, actualValue, JSONCompareMode.STRICT);
@@ -277,7 +281,7 @@ private void validateAppMetadataCacheEntity(String folder, TokenCache tokenCache
String keyExpected = readResource(folder + APP_METADATA_ENTITY_KEY);
Assert.assertEquals(actualKey, keyExpected);
- String actualValue = new GsonBuilder().create().toJson(tokenCache.appMetadata.get(actualKey));
+ String actualValue = JsonHelper.mapper.writeValueAsString(tokenCache.appMetadata.get(actualKey));
String valueExpected = readResource(folder + APP_METADATA_CACHE_ENTITY);
JSONAssert.assertEquals(valueExpected, actualValue, JSONCompareMode.STRICT);
diff --git a/src/test/java/com/microsoft/aad/msal4j/WSTrustRequestTest.java b/src/test/java/com/microsoft/aad/msal4j/WSTrustRequestTest.java
index 1b90e9b6..cca651b9 100644
--- a/src/test/java/com/microsoft/aad/msal4j/WSTrustRequestTest.java
+++ b/src/test/java/com/microsoft/aad/msal4j/WSTrustRequestTest.java
@@ -3,6 +3,7 @@
package com.microsoft.aad.msal4j;
+import org.apache.commons.text.StringEscapeUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -41,4 +42,13 @@ public void buildMessage_integrated() throws Exception {
Assert.assertTrue(msg.contains("cloudAudienceUrn"));
Assert.assertTrue(!msg.contains("