001package com.nimbusds.oauth2.sdk.client;
002
003
004import java.net.URL;
005
006import org.apache.commons.lang3.StringUtils;
007
008import net.jcip.annotations.Immutable;
009
010import net.minidev.json.JSONObject;
011
012import com.nimbusds.oauth2.sdk.ParseException;
013import com.nimbusds.oauth2.sdk.ProtectedResourceRequest;
014import com.nimbusds.oauth2.sdk.SerializeException;
015import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
016import com.nimbusds.oauth2.sdk.http.HTTPRequest;
017import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
018
019
020/**
021 * Client registration request.
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-14), section 3.1.
049 * </ul>
050 */
051@Immutable
052public class ClientRegistrationRequest extends ProtectedResourceRequest {
053
054
055        /**
056         * The client metadata.
057         */
058        private final ClientMetadata metadata;
059
060
061        /**
062         * Creates a new client registration request.
063         *
064         * @param uri         The URI of the client registration endpoint. May 
065         *                    be {@code null} if the {@link #toHTTPRequest()}
066         *                    method will not be used.
067         * @param metadata    The client metadata. Must not be {@code null} and 
068         *                    must specify one or more redirection URIs.
069         * @param accessToken An OAuth 2.0 Bearer access token for the request, 
070         *                    {@code null} if none.
071         */
072        public ClientRegistrationRequest(final URL uri,
073                                         final ClientMetadata metadata, 
074                                         final BearerAccessToken accessToken) {
075
076                super(uri, accessToken);
077
078                if (metadata == null)
079                        throw new IllegalArgumentException("The client metadata must not be null");
080                
081                this.metadata = metadata;
082        }
083
084
085        /**
086         * Gets the associated client metadata.
087         *
088         * @return The client metadata.
089         */
090        public ClientMetadata getClientMetadata() {
091
092                return metadata;
093        }
094
095
096        @Override
097        public HTTPRequest toHTTPRequest()
098                throws SerializeException{
099                
100                if (getEndpointURI() == null)
101                        throw new SerializeException("The endpoint URI is not specified");
102        
103                HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, getEndpointURI());
104
105                if (getAccessToken() != null)
106                        httpRequest.setAuthorization(getAccessToken().toAuthorizationHeader());
107
108                httpRequest.setContentType(CommonContentTypes.APPLICATION_JSON);
109
110                httpRequest.setQuery(metadata.toJSONObject().toString());
111
112                return httpRequest;
113        }
114
115
116        /**
117         * Parses a client registration request from the specified HTTP POST 
118         * request.
119         *
120         * @param httpRequest The HTTP request. Must not be {@code null}.
121         *
122         * @return The client registration request.
123         *
124         * @throws ParseException If the HTTP request couldn't be parsed to a 
125         *                        client registration request.
126         */
127        public static ClientRegistrationRequest parse(final HTTPRequest httpRequest)
128                throws ParseException {
129
130                httpRequest.ensureMethod(HTTPRequest.Method.POST);
131
132                // Parse the client metadata
133                JSONObject jsonObject = httpRequest.getQueryAsJSONObject();
134
135                ClientMetadata metadata = ClientMetadata.parse(jsonObject);
136
137                // Parse the optional bearer access token
138                BearerAccessToken accessToken = null;
139                
140                String authzHeaderValue = httpRequest.getAuthorization();
141                
142                if (StringUtils.isNotBlank(authzHeaderValue))
143                        accessToken = BearerAccessToken.parse(authzHeaderValue);
144                
145                return new ClientRegistrationRequest(httpRequest.getURL(), metadata, accessToken);
146        }
147}