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.openid.connect.sdk.rp; 019 020 021import java.net.URI; 022import java.net.URISyntaxException; 023 024import net.jcip.annotations.Immutable; 025 026import org.apache.commons.lang3.StringUtils; 027 028import net.minidev.json.JSONObject; 029 030import com.nimbusds.jwt.SignedJWT; 031 032import com.nimbusds.oauth2.sdk.ParseException; 033import com.nimbusds.oauth2.sdk.client.ClientRegistrationRequest; 034import com.nimbusds.oauth2.sdk.http.HTTPRequest; 035import com.nimbusds.oauth2.sdk.token.BearerAccessToken; 036import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 037 038 039/** 040 * OpenID Connect client registration request. 041 * 042 * <p>Example HTTP request: 043 * 044 * <pre> 045 * POST /connect/register HTTP/1.1 046 * Content-Type: application/json 047 * Accept: application/json 048 * Host: server.example.com 049 * Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJ ... 050 * 051 * { 052 * "application_type" : "web", 053 * "redirect_uris" : [ "https://client.example.org/callback", 054 * "https://client.example.org/callback2" ], 055 * "client_name" : "My Example", 056 * "client_name#ja-Jpan-JP" : "クライアント名", 057 * "logo_uri" : "https://client.example.org/logo.png", 058 * "subject_type" : "pairwise", 059 * "sector_identifier_uri" : "https://other.example.net/file_of_redirect_uris.json", 060 * "token_endpoint_auth_method" : "client_secret_basic", 061 * "jwks_uri" : "https://client.example.org/my_public_keys.jwks", 062 * "userinfo_encrypted_response_alg" : "RSA1_5", 063 * "userinfo_encrypted_response_enc" : "A128CBC-HS256", 064 * "contacts" : [ "[email protected]", "[email protected]" ], 065 * "request_uris" : [ "https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA" ] 066 * } 067 * </pre> 068 * 069 * <p>Related specifications: 070 * 071 * <ul> 072 * <li>OpenID Connect Dynamic Client Registration 1.0, section 3.1. 073 * <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), sections 074 * 2 and 3.1. 075 * </ul> 076 */ 077@Immutable 078public class OIDCClientRegistrationRequest extends ClientRegistrationRequest { 079 080 081 /** 082 * Creates a new OpenID Connect client registration request. 083 * 084 * @param uri The URI of the client registration endpoint. May 085 * be {@code null} if the {@link #toHTTPRequest()} 086 * method will not be used. 087 * @param metadata The OpenID Connect client metadata. Must not be 088 * {@code null} and must specify one or more 089 * redirection URIs. 090 * @param accessToken An OAuth 2.0 Bearer access token for the request, 091 * {@code null} if none. 092 */ 093 public OIDCClientRegistrationRequest(final URI uri, 094 final OIDCClientMetadata metadata, 095 final BearerAccessToken accessToken) { 096 097 super(uri, metadata, accessToken); 098 } 099 100 101 /** 102 * Creates a new OpenID Connect client registration request with an 103 * optional software statement. 104 * 105 * @param uri The URI of the client registration 106 * endpoint. May be {@code null} if the 107 * {@link #toHTTPRequest()} method will not be 108 * used. 109 * @param metadata The OpenID Connect client metadata. Must 110 * not be {@code null} and must specify one or 111 * more redirection URIs. 112 * @param softwareStatement Optional software statement, as a signed 113 * JWT with an {@code iss} claim; {@code null} 114 * if not specified. 115 * @param accessToken An OAuth 2.0 Bearer access token for the 116 * request, {@code null} if none. 117 */ 118 public OIDCClientRegistrationRequest(final URI uri, 119 final OIDCClientMetadata metadata, 120 final SignedJWT softwareStatement, 121 final BearerAccessToken accessToken) { 122 123 super(uri, metadata, softwareStatement, accessToken); 124 } 125 126 127 /** 128 * Gets the associated OpenID Connect client metadata. 129 * 130 * @return The OpenID Connect client metadata. 131 */ 132 public OIDCClientMetadata getOIDCClientMetadata() { 133 134 return (OIDCClientMetadata)getClientMetadata(); 135 } 136 137 138 /** 139 * Parses an OpenID Connect client registration request from the 140 * specified HTTP POST request. 141 * 142 * @param httpRequest The HTTP request. Must not be {@code null}. 143 * 144 * @return The OpenID Connect client registration request. 145 * 146 * @throws ParseException If the HTTP request couldn't be parsed to an 147 * OpenID Connect client registration request. 148 */ 149 public static OIDCClientRegistrationRequest parse(final HTTPRequest httpRequest) 150 throws ParseException { 151 152 httpRequest.ensureMethod(HTTPRequest.Method.POST); 153 154 // Get the JSON object content 155 JSONObject jsonObject = httpRequest.getQueryAsJSONObject(); 156 157 // Extract the software statement if any 158 SignedJWT stmt = null; 159 160 if (jsonObject.containsKey("software_statement")) { 161 162 try { 163 stmt = SignedJWT.parse(JSONObjectUtils.getString(jsonObject, "software_statement")); 164 165 } catch (java.text.ParseException e) { 166 167 throw new ParseException("Invalid software statement JWT: " + e.getMessage()); 168 } 169 170 // Prevent the JWT from appearing in the metadata 171 jsonObject.remove("software_statement"); 172 } 173 174 // Parse the client metadata 175 OIDCClientMetadata metadata = OIDCClientMetadata.parse(jsonObject); 176 177 // Parse the optional bearer access token 178 BearerAccessToken accessToken = null; 179 180 String authzHeaderValue = httpRequest.getAuthorization(); 181 182 if (StringUtils.isNotBlank(authzHeaderValue)) 183 accessToken = BearerAccessToken.parse(authzHeaderValue); 184 185 try { 186 URI endpointURI = httpRequest.getURL().toURI(); 187 188 return new OIDCClientRegistrationRequest(endpointURI, metadata, stmt, accessToken); 189 190 } catch (URISyntaxException | IllegalArgumentException e) { 191 192 throw new ParseException(e.getMessage(), e); 193 } 194 } 195}