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