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