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