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