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.security.cert.X509Certificate;
022import java.util.List;
023import java.util.Map;
024import javax.net.ssl.SSLSocketFactory;
025
026import com.nimbusds.oauth2.sdk.ParseException;
027import com.nimbusds.oauth2.sdk.http.HTTPRequest;
028import com.nimbusds.oauth2.sdk.id.ClientID;
029import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
030import com.nimbusds.oauth2.sdk.util.StringUtils;
031import com.nimbusds.oauth2.sdk.util.URLUtils;
032import net.jcip.annotations.Immutable;
033
034
035/**
036 * PKI mutual TLS client authentication at the Token endpoint. The client
037 * certificate is PKI bound, as opposed to
038 * {@link SelfSignedTLSClientAuthentication self_signed_tls_client_auth} which
039 * relies on a self-signed certificate. Implements
040 * {@link ClientAuthenticationMethod#TLS_CLIENT_AUTH}.
041 *
042 * <p>Related specifications:
043 *
044 * <ul>
045 *     <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound
046 *         Access Tokens (draft-ietf-oauth-mtls-15), section 2.1.
047 * </ul>
048 */
049@Immutable
050public class PKITLSClientAuthentication extends TLSClientAuthentication {
051        
052        
053        /**
054         * The client X.509 certificate subject DN.
055         */
056        private final String certSubjectDN;
057        
058        /**
059         * The client X.509 certificate used for authentication
060         */
061        private final X509Certificate certificate;
062        
063        
064        /**
065         * Creates a new PKI mutual TLS client authentication. This constructor
066         * is intended for an outgoing token request.
067         *
068         * @param clientID         The client identifier. Must not be
069         *                         {@code null}.
070         * @param sslSocketFactory The SSL socket factory to use for the
071         *                         outgoing HTTPS request and to present the
072         *                         client certificate(s), {@code null} to use
073         *                         the default one.
074         */
075        public PKITLSClientAuthentication(final ClientID clientID,
076                                          final SSLSocketFactory sslSocketFactory) {
077                
078                super(ClientAuthenticationMethod.TLS_CLIENT_AUTH, clientID, sslSocketFactory);
079                certSubjectDN = null;
080                certificate = null;
081        }
082        
083        
084        /**
085         * Creates a new PKI mutual TLS client authentication. This constructor
086         * is intended for a received token request.
087         *
088         * @param clientID      The client identifier. Must not be
089         *                      {@code null}.
090         * @param certSubjectDN The subject DN of the received validated client
091         *                      X.509 certificate. Must not be {@code null}.
092         * @deprecated This constructor does set the certificate
093         */
094        @Deprecated
095        public PKITLSClientAuthentication(final ClientID clientID,
096                                          final String certSubjectDN) {
097                
098                super(ClientAuthenticationMethod.TLS_CLIENT_AUTH, clientID);
099                
100                if (certSubjectDN == null) {
101                        throw new IllegalArgumentException("The X.509 client certificate subject DN must not be null");
102                }
103                this.certSubjectDN = certSubjectDN;
104                this.certificate = null;
105        }
106        
107        /**
108         * Creates a new PKI mutual TLS client authentication. This constructor
109         * is intended for a received token request.
110         *
111         * @param clientID      The client identifier. Must not be
112         *                      {@code null}.
113         * @param certificate   The received validated client X.509 certificate.
114         *                      Must not be {@code null}.
115         */
116        public PKITLSClientAuthentication(final ClientID clientID,
117                                          final X509Certificate certificate) {
118                
119                super(ClientAuthenticationMethod.TLS_CLIENT_AUTH, clientID);
120                
121                if (certificate == null) {
122                        throw new IllegalArgumentException("The X.509 client certificate must not be null");
123                }
124                this.certSubjectDN = certificate.getSubjectDN().getName();
125                this.certificate = certificate;
126        }
127        
128        
129        /**
130         * Gets the subject DN of the received validated client X.509
131         * certificate.
132         *
133         * @return The subject DN.
134         */
135        public String getClientX509CertificateSubjectDN() {
136                
137                return certSubjectDN;
138        }
139        
140        
141        /**
142         * Gets the received validated client X.509 certificate.
143         *
144         * @return The X.509 certificated used for authentication
145         */
146        public X509Certificate getClientX509Certificate() {
147                
148                return certificate;
149        }
150        
151        
152        /**
153         * Parses a PKI mutual TLS client authentication from the specified
154         * HTTP request.
155         *
156         * @param httpRequest The HTTP request to parse. Must not be
157         *                    {@code null} and must include a validated client
158         *                    X.509 certificate.
159         *
160         * @return The PKI mutual TLS client authentication.
161         *
162         * @throws ParseException If the {@code client_id} or client X.509
163         *                        certificate is missing.
164         */
165        public static PKITLSClientAuthentication parse(final HTTPRequest httpRequest)
166                throws ParseException {
167                
168                String query = httpRequest.getQuery();
169                
170                if (query == null) {
171                        throw new ParseException("Missing HTTP POST request entity body");
172                }
173                
174                Map<String,List<String>> params = URLUtils.parseParameters(query);
175                
176                String clientIDString = MultivaluedMapUtils.getFirstValue(params, "client_id");
177                
178                if (StringUtils.isBlank(clientIDString)) {
179                        throw new ParseException("Missing client_id parameter");
180                }
181                
182                if (httpRequest.getClientX509Certificate() == null) {
183                        throw new ParseException("Missing client X.509 certificate");
184                }
185                
186                return new PKITLSClientAuthentication(
187                        new ClientID(clientIDString),
188                        httpRequest.getClientX509Certificate()
189                );
190        }
191}