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    }