001    package com.nimbusds.oauth2.sdk.client;
002    
003    
004    import java.net.MalformedURLException;
005    import java.net.URL;
006    import java.util.HashMap;
007    import java.util.HashSet;
008    import java.util.LinkedHashSet;
009    import java.util.LinkedList;
010    import java.util.List;
011    import java.util.Map;
012    import java.util.Set;
013    
014    import javax.mail.internet.AddressException;
015    import javax.mail.internet.InternetAddress;
016    
017    import net.minidev.json.JSONArray;
018    import net.minidev.json.JSONObject;
019    
020    import com.nimbusds.langtag.LangTag;
021    import com.nimbusds.langtag.LangTagUtil;
022    
023    import com.nimbusds.oauth2.sdk.GrantType;
024    import com.nimbusds.oauth2.sdk.ParseException;
025    import com.nimbusds.oauth2.sdk.ResponseType;
026    import com.nimbusds.oauth2.sdk.Scope;
027    import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
028    import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
029    
030    
031    /**
032     * Client metadata.
033     * 
034     * <p>Example client metadata, serialised to a JSON object:
035     * 
036     * <pre>
037     * {
038     *  "redirect_uris"             : ["https://client.example.org/callback",
039     *                                 "https://client.example.org/callback2"]
040     *  "client_name"                : "My Example Client",
041     *  "client_name#ja-Jpan-JP"     : "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
042     *  "token_endpoint_auth_method" : "client_secret_basic",
043     *  "scope"                      : "read write dolphin",
044     *  "logo_uri"                   : "https://client.example.org/logo.png",
045     *  "jwks_uri"                   : "https://client.example.org/my_public_keys.jwks"
046     * }
047     * </pre>
048     * 
049     * <p>Related specifications:
050     *
051     * <ul>
052     *     <li>OAuth 2.0 Dynamic Client Registration Protocol 
053     *         (draft-ietf-oauth-dyn-reg-12), section 2.
054     * </ul>
055     * 
056     * @author Vladimir Dzhuvinov
057     */
058    public class ClientMetadata {
059            
060            
061            /**
062             * Redirect URIs.
063             */
064            private Set<URL> redirectURIs;
065            
066            
067            /**
068             * The client OAuth 2.0 scope.
069             */
070            private Scope scope;
071            
072            
073            /**
074             * The expected OAuth 2.0 response types.
075             */
076            private ResponseType responseTypes;
077            
078            
079            /**
080             * The expected OAuth 2.0 grant types.
081             */
082            private Set<GrantType> grantTypes;
083            
084            
085            /**
086             * Administrator contacts for the client.
087             */
088            private List<InternetAddress> contacts;
089    
090    
091            /**
092             * The client name.
093             */
094            private Map<LangTag,String> nameEntries;
095    
096    
097            /**
098             * The client application logo.
099             */
100            private Map<LangTag,URL> logoURIEntries;
101            
102            
103            /**
104             * The client URI entries.
105             */
106            private Map<LangTag,URL> uriEntries;
107    
108    
109            /**
110             * The client policy for use of end-user data.
111             */
112            private Map<LangTag,URL> policyURIEntries;
113    
114    
115            /**
116             * The client terms of service.
117             */
118            private Map<LangTag,URL> tosURIEntries;
119            
120            
121            /**
122             * Token endpoint authentication method.
123             */
124            private ClientAuthenticationMethod authMethod;
125            
126            
127            /**
128             * URI for this client's JSON Web Key (JWK) set containing key(s) that
129             * are used in signing requests to the server and key(s) for encrypting
130             * responses.
131             */
132            private URL jwkSetURI;
133            
134            
135            /** 
136             * Creates a new OAuth 2.0 client metadata instance.
137             */
138            public ClientMetadata() {
139    
140                    nameEntries = new HashMap<LangTag,String>();
141                    logoURIEntries = new HashMap<LangTag,URL>();
142                    uriEntries = new HashMap<LangTag,URL>();
143                    policyURIEntries = new HashMap<LangTag,URL>();
144                    policyURIEntries = new HashMap<LangTag,URL>();
145                    tosURIEntries = new HashMap<LangTag,URL>();
146            }
147            
148            
149            /**
150             * Creates a shallow copy of the specified OAuth 2.0 client metadata
151             * instance.
152             * 
153             * @param metadata The client metadata to copy. Must not be 
154             *                 {@code null}.
155             */
156            public ClientMetadata(final ClientMetadata metadata) {
157                    
158                    redirectURIs = metadata.redirectURIs;
159                    scope = metadata.scope;
160                    responseTypes = metadata.responseTypes;
161                    grantTypes = metadata.grantTypes;
162                    contacts = metadata.contacts;
163                    nameEntries = metadata.nameEntries;
164                    logoURIEntries = metadata.logoURIEntries;
165                    uriEntries = metadata.uriEntries;
166                    policyURIEntries = metadata.policyURIEntries;
167                    tosURIEntries = metadata.tosURIEntries;
168                    authMethod = metadata.authMethod;
169                    jwkSetURI = metadata.jwkSetURI;
170            }
171            
172            
173            /**
174             * Gets the redirect URIs for this client. Corresponds to the
175             * {@code redirect_uris} client registration parameter.
176             *
177             * @return The redirect URIs, {@code null} if not specified.
178             */
179            public Set<URL> getRedirectURIs() {
180            
181                    return redirectURIs;
182            }
183            
184            
185            /**
186             * Sets the redirect URIs for this client. Corresponds to the
187             * {@code redirect_uris} client registration parameter.
188             *
189             * @param redirectURIs The redirect URIs, {@code null} if not 
190             *                     specified.
191             */
192            public void setRedirectURIs(final Set<URL> redirectURIs) {
193            
194                    this.redirectURIs = redirectURIs;
195            }
196            
197            
198            /**
199             * Gets the scope values that the client can use when requesting access 
200             * tokens. Corresponds to the {@code scope} client registration
201             * parameter.
202             * 
203             * @return The scope, {@code null} if not specified.
204             */
205            public Scope getScope() {
206                    
207                    return scope;
208            }
209            
210            
211            /**
212             * Sets the scope values that the client can use when requesting access 
213             * tokens. Corresponds to the {@code scope} client registration
214             * parameter.
215             * 
216             * @param scope The scope, {@code null} if not specified.
217             */
218            public void setScope(final Scope scope) {
219                    
220                    this.scope = scope;
221            }
222            
223            
224            /**
225             * Gets the expected OAuth 2.0 response types. Corresponds to the
226             * {@code response_types} client registration parameter.
227             * 
228             * @return The response types, {@code null} if not specified.
229             */
230            public ResponseType getResponseTypes() {
231                    
232                    return responseTypes;
233            }
234            
235            
236            /**
237             * Sets the expected OAuth 2.0 response types. Corresponds to the
238             * {@code response_types} client registration parameter.
239             * 
240             * @param responseTypes The response types, {@code null} if not 
241             *                      specified.
242             */
243            public void setResponseTypes(final ResponseType responseTypes) {
244                    
245                    this.responseTypes = responseTypes;
246            }
247            
248            
249            /**
250             * Gets the expected OAuth 2.0 grant types. Corresponds to the
251             * {@code grant_types} client registration parameter.
252             * 
253             * @return The grant types, {@code null} if not specified.
254             */
255            public Set<GrantType> getGrantTypes() {
256                    
257                    return grantTypes;
258            }
259            
260            
261            /**
262             * Sets the expected OAuth 2.0 grant types. Corresponds to the
263             * {@code grant_types} client registration parameter.
264             * 
265             * @param grantTypes The grant types, {@code null} if not specified.
266             */
267            public void setGrantTypes(final Set<GrantType> grantTypes) {
268                    
269                    this.grantTypes = grantTypes;
270            }
271            
272            
273            /**
274             * Gets the administrator contacts for the client. Corresponds to the
275             * {@code contacts} client registration parameter.
276             *
277             * @return The administrator contacts, {@code null} if not specified.
278             */
279            public List<InternetAddress> getContacts() {
280    
281                    return contacts;
282            }
283    
284    
285            /**
286             * Sets the administrator contacts for the client. Corresponds to the
287             * {@code contacts} client registration parameter.
288             *
289             * @param contacts The administrator contacts, {@code null} if not
290             *                 specified.
291             */
292            public void setContacts(final List<InternetAddress> contacts) {
293    
294                    this.contacts = contacts;
295            }
296            
297            
298                    /**
299             * Gets the client name. Corresponds to the {@code client_name} client 
300             * registration parameter, with no language tag.
301             *
302             * @return The client name, {@code null} if not specified.
303             */
304            public String getName() {
305    
306                    return getName(null);
307            }
308    
309    
310            /**
311             * Gets the client name. Corresponds to the {@code client_name} client
312             * registration parameter, with an optional language tag.
313             *
314             * @param langTag The language tag of the entry, {@code null} to get 
315             *                the non-tagged entry.
316             *
317             * @return The client name, {@code null} if not specified.
318             */
319            public String getName(final LangTag langTag) {
320    
321                    return nameEntries.get(langTag);
322            }
323    
324    
325            /**
326             * Gets the client name entries. Corresponds to the {@code client_name}
327             * client registration parameter.
328             *
329             * @return The client name entries, empty map if none.
330             */
331            public Map<LangTag,String> getNameEntries() {
332    
333                    return nameEntries;
334            }
335    
336    
337            /**
338             * Sets the client name. Corresponds to the {@code client_name} client
339             * registration parameter, with no language tag.
340             *
341             * @param name The client name, {@code null} if not specified.
342             */
343            public void setName(final String name) {
344    
345                    nameEntries.put(null, name);
346            }
347    
348    
349            /**
350             * Sets the client name. Corresponds to the {@code client_name} client
351             * registration parameter, with an optional language tag.
352             *
353             * @param name    The client name. Must not be {@code null}.
354             * @param langTag The language tag, {@code null} if not specified.
355             */
356            public void setName(final String name, final LangTag langTag) {
357    
358                    nameEntries.put(langTag, name);
359            }
360    
361    
362            /**
363             * Gets the client application logo. Corresponds to the 
364             * {@code logo_uri} client registration parameter, with no language 
365             * tag.
366             *
367             * @return The logo URI, {@code null} if not specified.
368             */
369            public URL getLogoURI() {
370    
371                    return getLogoURI(null);
372            }
373    
374    
375            /**
376             * Gets the client application logo. Corresponds to the 
377             * {@code logo_uri} client registration parameter, with an optional
378             * language tag.
379             *
380             * @return The logo URI, {@code null} if not specified.
381             */
382            public URL getLogoURI(final LangTag langTag) {
383    
384                    return logoURIEntries.get(langTag);
385            }
386    
387    
388            /**
389             * Gets the client application logo entries. Corresponds to the 
390             * {@code logo_uri} client registration parameter.
391             *
392             * @return The logo URI entries, empty map if none.
393             */
394            public Map<LangTag,URL> getLogoURIEntries() {
395    
396                    return logoURIEntries;
397            }
398    
399    
400            /**
401             * Sets the client application logo. Corresponds to the 
402             * {@code logo_uri} client registration parameter, with no language 
403             * tag.
404             *
405             * @param logoURI The logo URI, {@code null} if not specified.
406             */
407            public void setLogoURI(final URL logoURI) {
408    
409                    logoURIEntries.put(null, logoURI);
410            }
411    
412    
413            /**
414             * Sets the client application logo. Corresponds to the 
415             * {@code logo_uri} client registration parameter, with an optional
416             * language tag.
417             *
418             * @param logoURI The logo URI. Must not be {@code null}.
419             * @param langTag The language tag, {@code null} if not specified.
420             */
421            public void setLogoURI(final URL logoURI, final LangTag langTag) {
422    
423                    logoURIEntries.put(langTag, logoURI);
424            }
425            
426            
427            /**
428             * Gets the client home page. Corresponds to the {@code client_uri} 
429             * client registration parameter, with no language tag.
430             *
431             * @return The client URI, {@code null} if not specified.
432             */
433            public URL getURI() {
434    
435                    return getURI(null);
436            }
437    
438    
439            /**
440             * Gets the client home page. Corresponds to the {@code client_uri} 
441             * client registration parameter, with an optional language tag.
442             *
443             * @return The client URI, {@code null} if not specified.
444             */
445            public URL getURI(final LangTag langTag) {
446    
447                    return uriEntries.get(langTag);
448            }
449    
450    
451            /**
452             * Gets the client home page entries. Corresponds to the 
453             * {@code client_uri} client registration parameter.
454             *
455             * @return The client URI entries, empty map if none.
456             */
457            public Map<LangTag,URL> getURIEntries() {
458    
459                    return uriEntries;
460            }
461    
462    
463            /**
464             * Sets the client home page. Corresponds to the {@code client_uri} 
465             * client registration parameter, with no language tag.
466             *
467             * @param uri The client URI, {@code null} if not specified.
468             */
469            public void setURI(final URL uri) {
470    
471                    uriEntries.put(null, uri);
472            }
473    
474    
475            /**
476             * Sets the client home page. Corresponds to the {@code client_uri} 
477             * client registration parameter, with an optional language tag.
478             *
479             * @param uri     The URI. Must not be {@code null}.
480             * @param langTag The language tag, {@code null} if not specified.
481             */
482            public void setURI(final URL uri, final LangTag langTag) {
483    
484                    logoURIEntries.put(langTag, uri);
485            }
486            
487    
488            /**
489             * Gets the client policy for use of end-user data. Corresponds to the 
490             * {@code policy_uri} client registration parameter, with no language 
491             * tag.
492             *
493             * @return The policy URI, {@code null} if not specified.
494             */
495            public URL getPolicyURI() {
496    
497                    return getPolicyURI(null);
498            }
499    
500    
501            /**
502             * Gets the client policy for use of end-user data. Corresponds to the 
503             * {@code policy_url} client registration parameter, with an optional
504             * language tag.
505             *
506             * @return The policy URI, {@code null} if not specified.
507             */
508            public URL getPolicyURI(final LangTag langTag) {
509    
510                    return policyURIEntries.get(langTag);
511            }
512    
513    
514            /**
515             * Gets the client policy entries for use of end-user data. 
516             * Corresponds to the {@code policy_uri} client registration parameter.
517             *
518             * @return The policy URI entries, empty map if none.
519             */
520            public Map<LangTag,URL> getPolicyURIEntries() {
521    
522                    return policyURIEntries;
523            }
524    
525    
526            /**
527             * Sets the client policy for use of end-user data. Corresponds to the 
528             * {@code policy_uri} client registration parameter, with no language 
529             * tag.
530             *
531             * @param policyURI The policy URI, {@code null} if not specified.
532             */
533            public void setPolicyURI(final URL policyURI) {
534    
535                    policyURIEntries.put(null, policyURI);
536            }
537    
538    
539            /**
540             * Sets the client policy for use of end-user data. Corresponds to the 
541             * {@code policy_uri} client registration parameter, with an optional
542             * language tag.
543             *
544             * @param policyURI The policy URI. Must not be {@code null}.
545             * @param langTag   The language tag, {@code null} if not specified.
546             */
547            public void setPolicyURI(final URL policyURI, final LangTag langTag) {
548    
549                    policyURIEntries.put(langTag, policyURI);
550            }
551    
552    
553            /**
554             * Gets the client's terms of service. Corresponds to the 
555             * {@code tos_uri} client registration parameter, with no language 
556             * tag.
557             *
558             * @return The terms of service URI, {@code null} if not specified.
559             */
560            public URL getTermsOfServiceURI() {
561    
562                    return getTermsOfServiceURI(null);
563            }
564    
565    
566            /**
567             * Gets the client's terms of service. Corresponds to the 
568             * {@code tos_uri} client registration parameter, with an optional
569             * language tag.
570             *
571             * @return The terms of service URI, {@code null} if not specified.
572             */
573            public URL getTermsOfServiceURI(final LangTag langTag) {
574    
575                    return tosURIEntries.get(langTag);
576            }
577    
578    
579            /**
580             * Gets the client's terms of service entries. Corresponds to the 
581             * {@code tos_uri} client registration parameter.
582             *
583             * @return The terms of service URI entries, empty map if none.
584             */
585            public Map<LangTag,URL> getTermsOfServiceURIEntries() {
586    
587                    return tosURIEntries;
588            }
589    
590    
591            /**
592             * Sets the client's terms of service. Corresponds to the 
593             * {@code tos_uri} client registration parameter, with no language 
594             * tag.
595             *
596             * @param tosURI The terms of service URI, {@code null} if not 
597             *               specified.
598             */
599            public void setTermsOfServiceURI(final URL tosURI) {
600    
601                    tosURIEntries.put(null, tosURI);
602            }
603    
604    
605            /**
606             * Sets the client's terms of service. Corresponds to the 
607             * {@code tos_uri} client registration parameter, with an optional
608             * language tag.
609             *
610             * @param tosURI  The terms of service URI. Must not be {@code null}.
611             * @param langTag The language tag, {@code null} if not specified.
612             */
613            public void setTermsOfServiceURI(final URL tosURI, final LangTag langTag) {
614    
615                            tosURIEntries.put(langTag, tosURI);
616            }
617            
618            
619            /**
620             * Gets the Token endpoint authentication method. Corresponds to the 
621             * {@code token_endpoint_auth_method} client registration parameter.
622             *
623             * @return The Token endpoint authentication method, {@code null} if
624             *         not specified.
625             */
626            public ClientAuthenticationMethod getTokenEndpointAuthMethod() {
627    
628                    return authMethod;
629            }
630    
631    
632            /**
633             * Sets the Token endpoint authentication method. Corresponds to the 
634             * {@code token_endpoint_auth_method} client registration parameter.
635             *
636             * @param authMethod The Token endpoint authentication  method, 
637             *                   {@code null} if not specified.
638             */
639            public void setTokenEndpointAuthMethod(final ClientAuthenticationMethod authMethod) {
640    
641                    this.authMethod = authMethod;
642            }
643            
644            
645            /**
646             * Gets the URI for this client's JSON Web Key (JWK) set containing 
647             * key(s) that are used in signing requests to the server and key(s) 
648             * for encrypting responses. Corresponds to the {@code jwks_uri} client 
649             * registration parameter.
650             *
651             * @return The JWK set URI, {@code null} if not specified.
652             */
653            public URL getJWKSetURI() {
654    
655                    return jwkSetURI;
656            }
657    
658    
659            /**
660             * Sets the URI for this client's JSON Web Key (JWK) set containing 
661             * key(s) that are used in signing requests to the server and key(s) 
662             * for encrypting responses. Corresponds to the {@code jwks_uri} client 
663             * registration parameter.
664             *
665             * @param jwkSetURI The JWK set URI, {@code null} if not specified.
666             */
667            public void setJWKSetURL(final URL jwkSetURI) {
668    
669                    this.jwkSetURI = jwkSetURI;
670            }
671            
672            
673            /**
674             * Applies the client metadata defaults where no values have been
675             * specified.
676             */
677            public void applyDefaults() {
678                    
679                    if (responseTypes == null) {
680                            responseTypes = ResponseType.getDefault();
681                    }
682                    
683                    if (grantTypes == null) {
684                            grantTypes = new HashSet<GrantType>();
685                            grantTypes.add(GrantType.AUTHORIZATION_CODE);
686                    }
687                    
688                    if (authMethod == null) {
689                            authMethod = ClientAuthenticationMethod.getDefault();
690                    }
691            }
692            
693            
694            /**
695             * Returns the JSON object representation of this client metadata.
696             *
697             * @return The JSON object.
698             */
699            public JSONObject toJSONObject() {
700    
701                    JSONObject o = new JSONObject();
702    
703                    if (redirectURIs != null) {
704    
705                            JSONArray uriList = new JSONArray();
706    
707                            for (URL uri: redirectURIs)
708                                    uriList.add(uri.toString());
709    
710                            o.put("redirect_uris", uriList);
711                    }
712                    
713                    
714                    if (scope != null)
715                            o.put("scope", scope.toString());
716                    
717                    
718                    if (responseTypes != null) {
719                            
720                            JSONArray rtList = new JSONArray();
721                            
722                            for (ResponseType.Value rtValue: responseTypes)
723                                    rtList.add(rtValue.toString());
724                            
725                            o.put("response_types", rtList);
726                    }
727                    
728                    
729                    if (grantTypes != null) {
730                            
731                            JSONArray grantList = new JSONArray();
732                            
733                            for (GrantType grant: grantTypes)
734                                    grantList.add(grant.toString());
735                            
736                            o.put("grant_types", grantList);
737                    }
738    
739    
740                    if (contacts != null) {
741    
742                            JSONArray contactList = new JSONArray();
743    
744                            for (InternetAddress email: contacts)
745                                    contactList.add(email.toString());
746    
747                            o.put("contacts", contactList);
748                    }
749    
750    
751                    if (! nameEntries.isEmpty()) {
752    
753                            for (Map.Entry<LangTag,String> entry: nameEntries.entrySet()) {
754    
755                                    LangTag langTag = entry.getKey();
756                                    String name = entry.getValue();
757                                    
758                                    if (name == null)
759                                            continue;
760    
761                                    if (langTag == null)
762                                            o.put("client_name", entry.getValue());
763                                    else
764                                            o.put("client_name#" + langTag, entry.getValue());
765                            } 
766                    }
767                    
768                    
769                    if (! logoURIEntries.isEmpty()) {
770    
771                            for (Map.Entry<LangTag,URL> entry: logoURIEntries.entrySet()) {
772    
773                                    LangTag langTag = entry.getKey();
774                                    URL uri = entry.getValue();
775                                    
776                                    if (uri == null)
777                                            continue;
778    
779                                    if (langTag == null)
780                                            o.put("logo_uri", entry.getValue());
781                                    else
782                                            o.put("logo_uri#" + langTag, entry.getValue().toString());
783                            } 
784                    }
785                    
786                    
787                    if (! uriEntries.isEmpty()) {
788    
789                            for (Map.Entry<LangTag,URL> entry: uriEntries.entrySet()) {
790    
791                                    LangTag langTag = entry.getKey();
792                                    URL uri = entry.getValue();
793                                    
794                                    if (uri == null)
795                                            continue;
796    
797                                    if (langTag == null)
798                                            o.put("client_uri", entry.getValue());
799                                    else
800                                            o.put("client_uri#" + langTag, entry.getValue().toString());
801                            } 
802                    }
803                    
804                    
805                    if (! policyURIEntries.isEmpty()) {
806    
807                            for (Map.Entry<LangTag,URL> entry: policyURIEntries.entrySet()) {
808    
809                                    LangTag langTag = entry.getKey();
810                                    URL uri = entry.getValue();
811                                    
812                                    if (uri == null)
813                                            continue;
814    
815                                    if (langTag == null)
816                                            o.put("policy_uri", entry.getValue());
817                                    else
818                                            o.put("policy_uri#" + langTag, entry.getValue().toString());
819                            } 
820                    }
821                    
822                    
823                    if (! tosURIEntries.isEmpty()) {
824    
825                            for (Map.Entry<LangTag,URL> entry: tosURIEntries.entrySet()) {
826    
827                                    LangTag langTag = entry.getKey();
828                                    URL uri = entry.getValue();
829                                    
830                                    if (uri == null)
831                                            continue;
832    
833                                    if (langTag == null)
834                                            o.put("tos_uri", entry.getValue());
835                                    else
836                                            o.put("tos_uri#" + langTag, entry.getValue().toString());
837                            } 
838                    }
839    
840    
841                    if (authMethod != null)
842                            o.put("token_endpoint_auth_method", authMethod.toString());
843    
844    
845                    if (jwkSetURI != null)
846                            o.put("jwks_uri", jwkSetURI.toString());
847    
848                    return o;
849            }
850            
851            
852            /**
853             * Parses an client metadata instance from the specified JSON object.
854             *
855             * @param jsonObject The JSON object to parse. Must not be  
856             *                   {@code null}.
857             *
858             * @return The client metadata.
859             *
860             * @throws ParseException If the JSON object couldn't be parsed to a
861             *                        client metadata instance.
862             */
863            public static ClientMetadata parse(final JSONObject jsonObject)
864                    throws ParseException {
865    
866                    ClientMetadata metadata = new ClientMetadata();
867    
868                    if (jsonObject.containsKey("redirect_uris")) {
869    
870                            Set<URL> redirectURIs = new LinkedHashSet<URL>();
871    
872                            for (String uriString: JSONObjectUtils.getStringArray(jsonObject, "redirect_uris")) {
873    
874                                    try {
875                                            redirectURIs.add(new URL(uriString));
876    
877                                    } catch (MalformedURLException e) {
878    
879                                            throw new ParseException("Invalid \"redirect_uris\" parameter: " +
880                                                                      e.getMessage());
881                                    }
882                            }
883    
884                            metadata.setRedirectURIs(redirectURIs);
885                    }
886                    
887                    
888                    if (jsonObject.containsKey("scope"))
889                            metadata.setScope(Scope.parse(JSONObjectUtils.getString(jsonObject, "scope")));
890                    
891                    
892                    if (jsonObject.containsKey("response_types")) {
893                            
894                            ResponseType responseTypes = new ResponseType();
895                            
896                            for (String responseTypeValue: JSONObjectUtils.getStringArray(jsonObject, "response_types")) {
897                                    
898                                    responseTypes.add(new ResponseType.Value(responseTypeValue));
899                            }
900                            
901                            metadata.setResponseTypes(responseTypes);
902                    }
903                    
904                    
905                    if (jsonObject.containsKey("grant_types")) {
906                            
907                            Set<GrantType> grantTypes = new LinkedHashSet<GrantType>();
908                            
909                            for (String grant: JSONObjectUtils.getStringArray(jsonObject, "grant_types")) {
910                                    
911                                    grantTypes.add(new GrantType(grant));
912                            }
913                            
914                            metadata.setGrantTypes(grantTypes);
915                    }       
916                    
917    
918                    if (jsonObject.containsKey("contacts")) {
919    
920                            List<InternetAddress> emailList = new LinkedList<InternetAddress>();
921    
922                            for (String emailString: JSONObjectUtils.getStringArray(jsonObject, "contacts")) {
923    
924                                    try {
925                                            emailList.add(new InternetAddress(emailString));
926    
927                                    } catch (AddressException e) {
928    
929                                            throw new ParseException("Invalid \"contacts\" parameter: " +
930                                                                     e.getMessage());
931                                    }
932                            }
933    
934                            metadata.setContacts(emailList);
935                    }
936    
937                    // Find lang-tagged client_name params
938                    Map<LangTag,Object> matches = LangTagUtil.find("client_name", jsonObject);
939    
940                    for (Map.Entry<LangTag,Object> entry: matches.entrySet()) {
941    
942                            try {
943                                    metadata.setName((String)entry.getValue(), entry.getKey());
944    
945                            } catch (ClassCastException e) {
946    
947                                    throw new ParseException("Invalid \"client_name\" (language tag) parameter");
948                            }
949                    }
950    
951    
952                    matches = LangTagUtil.find("logo_uri", jsonObject);
953    
954                    for (Map.Entry<LangTag,Object> entry: matches.entrySet()) {
955    
956                            try {
957                                    metadata.setLogoURI(new URL((String)entry.getValue()), entry.getKey());
958    
959                            } catch (Exception e) {
960    
961                                    throw new ParseException("Invalid \"logo_uri\" (language tag) parameter");
962                            }
963                    }
964                    
965                    
966                    matches = LangTagUtil.find("client_uri", jsonObject);
967    
968                    for (Map.Entry<LangTag,Object> entry: matches.entrySet()) {
969    
970                            try {
971                                    metadata.setURI(new URL((String)entry.getValue()), entry.getKey());
972    
973                            } catch (Exception e) {
974    
975                                    throw new ParseException("Invalid \"client_uri\" (language tag) parameter");
976                            }
977                    }
978                    
979                    
980                    matches = LangTagUtil.find("policy_uri", jsonObject);
981    
982                    for (Map.Entry<LangTag,Object> entry: matches.entrySet()) {
983    
984                            try {
985                                    metadata.setPolicyURI(new URL((String)entry.getValue()), entry.getKey());
986    
987                            } catch (Exception e) {
988    
989                                    throw new ParseException("Invalid \"policy_uri\" (language tag) parameter");
990                            }
991                    }
992                    
993                    
994                    matches = LangTagUtil.find("tos_uri", jsonObject);
995    
996                    for (Map.Entry<LangTag,Object> entry: matches.entrySet()) {
997    
998                            try {
999                                    metadata.setTermsOfServiceURI(new URL((String)entry.getValue()), entry.getKey());
1000    
1001                            } catch (Exception e) {
1002    
1003                                    throw new ParseException("Invalid \"tos_uri\" (language tag) parameter");
1004                            }
1005                    }
1006                    
1007    
1008                    if (jsonObject.containsKey("token_endpoint_auth_method"))
1009                            metadata.setTokenEndpointAuthMethod(new ClientAuthenticationMethod(
1010                                    JSONObjectUtils.getString(jsonObject, "token_endpoint_auth_method")));
1011    
1012                            
1013                    if (jsonObject.containsKey("jwks_uri"))
1014                            metadata.setJWKSetURL(JSONObjectUtils.getURL(jsonObject, "jwks_uri"));
1015    
1016                    return metadata;
1017            }
1018            
1019    }