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