33
44package 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 .JsonToken ;
10+ import com .azure .json .JsonWriter ;
611
7- import com .fasterxml .jackson .core .type .TypeReference ;
8- import com .fasterxml .jackson .databind .JsonNode ;
9- import com .fasterxml .jackson .databind .ObjectMapper ;
10- import com .fasterxml .jackson .databind .ObjectReader ;
11- import com .fasterxml .jackson .databind .node .ObjectNode ;
12-
12+ import java .io .ByteArrayOutputStream ;
1313import java .io .IOException ;
14+ import java .nio .charset .StandardCharsets ;
1415import java .util .ArrayList ;
15- import java .util .Iterator ;
1616import java .util .List ;
1717
1818/**
1919 * Represents the claims request parameter as an object
2020 *
2121 * @see <a href="https://openid.net/specs/openid-connect-core-1_0-final.html#ClaimsParameter">https://openid.net/specs/openid-connect-core-1_0-final.html#ClaimsParameter</a>
2222 */
23- public class ClaimsRequest {
23+ public class ClaimsRequest implements JsonSerializable < ClaimsRequest > {
2424
2525 List <RequestedClaim > idTokenRequestedClaims = new ArrayList <>();
2626 List <RequestedClaim > userInfoRequestedClaims = new ArrayList <>();
@@ -62,31 +62,47 @@ protected void requestClaimInAccessToken(String claim, RequestedClaimAdditionalI
6262 * @return a String following JSON formatting
6363 */
6464 public String formatAsJSONString () {
65- ObjectMapper mapper = new ObjectMapper ();
66- ObjectNode rootNode = mapper .createObjectNode ();
65+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
66+ JsonWriter jsonWriter = JsonProviders .createWriter (outputStream )) {
67+ toJson (jsonWriter );
6768
68- if (!idTokenRequestedClaims .isEmpty ()) {
69- rootNode .set ("id_token" , convertClaimsToObjectNode (idTokenRequestedClaims ));
70- }
71- if (!userInfoRequestedClaims .isEmpty ()) {
72- rootNode .set ("userinfo" , convertClaimsToObjectNode (userInfoRequestedClaims ));
73- }
74- if (!accessTokenRequestedClaims .isEmpty ()) {
75- rootNode .set ("access_token" , convertClaimsToObjectNode (accessTokenRequestedClaims ));
69+ jsonWriter .flush ();
70+ return outputStream .toString (StandardCharsets .UTF_8 .name ());
71+ } catch (IOException e ) {
72+ throw new MsalClientException ("Could not convert ClaimsRequest to string: " + e .getMessage (), AuthenticationErrorCode .INVALID_JSON );
7673 }
74+ }
75+
76+ @ Override
77+ public JsonWriter toJson (JsonWriter jsonWriter ) throws IOException {
78+ jsonWriter .writeStartObject ();
7779
78- return mapper .valueToTree (rootNode ).toString ();
80+ writeClaimsToJsonWriter (jsonWriter , "id_token" , idTokenRequestedClaims );
81+ writeClaimsToJsonWriter (jsonWriter , "userinfo" , userInfoRequestedClaims );
82+ writeClaimsToJsonWriter (jsonWriter , "access_token" , accessTokenRequestedClaims );
83+
84+ jsonWriter .writeEndObject ();
85+ return jsonWriter ;
7986 }
8087
81- private ObjectNode convertClaimsToObjectNode (List <RequestedClaim > claims ) {
82- ObjectMapper mapper = new ObjectMapper ();
83- ObjectNode claimsNode = mapper .createObjectNode ();
88+ private void writeClaimsToJsonWriter (JsonWriter jsonWriter , String sectionName , List <RequestedClaim > claims ) throws IOException {
89+ if (claims .isEmpty ()) {
90+ return ;
91+ }
8492
93+ jsonWriter .writeStartObject (sectionName );
8594
8695 for (RequestedClaim claim : claims ) {
87- claimsNode .setAll ((ObjectNode ) mapper .valueToTree (claim ));
96+ if (claim .name != null ) {
97+ if (claim .getRequestedClaimAdditionalInfo () != null ) {
98+ jsonWriter .writeJsonField (claim .name , claim .getRequestedClaimAdditionalInfo ());
99+ } else {
100+ jsonWriter .writeNullField (claim .name );
101+ }
102+ }
88103 }
89- return claimsNode ;
104+
105+ jsonWriter .writeEndObject ();
90106 }
91107
92108 /**
@@ -96,49 +112,74 @@ private ObjectNode convertClaimsToObjectNode(List<RequestedClaim> claims) {
96112 * @return a ClaimsRequest instance
97113 */
98114 public static ClaimsRequest formatAsClaimsRequest (String claims ) {
99- try {
100- ClaimsRequest cr = new ClaimsRequest ();
115+ try ( JsonReader jsonReader = JsonProviders . createReader ( claims )) {
116+ ClaimsRequest claimsRequest = new ClaimsRequest ();
101117
102- ObjectMapper mapper = new ObjectMapper ();
103- ObjectReader reader = mapper .readerFor (new TypeReference <List <String >>() {
104- });
105-
106- JsonNode jsonClaims = mapper .readTree (claims );
118+ return jsonReader .readObject (reader -> {
119+ if (reader .currentToken () != JsonToken .START_OBJECT ) {
120+ throw new IllegalStateException ("Expected start of object but was " + reader .currentToken ());
121+ }
107122
108- addClaimsFromJsonNode ( jsonClaims . get ( "id_token" ), "id_token" , cr , reader );
109- addClaimsFromJsonNode ( jsonClaims . get ( "userinfo" ), "userinfo" , cr , reader );
110- addClaimsFromJsonNode ( jsonClaims . get ( "access_token" ), "access_token" , cr , reader );
123+ while ( reader . nextToken () != JsonToken . END_OBJECT ) {
124+ parseClaims ( reader , claimsRequest , reader . getFieldName () );
125+ }
111126
112- return cr ;
127+ return claimsRequest ;
128+ });
113129 } catch (IOException e ) {
114- throw new MsalClientException ("Could not convert string to ClaimsRequest: " + e .getMessage (), AuthenticationErrorCode .INVALID_JSON );
130+ throw new MsalClientException ("Could not convert string to ClaimsRequest: " + e .getMessage (),
131+ AuthenticationErrorCode .INVALID_JSON );
115132 }
116133 }
117134
118- private static void addClaimsFromJsonNode (JsonNode claims , String group , ClaimsRequest cr , ObjectReader reader ) throws IOException {
119- Iterator <String > claimsIterator ;
135+ private static void parseClaims (JsonReader jsonReader , ClaimsRequest claimsRequest , String section ) throws IOException {
136+ if (jsonReader .currentToken () != JsonToken .FIELD_NAME ) {
137+ jsonReader .nextToken ();
138+ }
120139
121- if (claims != null ) {
122- claimsIterator = claims .fieldNames ();
123- while (claimsIterator .hasNext ()) {
124- String claim = claimsIterator .next ();
125- Boolean essential = null ;
140+ jsonReader .nextToken ();
141+ if (jsonReader .currentToken () != JsonToken .START_OBJECT ) {
142+ throw new IllegalStateException ("Expected start of object but was " + jsonReader .currentToken ());
143+ }
144+
145+ while (jsonReader .nextToken () != JsonToken .END_OBJECT ) {
146+ String claimName = jsonReader .getFieldName ();
147+ jsonReader .nextToken ();
148+
149+ RequestedClaimAdditionalInfo claimInfo = null ;
150+ if (jsonReader .currentToken () == JsonToken .START_OBJECT ) {
151+ boolean essential = false ;
126152 String value = null ;
127153 List <String > values = null ;
128- RequestedClaimAdditionalInfo claimInfo = null ;
129154
130- if (claims .get (claim ).has ("essential" )) essential = claims .get (claim ).get ("essential" ).asBoolean ();
131- if (claims .get (claim ).has ("value" )) value = claims .get (claim ).get ("value" ).textValue ();
132- if (claims .get (claim ).has ("values" )) values = reader .readValue (claims .get (claim ).get ("values" ));
155+ while (jsonReader .nextToken () != JsonToken .END_OBJECT ) {
156+ String fieldName = jsonReader .getFieldName ();
157+ jsonReader .nextToken ();
158+
159+ switch (fieldName ) {
160+ case "essential" : essential = jsonReader .getBoolean (); break ;
161+ case "value" : value = jsonReader .getString (); break ;
162+ case "values" :
163+ values = new ArrayList <>();
164+ if (jsonReader .currentToken () == JsonToken .START_ARRAY ) {
165+ while (jsonReader .nextToken () != JsonToken .END_ARRAY ) {
166+ values .add (jsonReader .getString ());
167+ }
168+ }
169+ break ;
170+ default : jsonReader .skipChildren (); break ;
171+ }
172+ }
133173
134- //'null' is a valid value for RequestedClaimAdditionalInfo, so only initialize it if one of the parameters is not null
135- if (essential != null || value != null || values != null ) {
136- claimInfo = new RequestedClaimAdditionalInfo (essential == null ? false : essential , value , values );
174+ if (essential || value != null || values != null ) {
175+ claimInfo = new RequestedClaimAdditionalInfo (essential , value , values );
137176 }
177+ }
138178
139- if (group .equals ("id_token" )) cr .requestClaimInIdToken (claim , claimInfo );
140- if (group .equals ("userinfo" )) cr .requestClaimInUserInfo (claim , claimInfo );
141- if (group .equals ("access_token" )) cr .requestClaimInAccessToken (claim , claimInfo );
179+ switch (section ) {
180+ case "access_token" : claimsRequest .requestClaimInAccessToken (claimName , claimInfo ); break ;
181+ case "id_token" : claimsRequest .requestClaimInIdToken (claimName , claimInfo ); break ;
182+ case "userinfo" : claimsRequest .requestClaimInUserInfo (claimName , claimInfo ); break ;
142183 }
143184 }
144185 }
@@ -150,4 +191,4 @@ public List<RequestedClaim> getIdTokenRequestedClaims() {
150191 public void setIdTokenRequestedClaims (List <RequestedClaim > idTokenRequestedClaims ) {
151192 this .idTokenRequestedClaims = idTokenRequestedClaims ;
152193 }
153- }
194+ }
0 commit comments