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