Skip to content

Commit a990b4a

Browse files
authored
Merge pull request #918 from AzureAD/avdunn/jackson-databind-removal
Replace jackson-databind with azure-json in HTTP response classes
2 parents 2cba07f + 656fd23 commit a990b4a

12 files changed

+270
-96
lines changed

msal4j-sdk/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@
6060
<version>1.18.36</version>
6161
<scope>provided</scope>
6262
</dependency>
63+
<dependency>
64+
<groupId>com.azure</groupId>
65+
<artifactId>azure-json</artifactId>
66+
<version>1.4.0</version>
67+
</dependency>
6368
<dependency>
6469
<groupId>com.fasterxml.jackson.core</groupId>
6570
<artifactId>jackson-databind</artifactId>

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryProvider.java

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,13 @@ static Set<String> getAliases(String host) {
120120

121121
static AadInstanceDiscoveryResponse parseInstanceDiscoveryMetadata(String instanceDiscoveryJson) {
122122

123-
AadInstanceDiscoveryResponse aadInstanceDiscoveryResponse;
124123
try {
125-
aadInstanceDiscoveryResponse = JsonHelper.convertJsonToObject(
126-
instanceDiscoveryJson,
127-
AadInstanceDiscoveryResponse.class);
128-
124+
return JsonHelper.convertJsonStringToJsonSerializableObject(instanceDiscoveryJson, AadInstanceDiscoveryResponse::fromJson);
129125
} catch (Exception ex) {
130126
throw new MsalClientException("Error parsing instance discovery response. Data must be " +
131127
"in valid JSON format. For more information, see https://aka.ms/msal4j-instance-discovery",
132128
AuthenticationErrorCode.INVALID_INSTANCE_DISCOVERY_METADATA);
133129
}
134-
135-
return aadInstanceDiscoveryResponse;
136130
}
137131

138132
static void cacheInstanceDiscoveryResponse(String host,
@@ -150,14 +144,9 @@ static void cacheInstanceDiscoveryResponse(String host,
150144
}
151145

152146
static void cacheInstanceDiscoveryMetadata(String host) {
153-
cache.putIfAbsent(host, InstanceDiscoveryMetadataEntry.builder().
154-
preferredCache(host).
155-
preferredNetwork(host).
156-
aliases(Collections.singleton(host)).
157-
build());
147+
cache.putIfAbsent(host, new InstanceDiscoveryMetadataEntry(host, host, Collections.singleton(host)));
158148
}
159149

160-
161150
private static boolean shouldUseRegionalEndpoint(MsalRequest msalRequest){
162151
if (((AbstractClientApplicationBase) msalRequest.application()).azureRegion() != null
163152
|| ((AbstractClientApplicationBase) msalRequest.application()).autoDetectRegion()){
@@ -184,11 +173,7 @@ static void cacheRegionInstanceMetadata(String originalHost, String regionalHost
184173
Set<String> aliases = new HashSet<>();
185174
aliases.add(originalHost);
186175

187-
cache.putIfAbsent(regionalHost, InstanceDiscoveryMetadataEntry.builder().
188-
preferredCache(originalHost).
189-
preferredNetwork(regionalHost).
190-
aliases(aliases).
191-
build());
176+
cache.putIfAbsent(regionalHost, new InstanceDiscoveryMetadataEntry(regionalHost, originalHost, aliases));
192177
}
193178

194179
private static String getRegionalizedHost(String host, String region) {
@@ -248,10 +233,10 @@ static AadInstanceDiscoveryResponse sendInstanceDiscoveryRequest(URL authorityUr
248233

249234
IHttpResponse httpResponse = executeRequest(instanceDiscoveryRequestUrl, msalRequest.headers().getReadonlyHeaderMap(), msalRequest, serviceBundle);
250235

251-
AadInstanceDiscoveryResponse response = JsonHelper.convertJsonToObject(httpResponse.body(), AadInstanceDiscoveryResponse.class);
236+
AadInstanceDiscoveryResponse response = JsonHelper.convertJsonStringToJsonSerializableObject(httpResponse.body(), AadInstanceDiscoveryResponse::fromJson);
252237

253238
if (httpResponse.statusCode() != HttpHelper.HTTP_STATUS_200) {
254-
if(httpResponse.statusCode() == HttpHelper.HTTP_STATUS_400 && response.error().equals("invalid_instance")){
239+
if (httpResponse.statusCode() == HttpHelper.HTTP_STATUS_400 && response.error().equals("invalid_instance")) {
255240
// instance discovery failed due to an invalid authority, throw an exception.
256241
throw MsalServiceExceptionFactory.fromHttpResponse(httpResponse);
257242
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscoveryResponse.java

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,71 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import com.fasterxml.jackson.annotation.JsonProperty;
6+
import com.azure.json.JsonReader;
7+
import com.azure.json.JsonSerializable;
8+
import com.azure.json.JsonToken;
9+
import com.azure.json.JsonWriter;
710
import lombok.AccessLevel;
811
import lombok.Getter;
912
import lombok.experimental.Accessors;
1013

14+
import java.io.IOException;
15+
import java.util.List;
16+
1117
@Accessors(fluent = true)
1218
@Getter(AccessLevel.PACKAGE)
13-
class AadInstanceDiscoveryResponse {
19+
class AadInstanceDiscoveryResponse implements JsonSerializable<AadInstanceDiscoveryResponse> {
1420

15-
@JsonProperty("tenant_discovery_endpoint")
1621
private String tenantDiscoveryEndpoint;
17-
18-
@JsonProperty("metadata")
19-
private InstanceDiscoveryMetadataEntry[] metadata;
20-
21-
@JsonProperty("error_description")
22+
private List<InstanceDiscoveryMetadataEntry> metadata;
2223
private String errorDescription;
23-
24-
@JsonProperty("error_codes")
25-
private long[] errorCodes;
26-
27-
@JsonProperty("error")
24+
private List<Long> errorCodes;
2825
private String error;
29-
30-
@JsonProperty("correlation_id")
3126
private String correlationId;
32-
}
27+
28+
public static AadInstanceDiscoveryResponse fromJson(JsonReader jsonReader) throws IOException {
29+
AadInstanceDiscoveryResponse response = new AadInstanceDiscoveryResponse();
30+
return jsonReader.readObject(reader -> {
31+
while (reader.nextToken() != JsonToken.END_OBJECT) {
32+
String fieldName = reader.getFieldName();
33+
reader.nextToken();
34+
switch (fieldName) {
35+
case "tenant_discovery_endpoint":
36+
response.tenantDiscoveryEndpoint = reader.getString();
37+
break;
38+
case "metadata":
39+
response.metadata = reader.readArray(InstanceDiscoveryMetadataEntry::fromJson);
40+
break;
41+
case "error_description":
42+
response.errorDescription = reader.getString();
43+
break;
44+
case "error_codes":
45+
response.errorCodes = reader.readArray(JsonReader::getLong);
46+
break;
47+
case "error":
48+
response.error = reader.getString();
49+
break;
50+
case "correlation_id":
51+
response.correlationId = reader.getString();
52+
break;
53+
default:
54+
reader.skipChildren();
55+
break;
56+
}
57+
}
58+
return response;
59+
});
60+
}
61+
62+
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
63+
jsonWriter.writeStartObject();
64+
jsonWriter.writeStringField("tenant_discovery_endpoint", tenantDiscoveryEndpoint);
65+
jsonWriter.writeArrayField("metadata", metadata, JsonWriter::writeJson);
66+
jsonWriter.writeStringField("error_description", errorDescription);
67+
jsonWriter.writeArrayField("error_codes", errorCodes, JsonWriter::writeLong);
68+
jsonWriter.writeStringField("error", error);
69+
jsonWriter.writeStringField("correlation_id", correlationId);
70+
jsonWriter.writeEndObject();
71+
return jsonWriter;
72+
}
73+
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractManagedIdentitySource.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ public ManagedIdentityResponse handleResponse(
101101

102102
protected ManagedIdentityResponse getSuccessfulResponse(IHttpResponse response) {
103103

104-
ManagedIdentityResponse managedIdentityResponse = JsonHelper
105-
.convertJsonToObject(response.body(), ManagedIdentityResponse.class);
104+
ManagedIdentityResponse managedIdentityResponse = JsonHelper.convertJsonStringToJsonSerializableObject(response.body(), ManagedIdentityResponse::fromJson);
106105

107106
if (managedIdentityResponse == null || managedIdentityResponse.getAccessToken() == null
108107
|| managedIdentityResponse.getAccessToken().isEmpty() || managedIdentityResponse.getExpiresOn() == null

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/InstanceDiscoveryMetadataEntry.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,58 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import com.fasterxml.jackson.annotation.JsonProperty;
6+
import com.azure.json.JsonReader;
7+
import com.azure.json.JsonSerializable;
8+
import com.azure.json.JsonToken;
9+
import com.azure.json.JsonWriter;
710
import lombok.*;
811
import lombok.experimental.Accessors;
912

13+
import java.io.IOException;
1014
import java.util.*;
1115

1216
@Accessors(fluent = true)
1317
@Getter(AccessLevel.PACKAGE)
1418
@Builder
1519
@NoArgsConstructor
1620
@AllArgsConstructor
17-
class InstanceDiscoveryMetadataEntry {
21+
class InstanceDiscoveryMetadataEntry implements JsonSerializable<InstanceDiscoveryMetadataEntry> {
1822

19-
@JsonProperty("preferred_network")
2023
String preferredNetwork;
21-
22-
@JsonProperty("preferred_cache")
2324
String preferredCache;
24-
25-
@JsonProperty("aliases")
2625
Set<String> aliases;
26+
27+
public static InstanceDiscoveryMetadataEntry fromJson(JsonReader jsonReader) throws IOException {
28+
InstanceDiscoveryMetadataEntry entry = new InstanceDiscoveryMetadataEntry();
29+
return jsonReader.readObject(reader -> {
30+
while (reader.nextToken() != JsonToken.END_OBJECT) {
31+
String fieldName = reader.getFieldName();
32+
reader.nextToken();
33+
switch (fieldName) {
34+
case "preferred_network":
35+
entry.preferredNetwork = reader.getString();
36+
break;
37+
case "preferred_cache":
38+
entry.preferredCache = reader.getString();
39+
break;
40+
case "aliases":
41+
entry.aliases = new HashSet<>(reader.readArray(JsonReader::getString));
42+
break;
43+
default:
44+
reader.skipChildren();
45+
break;
46+
}
47+
}
48+
return entry;
49+
});
50+
}
51+
52+
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
53+
jsonWriter.writeStartObject();
54+
jsonWriter.writeStringField("preferred_network", preferredNetwork);
55+
jsonWriter.writeStringField("preferred_cache", preferredCache);
56+
jsonWriter.writeArrayField("aliases", aliases, JsonWriter::writeString);
57+
jsonWriter.writeEndObject();
58+
return jsonWriter;
59+
}
2760
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/JsonHelper.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
package com.microsoft.aad.msal4j;
55

6+
import com.azure.json.JsonProviders;
7+
import com.azure.json.JsonReader;
8+
import com.azure.json.JsonSerializable;
9+
import com.azure.json.ReadValueCallback;
610
import com.fasterxml.jackson.annotation.JsonInclude;
711
import com.fasterxml.jackson.core.JsonParser;
812
import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -36,6 +40,17 @@ static <T> T convertJsonToObject(final String json, final Class<T> tClass) {
3640
}
3741
}
3842

43+
//This method is used to convert a JSON string to an object which implements the JsonSerializable interface from com.azure.json
44+
static <T extends JsonSerializable<T>> T convertJsonStringToJsonSerializableObject(String jsonResponse, ReadValueCallback<JsonReader, T> readFunction) {
45+
try (JsonReader jsonReader = JsonProviders.createReader(jsonResponse)) {
46+
return readFunction.read(jsonReader);
47+
} catch (IOException e) {
48+
throw new MsalClientException(e.getMessage(), AuthenticationErrorCode.INVALID_JSON);
49+
} catch (Exception e) {
50+
throw new MsalClientException("Error parsing JSON response: " + e.getMessage(), AuthenticationErrorCode.INVALID_JSON);
51+
}
52+
}
53+
3954
/**
4055
* Throws exception if given String does not follow JSON syntax
4156
*/

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityResponse.java

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,67 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import com.fasterxml.jackson.annotation.JsonCreator;
7-
import com.fasterxml.jackson.annotation.JsonProperty;
6+
import com.azure.json.JsonReader;
7+
import com.azure.json.JsonSerializable;
8+
import com.azure.json.JsonToken;
9+
import com.azure.json.JsonWriter;
810
import lombok.Getter;
911
import org.slf4j.Logger;
1012
import org.slf4j.LoggerFactory;
1113

14+
import java.io.IOException;
15+
1216
@Getter
13-
class ManagedIdentityResponse {
17+
class ManagedIdentityResponse implements JsonSerializable<ManagedIdentityResponse> {
1418

1519
private static final Logger LOG = LoggerFactory.getLogger(ManagedIdentityResponse.class);
1620

17-
@JsonProperty(value = "token_type")
1821
String tokenType;
19-
20-
@JsonProperty(value = "access_token")
2122
String accessToken;
22-
23-
@JsonProperty(value = "expires_on")
2423
String expiresOn;
25-
2624
String resource;
27-
28-
@JsonProperty(value = "client_id")
2925
String clientId;
3026

31-
/**
32-
* Creates an access token instance.
33-
*
34-
* @param token the token string.
35-
* @param expiresOn the expiration time.
36-
*/
37-
@JsonCreator
38-
private ManagedIdentityResponse(
39-
@JsonProperty(value = "access_token") String token,
40-
@JsonProperty(value = "expires_on") String expiresOn) {
41-
this.accessToken = token;
42-
this.expiresOn = expiresOn;
27+
public static ManagedIdentityResponse fromJson(JsonReader jsonReader) throws IOException {
28+
ManagedIdentityResponse response = new ManagedIdentityResponse();
29+
return jsonReader.readObject(reader -> {
30+
while (reader.nextToken() != JsonToken.END_OBJECT) {
31+
String fieldName = reader.getFieldName();
32+
reader.nextToken();
33+
switch (fieldName) {
34+
case "token_type":
35+
response.tokenType = reader.getString();
36+
break;
37+
case "access_token":
38+
response.accessToken = reader.getString();
39+
break;
40+
case "expires_on":
41+
response.expiresOn = reader.getString();
42+
break;
43+
case "resource":
44+
response.resource = reader.getString();
45+
break;
46+
case "client_id":
47+
response.clientId = reader.getString();
48+
break;
49+
default:
50+
reader.skipChildren();
51+
break;
52+
}
53+
}
54+
return response;
55+
});
56+
}
57+
58+
@Override
59+
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
60+
jsonWriter.writeStartObject();
61+
jsonWriter.writeStringField("token_type", tokenType);
62+
jsonWriter.writeStringField("access_token", accessToken);
63+
jsonWriter.writeStringField("expires_on", expiresOn);
64+
jsonWriter.writeStringField("resource", resource);
65+
jsonWriter.writeStringField("client_id", clientId);
66+
jsonWriter.writeEndObject();
67+
return jsonWriter;
4368
}
44-
}
69+
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OidcDiscoveryProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ static OidcDiscoveryResponse performOidcDiscovery(OidcAuthority authority, Abstr
1212

1313
IHttpResponse httpResponse = ((HttpHelper)clientApplication.serviceBundle.getHttpHelper()).executeHttpRequest(httpRequest);
1414

15-
OidcDiscoveryResponse response = JsonHelper.convertJsonToObject(httpResponse.body(), OidcDiscoveryResponse.class);
15+
OidcDiscoveryResponse response = JsonHelper.convertJsonStringToJsonSerializableObject(httpResponse.body(), OidcDiscoveryResponse::fromJson);
1616

1717
if (httpResponse.statusCode() != HttpHelper.HTTP_STATUS_200) {
1818
throw MsalServiceExceptionFactory.fromHttpResponse(httpResponse);

0 commit comments

Comments
 (0)