001 package com.nimbusds.oauth2.sdk.auth; 002 003 004 import java.util.Collections; 005 import java.util.HashSet; 006 import java.util.Map; 007 import java.util.Set; 008 009 import net.jcip.annotations.Immutable; 010 011 import com.nimbusds.jose.JWSAlgorithm; 012 import com.nimbusds.jwt.SignedJWT; 013 014 import com.nimbusds.oauth2.sdk.ParseException; 015 import com.nimbusds.oauth2.sdk.id.ClientID; 016 import com.nimbusds.oauth2.sdk.http.CommonContentTypes; 017 import com.nimbusds.oauth2.sdk.http.HTTPRequest; 018 import com.nimbusds.oauth2.sdk.util.URLUtils; 019 020 021 /** 022 * Client secret JWT authentication at the Token endpoint. Implements 023 * {@link ClientAuthenticationMethod#CLIENT_SECRET_JWT}. This class is 024 * immutable. 025 * 026 * <p>Supported signature JSON Web Algorithms (JWAs) by this implementation: 027 * 028 * <ul> 029 * <li>HS256 030 * <li>HS384 031 * <li>HS512 032 * </ul> 033 * 034 * <p>Related specifications: 035 * 036 * <ul> 037 * <li>Assertion Framework for OAuth 2.0 (draft-ietf-oauth-assertions-06) 038 * <li>JSON Web Token (JWT) Bearer Token Profiles for OAuth 2.0 039 * (draft-ietf-oauth-jwt-bearer-04). 040 * </ul> 041 * 042 * @author Vladimir Dzhuvinov 043 */ 044 @Immutable 045 public final class ClientSecretJWT extends JWTAuthentication { 046 047 048 /** 049 * Gets the set of supported signature JSON Web Algorithms (JWAs) by 050 * this implementation of client secret JSON Web Token (JWT) 051 * authentication. 052 * 053 * @return The set of supported JSON Web Algorithms (JWAs). 054 */ 055 public static Set<JWSAlgorithm> getSupportedJWAs() { 056 057 Set<JWSAlgorithm> supported = new HashSet<JWSAlgorithm>(); 058 059 supported.add(JWSAlgorithm.HS256); 060 supported.add(JWSAlgorithm.HS384); 061 supported.add(JWSAlgorithm.HS512); 062 063 return Collections.unmodifiableSet(supported); 064 } 065 066 067 /** 068 * Creates a new client secret JWT authentication. 069 * 070 * @param clientAssertion The client assertion, corresponding to the 071 * {@code client_assertion_parameter}, as an 072 * HMAC-signed JWT. Must not be {@code null}. 073 * @param clientID Optional client identifier, corresponding to 074 * the {@code client_id} parameter. {@code null} 075 * if not specified. 076 */ 077 public ClientSecretJWT(final SignedJWT clientAssertion, final ClientID clientID) { 078 079 super(ClientAuthenticationMethod.CLIENT_SECRET_JWT, clientAssertion, clientID); 080 } 081 082 083 /** 084 * Parses the specified parameters map for a client secret JSON Web 085 * Token (JWT) authentication. Note that the parameters must not be 086 * {@code application/x-www-form-urlencoded} encoded. 087 * 088 * @param params The parameters map to parse. The client secret JSON 089 * Web Token (JWT) parameters must be keyed under 090 * "client_assertion" and "client_assertion_type". The 091 * map must not be {@code null}. 092 * 093 * @return The client secret JSON Web Token (JWT) authentication. 094 * 095 * @throws ParseException If the parameters map couldn't be parsed to a 096 * client secret JSON Web Token (JWT) 097 * authentication. 098 */ 099 public static ClientSecretJWT parse(final Map<String,String> params) 100 throws ParseException { 101 102 JWTAuthentication.ensureClientAssertionType(params); 103 104 SignedJWT clientAssertion = JWTAuthentication.parseClientAssertion(params); 105 106 ClientID clientID = JWTAuthentication.parseClientID(params); 107 108 JWSAlgorithm alg = clientAssertion.getHeader().getAlgorithm(); 109 110 if (getSupportedJWAs().contains(alg)) 111 throw new ParseException("The client assertion JWT must be HMAC-signed (HS256, HS384 or HS512)"); 112 113 return new ClientSecretJWT(clientAssertion, clientID); 114 } 115 116 117 /** 118 * Parses a client secret JSON Web Token (JWT) authentication from the 119 * specified {@code application/x-www-form-urlencoded} encoded 120 * parameters string. 121 * 122 * @param paramsString The parameters string to parse. The client secret 123 * JSON Web Token (JWT) parameters must be keyed 124 * under "client_assertion" and 125 * "client_assertion_type". The string must not be 126 * {@code null}. 127 * 128 * @return The client secret JSON Web Token (JWT) authentication. 129 * 130 * @throws ParseException If the parameters string couldn't be parsed 131 * to a client secret JSON Web Token (JWT) 132 * authentication. 133 */ 134 public static ClientSecretJWT parse(final String paramsString) 135 throws ParseException { 136 137 Map<String,String> params = URLUtils.parseParameters(paramsString); 138 139 return parse(params); 140 } 141 142 143 /** 144 * Parses the specified HTTP POST request for a client secret JSON Web 145 * Token (JWT) authentication. 146 * 147 * @param httpRequest The HTTP POST request to parse. Must not be 148 * {@code null} and must contain a valid 149 * {@code application/x-www-form-urlencoded} encoded 150 * parameters string in the entity body. The client 151 * secret JSON Web Token (JWT) parameters must be 152 * keyed under "client_assertion" and 153 * "client_assertion_type". 154 * 155 * @return The client secret JSON Web Token (JWT) authentication. 156 * 157 * @throws ParseException If the HTTP request header couldn't be parsed 158 * to a client secret JSON Web Token (JWT) 159 * authentication. 160 */ 161 public static ClientSecretJWT parse(final HTTPRequest httpRequest) 162 throws ParseException { 163 164 httpRequest.ensureMethod(HTTPRequest.Method.POST); 165 httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED); 166 167 return parse(httpRequest.getQueryParameters()); 168 } 169 }