001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.oauth2.sdk.client; 019 020 021import java.net.URI; 022import java.net.URISyntaxException; 023 024import net.jcip.annotations.Immutable; 025import net.minidev.json.JSONObject; 026 027import com.nimbusds.common.contenttype.ContentType; 028import com.nimbusds.oauth2.sdk.ParseException; 029import com.nimbusds.oauth2.sdk.ProtectedResourceRequest; 030import com.nimbusds.oauth2.sdk.SerializeException; 031import com.nimbusds.oauth2.sdk.auth.Secret; 032import com.nimbusds.oauth2.sdk.http.HTTPRequest; 033import com.nimbusds.oauth2.sdk.id.ClientID; 034import com.nimbusds.oauth2.sdk.token.BearerAccessToken; 035import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 036 037 038/** 039 * Client registration request. 040 * 041 * <p>Example HTTP request: 042 * 043 * <pre> 044 * PUT /register/s6BhdRkqt3 HTTP/1.1 045 * Accept: application/json 046 * Host: server.example.com 047 * Authorization: Bearer reg-23410913-abewfq.123483 048 * 049 * { 050 * "client_id" :"s6BhdRkqt3", 051 * "client_secret" : "cf136dc3c1fc93f31185e5885805d", 052 * "redirect_uris" : [ "https://client.example.org/callback", 053 * "https://client.example.org/alt" ], 054 * "scope" : "read write dolphin", 055 * "grant_types" : [ "authorization_code", "refresh_token" ] 056 * "token_endpoint_auth_method" : "client_secret_basic", 057 * "jwks_uri" : "https://client.example.org/my_public_keys.jwks" 058 * "client_name" : "My New Example", 059 * "client_name#fr" : "Mon Nouvel Exemple", 060 * "logo_uri" : "https://client.example.org/newlogo.png" 061 * "logo_uri#fr" : "https://client.example.org/fr/newlogo.png" 062 * } 063 * 064 * </pre> 065 * 066 * <p>Related specifications: 067 * 068 * <ul> 069 * <li>OAuth 2.0 Dynamic Client Registration Management Protocol (RFC 070 * 7592), section 2.2. 071 * <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), section 072 * 2. 073 * </ul> 074 */ 075@Immutable 076public class ClientUpdateRequest extends ProtectedResourceRequest { 077 078 079 /** 080 * The registered client ID. 081 */ 082 private final ClientID id; 083 084 085 /** 086 * The client metadata. 087 */ 088 private final ClientMetadata metadata; 089 090 091 /** 092 * The optional client secret. 093 */ 094 private final Secret secret; 095 096 097 /** 098 * Creates a new client update request. 099 * 100 * @param uri The URI of the client update endpoint. May be 101 * {@code null} if the {@link #toHTTPRequest()} 102 * method will not be used. 103 * @param id The client ID. Must not be {@code null}. 104 * @param accessToken The client registration access token. Must not be 105 * {@code null}. 106 * @param metadata The client metadata. Must not be {@code null} and 107 * must specify one or more redirection URIs. 108 * @param secret The optional client secret, {@code null} if not 109 * specified. 110 */ 111 public ClientUpdateRequest(final URI uri, 112 final ClientID id, 113 final BearerAccessToken accessToken, 114 final ClientMetadata metadata, 115 final Secret secret) { 116 117 super(uri, accessToken); 118 119 if (id == null) 120 throw new IllegalArgumentException("The client identifier must not be null"); 121 122 this.id = id; 123 124 if (metadata == null) 125 throw new IllegalArgumentException("The client metadata must not be null"); 126 127 this.metadata = metadata; 128 129 this.secret = secret; 130 } 131 132 133 /** 134 * Gets the client ID. Corresponds to the {@code client_id} client 135 * registration parameter. 136 * 137 * @return The client ID, {@code null} if not specified. 138 */ 139 public ClientID getClientID() { 140 141 return id; 142 } 143 144 145 /** 146 * Gets the associated client metadata. 147 * 148 * @return The client metadata. 149 */ 150 public ClientMetadata getClientMetadata() { 151 152 return metadata; 153 } 154 155 156 /** 157 * Gets the client secret. Corresponds to the {@code client_secret} 158 * registration parameters. 159 * 160 * @return The client secret, {@code null} if not specified. 161 */ 162 public Secret getClientSecret() { 163 164 return secret; 165 } 166 167 168 @Override 169 public HTTPRequest toHTTPRequest() { 170 171 if (getEndpointURI() == null) 172 throw new SerializeException("The endpoint URI is not specified"); 173 174 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.PUT, getEndpointURI()); 175 176 httpRequest.setAuthorization(getAccessToken().toAuthorizationHeader()); 177 178 httpRequest.setEntityContentType(ContentType.APPLICATION_JSON); 179 180 JSONObject jsonObject = metadata.toJSONObject(); 181 182 jsonObject.put("client_id", id.getValue()); 183 184 if (secret != null) 185 jsonObject.put("client_secret", secret.getValue()); 186 187 httpRequest.setQuery(jsonObject.toString()); 188 189 return httpRequest; 190 } 191 192 193 /** 194 * Parses a client update request from the specified HTTP PUT request. 195 * 196 * @param httpRequest The HTTP request. Must not be {@code null}. 197 * 198 * @return The client update request. 199 * 200 * @throws ParseException If the HTTP request couldn't be parsed to a 201 * client update request. 202 */ 203 public static ClientUpdateRequest parse(final HTTPRequest httpRequest) 204 throws ParseException { 205 206 httpRequest.ensureMethod(HTTPRequest.Method.PUT); 207 208 BearerAccessToken accessToken = BearerAccessToken.parse(httpRequest.getAuthorization()); 209 210 JSONObject jsonObject = httpRequest.getQueryAsJSONObject(); 211 212 ClientID id = new ClientID(JSONObjectUtils.getString(jsonObject, "client_id")); 213 214 ClientMetadata metadata = ClientMetadata.parse(jsonObject); 215 216 Secret clientSecret = null; 217 218 if (jsonObject.get("client_secret") != null) 219 clientSecret = new Secret(JSONObjectUtils.getString(jsonObject, "client_secret")); 220 221 URI endpointURI; 222 223 try { 224 endpointURI = httpRequest.getURL().toURI(); 225 226 } catch (URISyntaxException e) { 227 228 throw new ParseException(e.getMessage(), e); 229 } 230 231 return new ClientUpdateRequest(endpointURI, id, accessToken, metadata, clientSecret); 232 } 233}