001 package com.nimbusds.oauth2.sdk.auth; 002 003 004 import java.util.HashMap; 005 import java.util.Map; 006 007 import javax.mail.internet.ContentType; 008 009 import net.jcip.annotations.Immutable; 010 011 import com.nimbusds.oauth2.sdk.ParseException; 012 import com.nimbusds.oauth2.sdk.SerializeException; 013 import com.nimbusds.oauth2.sdk.id.ClientID; 014 import com.nimbusds.oauth2.sdk.http.CommonContentTypes; 015 import com.nimbusds.oauth2.sdk.http.HTTPRequest; 016 import com.nimbusds.oauth2.sdk.util.URLUtils; 017 018 019 /** 020 * Client secret post authentication at the Token endpoint. Implements 021 * {@link ClientAuthenticationMethod#CLIENT_SECRET_POST}. This class is 022 * immutable. 023 * 024 * <p>Related specifications: 025 * 026 * <ul> 027 * <li>OAuth 2.0 (RFC 6749), section 2.3.1. 028 * </ul> 029 * 030 * @author Vladimir Dzhuvinov 031 */ 032 @Immutable 033 public final class ClientSecretPost extends ClientAuthentication { 034 035 036 /** 037 * The client ID. 038 */ 039 private final ClientID clientID; 040 041 042 /** 043 * The client secret. 044 */ 045 private final Secret secret; 046 047 048 /** 049 * Creates a new client secret post authentication. 050 * 051 * @param clientID The client identifier. Must not be {@code null}. 052 * @param secret The client secret. Must not be {@code null}. 053 */ 054 public ClientSecretPost(final ClientID clientID, final Secret secret) { 055 056 super(ClientAuthenticationMethod.CLIENT_SECRET_POST); 057 058 if (clientID == null) 059 throw new IllegalArgumentException("The client ID must not be null"); 060 061 this.clientID = clientID; 062 063 if (secret == null) 064 throw new IllegalArgumentException("The client secret must not be null"); 065 066 this.secret = secret; 067 } 068 069 070 /** 071 * Gets the client identifier. 072 * 073 * @return The client identifier. 074 */ 075 public ClientID getClientID() { 076 077 return clientID; 078 } 079 080 081 /** 082 * Gets the client secret. 083 * 084 * @return The client secret. 085 */ 086 public Secret getClientSecret() { 087 088 return secret; 089 } 090 091 092 /** 093 * Returns the parameter representation of this client secret post 094 * authentication. Note that the parameters are not 095 * {@code application/x-www-form-urlencoded} encoded. 096 * 097 * <p>Parameters map: 098 * 099 * <pre> 100 * "client_id" -> [client-identifier] 101 * "client_secret" -> [client-secret] 102 * </pre> 103 * 104 * @return The parameters map, with keys "client_id" and 105 * "client_secret". 106 */ 107 public Map<String,String> toParameters() { 108 109 Map<String,String> params = new HashMap<String,String>(); 110 111 params.put("client_id", clientID.toString()); 112 params.put("client_secret", secret.getValue()); 113 114 return params; 115 } 116 117 118 @Override 119 public void applyTo(final HTTPRequest httpRequest) 120 throws SerializeException { 121 122 if (httpRequest.getMethod() != HTTPRequest.Method.POST) 123 throw new SerializeException("The HTTP request method must be POST"); 124 125 ContentType ct = httpRequest.getContentType(); 126 127 if (ct == null) 128 throw new SerializeException("Missing HTTP Content-Type header"); 129 130 if (! ct.match(CommonContentTypes.APPLICATION_URLENCODED)) 131 throw new SerializeException("The HTTP Content-Type header must be " + CommonContentTypes.APPLICATION_URLENCODED); 132 133 Map <String,String> params = httpRequest.getQueryParameters(); 134 135 params.putAll(toParameters()); 136 137 String queryString = URLUtils.serializeParameters(params); 138 139 httpRequest.setQuery(queryString); 140 } 141 142 143 /** 144 * Parses a client secret post authentication from the specified 145 * parameters map. Note that the parameters must not be 146 * {@code application/x-www-form-urlencoded} encoded. 147 * 148 * @param params The parameters map to parse. The client secret post 149 * parameters must be keyed under "client_id" and 150 * "client_secret". The map must not be {@code null}. 151 * 152 * @return The client secret post authentication. 153 * 154 * @throws ParseException If the parameters map couldn't be parsed to a 155 * client secret post authentication. 156 */ 157 public static ClientSecretPost parse(final Map<String,String> params) 158 throws ParseException { 159 160 String clientIDString = params.get("client_id"); 161 162 if (clientIDString == null) 163 throw new ParseException("Missing \"client_id\" parameter"); 164 165 String secretValue = params.get("client_secret"); 166 167 if (secretValue == null) 168 throw new ParseException("Missing \"client_secret\" parameter"); 169 170 return new ClientSecretPost(new ClientID(clientIDString), new Secret(secretValue)); 171 } 172 173 174 /** 175 * Parses a client secret post authentication from the specified 176 * {@code application/x-www-form-urlencoded} encoded parameters string. 177 * 178 * @param paramsString The parameters string to parse. The client secret 179 * post parameters must be keyed under "client_id" 180 * and "client_secret". The string must not be 181 * {@code null}. 182 * 183 * @return The client secret post authentication. 184 * 185 * @throws ParseException If the parameters string couldn't be parsed to 186 * a client secret post authentication. 187 */ 188 public static ClientSecretPost parse(final String paramsString) 189 throws ParseException { 190 191 Map<String,String> params = URLUtils.parseParameters(paramsString); 192 193 return parse(params); 194 } 195 196 197 /** 198 * Parses a client secret post authentication from the specified HTTP 199 * POST request. 200 * 201 * @param httpRequest The HTTP POST request to parse. Must not be 202 * {@code null} and must contain a valid 203 * {@code application/x-www-form-urlencoded} encoded 204 * parameters string in the entity body. The client 205 * secret post parameters must be keyed under 206 * "client_id" and "client_secret". 207 * 208 * @return The client secret post authentication. 209 * 210 * @throws ParseException If the HTTP request header couldn't be parsed 211 * to a valid client secret post authentication. 212 */ 213 public static ClientSecretPost parse(final HTTPRequest httpRequest) 214 throws ParseException { 215 216 httpRequest.ensureMethod(HTTPRequest.Method.POST); 217 httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED); 218 219 return parse(httpRequest.getQueryParameters()); 220 } 221 }