001package com.nimbusds.oauth2.sdk.auth;
002
003
004import java.util.Map;
005
006import com.nimbusds.oauth2.sdk.ParseException;
007import com.nimbusds.oauth2.sdk.SerializeException;
008import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
009import com.nimbusds.oauth2.sdk.http.HTTPRequest;
010import com.nimbusds.oauth2.sdk.id.ClientID;
011import com.nimbusds.oauth2.sdk.util.URLUtils;
012
013
014/**
015 * Base abstract class for client authentication at the Token endpoint.
016 *
017 * <p>Related specifications:
018 *
019 * <ul>
020 *     <li>OAuth 2.0 (RFC 6749), section 2.3.
021 * </ul>
022 */
023public abstract class ClientAuthentication {
024        
025        
026        /**
027         * The client authentication method.
028         */
029        private final ClientAuthenticationMethod method;
030
031
032        /**
033         * The client ID.
034         */
035        private final ClientID clientID;
036        
037        
038        /**
039         * Creates a new abstract client authentication.
040         *
041         * @param method   The client authentication method. Must not be
042         *                 {@code null}.
043         * @param clientID The client identifier. Must not be {@code null}.
044         */
045        protected ClientAuthentication(final ClientAuthenticationMethod method, final ClientID clientID) {
046        
047                if (method == null)
048                        throw new IllegalArgumentException("The client authentication method must not be null");
049                
050                this.method = method;
051
052
053                if (clientID == null)
054                        throw new IllegalArgumentException("The client identifier must not be null");
055
056                this.clientID = clientID;
057        }
058        
059        
060        /**
061         * Gets the client authentication method.
062         *
063         * @return The client authentication method.
064         */
065        public ClientAuthenticationMethod getMethod() {
066        
067                return method;
068        }
069
070
071        /**
072         * Gets the client identifier.
073         *
074         * @return The client identifier.
075         */
076        public ClientID getClientID() {
077
078                return clientID;
079        }
080        
081        
082        /**
083         * Parses the specified HTTP request for a supported client 
084         * authentication (see {@link ClientAuthenticationMethod}). This method
085         * is intended to aid parsing of authenticated 
086         * {@link com.nimbusds.oauth2.sdk.TokenRequest}s.
087         *
088         * @param httpRequest The HTTP request to parse. Must not be 
089         *                    {@code null}.
090         *
091         * @return The client authentication method, {@code null} if none or 
092         *         the method is not supported.
093         *
094         * @throws ParseException If the inferred client authentication 
095         *                        couldn't be parsed.
096         */
097        public static ClientAuthentication parse(final HTTPRequest httpRequest)
098                throws ParseException {
099        
100                // Check for client secret basic
101                if (httpRequest.getAuthorization() != null && 
102                    httpRequest.getAuthorization().startsWith("Basic"))
103
104                        return ClientSecretBasic.parse(httpRequest);
105                
106                // The other methods require HTTP POST with URL-encoded params
107                if (httpRequest.getMethod() != HTTPRequest.Method.POST &&
108                    ! httpRequest.getContentType().match(CommonContentTypes.APPLICATION_URLENCODED))
109                        return null;
110                
111                
112                String query = httpRequest.getQuery();
113                
114                if (query == null)
115                        return null;
116                
117                Map<String,String> params = URLUtils.parseParameters(query);
118                
119                // We have client secret post
120                if (params.containsKey("client_id") && params.containsKey("client_secret"))
121                        return ClientSecretPost.parse(httpRequest);
122                
123                // Do we have a signed JWT assertion?
124                if (params.containsKey("client_assertion") && params.containsKey("client_assertion_type"))
125                        return JWTAuthentication.parse(httpRequest);
126                else
127                        return null;
128        }
129        
130        
131        /**
132         * Applies the authentication to the specified HTTP request by setting 
133         * its Authorization header and/or POST entity-body parameters 
134         * (according to the implemented client authentication method).
135         *
136         * @param httpRequest The HTTP request. Must not be {@code null}.
137         *
138         * @throws SerializeException If the client authentication parameters
139         *                            couldn't be applied to the HTTP request.
140         */
141        public abstract void applyTo(final HTTPRequest httpRequest) 
142                throws SerializeException;
143}