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