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