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