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