001    package com.nimbusds.oauth2.sdk.client;
002    
003    
004    import java.net.URL;
005    
006    import org.apache.commons.lang3.StringUtils;
007    
008    import net.jcip.annotations.Immutable;
009    
010    import net.minidev.json.JSONObject;
011    
012    import com.nimbusds.oauth2.sdk.ParseException;
013    import com.nimbusds.oauth2.sdk.ProtectedResourceRequest;
014    import com.nimbusds.oauth2.sdk.SerializeException;
015    import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
016    import com.nimbusds.oauth2.sdk.http.HTTPRequest;
017    import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
018    
019    
020    /**
021     * Client registration request. This class is immutable.
022     *
023     * <p>Example HTTP request:
024     *
025     * <pre>
026     * POST /register HTTP/1.1
027     * Content-Type: application/json
028     * Accept: application/json
029     * Authorization: Bearer ey23f2.adfj230.af32-developer321
030     * Host: server.example.com
031     *
032     * {
033     *  "redirect_uris"              : ["https://client.example.org/callback", 
034     *                                  "https://client.example.org/callback2"]
035     *  "client_name"                : "My Example Client",
036     *  "client_name#ja-Jpan-JP"     : "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
037     *  "token_endpoint_auth_method" : "client_secret_basic",
038     *  "scope"                      : "read write dolphin",
039     *  "logo_uri"                   : "https://client.example.org/logo.png",
040     *  "jwks_uri"                   : "https://client.example.org/my_public_keys.jwks"
041     * }
042     * </pre>
043     *
044     * <p>Related specifications:
045     *
046     * <ul>
047     *     <li>OAuth 2.0 Dynamic Client Registration Protocol 
048     *         (draft-ietf-oauth-dyn-reg-12), section 3.1.
049     * </ul>
050     *
051     * @author Vladimir Dzhuvinov
052     */
053    @Immutable
054    public class ClientRegistrationRequest extends ProtectedResourceRequest {
055    
056    
057            /**
058             * The client metadata.
059             */
060            private final ClientMetadata metadata;
061    
062    
063            /**
064             * Creates a new client registration request.
065             *
066             * @param uri         The URI of the client registration endpoint. May 
067             *                    be {@code null} if the {@link #toHTTPRequest()}
068             *                    method will not be used.
069             * @param metadata    The client metadata. Must not be {@code null} and 
070             *                    must specify one or more redirect URIs.
071             * @param accessToken An OAuth 2.0 Bearer access token for the request, 
072             *                    {@code null} if none.
073             */
074            public ClientRegistrationRequest(final URL uri,
075                                             final ClientMetadata metadata, 
076                                             final BearerAccessToken accessToken) {
077    
078                    super(uri, accessToken);
079    
080                    if (metadata == null)
081                            throw new IllegalArgumentException("The client metadata must not be null");
082                    
083                    this.metadata = metadata;
084            }
085    
086    
087            /**
088             * Gets the associated client metadata.
089             *
090             * @return The client metadata.
091             */
092            public ClientMetadata getClientMetadata() {
093    
094                    return metadata;
095            }
096    
097    
098            @Override
099            public HTTPRequest toHTTPRequest()
100                    throws SerializeException{
101                    
102                    if (getURI() == null)
103                            throw new SerializeException("The endpoint URI is not specified");
104            
105                    HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, getURI());
106    
107                    if (getAccessToken() != null)
108                            httpRequest.setAuthorization(getAccessToken().toAuthorizationHeader());
109    
110                    httpRequest.setContentType(CommonContentTypes.APPLICATION_JSON);
111    
112                    httpRequest.setQuery(metadata.toJSONObject().toString());
113    
114                    return httpRequest;
115            }
116    
117    
118            /**
119             * Parses a client registration request from the specified HTTP POST 
120             * request.
121             *
122             * @param httpRequest The HTTP request. Must not be {@code null}.
123             *
124             * @return The client registration request.
125             *
126             * @throws ParseException If the HTTP request couldn't be parsed to a 
127             *                        client registration request.
128             */
129            public static ClientRegistrationRequest parse(final HTTPRequest httpRequest)
130                    throws ParseException {
131    
132                    httpRequest.ensureMethod(HTTPRequest.Method.POST);
133    
134                    // Parse the client metadata
135                    JSONObject jsonObject = httpRequest.getQueryAsJSONObject();
136    
137                    ClientMetadata metadata = ClientMetadata.parse(jsonObject);
138    
139                    // Parse the optinal bearer access token
140                    BearerAccessToken accessToken = null;
141                    
142                    String authzHeaderValue = httpRequest.getAuthorization();
143                    
144                    if (StringUtils.isNotBlank(authzHeaderValue))
145                            accessToken = BearerAccessToken.parse(authzHeaderValue);
146                    
147                    return new ClientRegistrationRequest(httpRequest.getURL(), metadata, accessToken);
148            }
149    }