001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.oauth2.sdk.auth; 019 020 021import java.util.HashMap; 022import java.util.Map; 023 024import javax.mail.internet.ContentType; 025 026import net.jcip.annotations.Immutable; 027 028import com.nimbusds.oauth2.sdk.ParseException; 029import com.nimbusds.oauth2.sdk.SerializeException; 030import com.nimbusds.oauth2.sdk.id.ClientID; 031import com.nimbusds.oauth2.sdk.http.CommonContentTypes; 032import com.nimbusds.oauth2.sdk.http.HTTPRequest; 033import com.nimbusds.oauth2.sdk.util.URLUtils; 034 035 036/** 037 * Client secret post authentication at the Token endpoint. Implements 038 * {@link ClientAuthenticationMethod#CLIENT_SECRET_POST}. 039 * 040 * <p>Related specifications: 041 * 042 * <ul> 043 * <li>OAuth 2.0 (RFC 6749), sections 2.3.1 and 3.2.1. 044 * <li>OpenID Connect Core 1.0, section 9. 045 * </ul> 046 */ 047@Immutable 048public final class ClientSecretPost extends PlainClientSecret { 049 050 051 /** 052 * Creates a new client secret post authentication. 053 * 054 * @param clientID The client identifier. Must not be {@code null}. 055 * @param secret The client secret. Must not be {@code null}. 056 */ 057 public ClientSecretPost(final ClientID clientID, final Secret secret) { 058 059 super(ClientAuthenticationMethod.CLIENT_SECRET_POST, clientID, secret); 060 } 061 062 063 /** 064 * Returns the parameter representation of this client secret post 065 * authentication. Note that the parameters are not 066 * {@code application/x-www-form-urlencoded} encoded. 067 * 068 * <p>Parameters map: 069 * 070 * <pre> 071 * "client_id" -> [client-identifier] 072 * "client_secret" -> [client-secret] 073 * </pre> 074 * 075 * @return The parameters map, with keys "client_id" and 076 * "client_secret". 077 */ 078 public Map<String,String> toParameters() { 079 080 Map<String,String> params = new HashMap<>(); 081 params.put("client_id", getClientID().getValue()); 082 params.put("client_secret", getClientSecret().getValue()); 083 return params; 084 } 085 086 087 @Override 088 public void applyTo(final HTTPRequest httpRequest) { 089 090 if (httpRequest.getMethod() != HTTPRequest.Method.POST) 091 throw new SerializeException("The HTTP request method must be POST"); 092 093 ContentType ct = httpRequest.getContentType(); 094 095 if (ct == null) 096 throw new SerializeException("Missing HTTP Content-Type header"); 097 098 if (! ct.match(CommonContentTypes.APPLICATION_URLENCODED)) 099 throw new SerializeException("The HTTP Content-Type header must be " + CommonContentTypes.APPLICATION_URLENCODED); 100 101 Map <String,String> params = httpRequest.getQueryParameters(); 102 103 params.putAll(toParameters()); 104 105 String queryString = URLUtils.serializeParameters(params); 106 107 httpRequest.setQuery(queryString); 108 } 109 110 111 /** 112 * Parses a client secret post authentication from the specified 113 * parameters map. Note that the parameters must not be 114 * {@code application/x-www-form-urlencoded} encoded. 115 * 116 * @param params The parameters map to parse. The client secret post 117 * parameters must be keyed under "client_id" and 118 * "client_secret". The map must not be {@code null}. 119 * 120 * @return The client secret post authentication. 121 * 122 * @throws ParseException If the parameters map couldn't be parsed to a 123 * client secret post authentication. 124 */ 125 public static ClientSecretPost parse(final Map<String,String> params) 126 throws ParseException { 127 128 String clientIDString = params.get("client_id"); 129 130 if (clientIDString == null) 131 throw new ParseException("Malformed client secret post authentication: Missing \"client_id\" parameter"); 132 133 String secretValue = params.get("client_secret"); 134 135 if (secretValue == null) 136 throw new ParseException("Malformed client secret post authentication: Missing \"client_secret\" parameter"); 137 138 return new ClientSecretPost(new ClientID(clientIDString), new Secret(secretValue)); 139 } 140 141 142 /** 143 * Parses a client secret post authentication from the specified 144 * {@code application/x-www-form-urlencoded} encoded parameters string. 145 * 146 * @param paramsString The parameters string to parse. The client secret 147 * post parameters must be keyed under "client_id" 148 * and "client_secret". The string must not be 149 * {@code null}. 150 * 151 * @return The client secret post authentication. 152 * 153 * @throws ParseException If the parameters string couldn't be parsed to 154 * a client secret post authentication. 155 */ 156 public static ClientSecretPost parse(final String paramsString) 157 throws ParseException { 158 159 Map<String,String> params = URLUtils.parseParameters(paramsString); 160 161 return parse(params); 162 } 163 164 165 /** 166 * Parses a client secret post authentication from the specified HTTP 167 * POST request. 168 * 169 * @param httpRequest The HTTP POST request to parse. Must not be 170 * {@code null} and must contain a valid 171 * {@code application/x-www-form-urlencoded} encoded 172 * parameters string in the entity body. The client 173 * secret post parameters must be keyed under 174 * "client_id" and "client_secret". 175 * 176 * @return The client secret post authentication. 177 * 178 * @throws ParseException If the HTTP request header couldn't be parsed 179 * to a valid client secret post authentication. 180 */ 181 public static ClientSecretPost parse(final HTTPRequest httpRequest) 182 throws ParseException { 183 184 httpRequest.ensureMethod(HTTPRequest.Method.POST); 185 httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED); 186 187 return parse(httpRequest.getQueryParameters()); 188 } 189}