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. 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
054public 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}