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