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 * Self-signed certificate mutual TLS client authentication at the Token 037 * endpoint. The client certificate is self-signed, as opposed to 038 * {@link TLSClientAuthentication tls_client_auth} which relies on PKI binding. 039 * Implements {@link ClientAuthenticationMethod#SELF_SIGNED_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-08), section 2.2. 046 * </ul> 047 */ 048@Immutable 049public class SelfSignedTLSClientAuthentication extends AbstractTLSClientAuthentication { 050 051 052 /** 053 * The validated client X.509 certificate from the received HTTPS 054 * request, {@code null} for an outgoing HTTPS request. 055 */ 056 private final X509Certificate x509Certificate; 057 058 059 /** 060 * Creates a new self-signed certificate mutual TLS client 061 * authentication. This constructor is intended for an outgoing token 062 * request. 063 * 064 * @param clientID The client identifier. Must not be 065 * {@code null}. 066 * @param sslSocketFactory The SSL socket factory to use for the 067 * outgoing HTTPS request and to present the 068 * client certificate(s), {@code null} to use 069 * the default one. 070 */ 071 public SelfSignedTLSClientAuthentication(final ClientID clientID, 072 final SSLSocketFactory sslSocketFactory) { 073 074 super(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, clientID, sslSocketFactory); 075 x509Certificate = null; 076 } 077 078 079 /** 080 * Creates a new self-signed certificate mutual TLS client 081 * authentication. This constructor is intended for a received token 082 * request. 083 * 084 * @param clientID The client identifier. Must not be 085 * {@code null}. 086 * @param x509Certificate The validated client X.509 certificate from 087 * the received HTTPS request. Must not be 088 * {@code null}. 089 */ 090 public SelfSignedTLSClientAuthentication(final ClientID clientID, 091 final X509Certificate x509Certificate) { 092 093 super(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, clientID); 094 095 if (x509Certificate == null) { 096 throw new IllegalArgumentException("The client X.509 certificate must not be null"); 097 } 098 099 this.x509Certificate = x509Certificate; 100 } 101 102 103 /** 104 * Returns the validated client X.509 certificate from the received 105 * HTTPS request. 106 * 107 * @return The client X.509 certificate, {@code null} for an outgoing 108 * HTTPS request. 109 */ 110 public X509Certificate getClientX509Certificate() { 111 112 return x509Certificate; 113 } 114 115 116 /** 117 * Parses a self-signed certificate mutual TLS client authentication 118 * from the specified HTTP request. 119 * 120 * @param httpRequest The HTTP request to parse. Must not be 121 * {@code null} and must include a validated client 122 * X.509 certificate. 123 * 124 * @return The self-signed TLS / X.509 certificate client 125 * authentication. 126 * 127 * @throws ParseException If the {@code client_id} or client X.509 128 * certificate is missing. 129 */ 130 public static SelfSignedTLSClientAuthentication parse(final HTTPRequest httpRequest) 131 throws ParseException { 132 133 String query = httpRequest.getQuery(); 134 135 if (query == null) { 136 throw new ParseException("Missing HTTP POST request entity body"); 137 } 138 139 Map<String,List<String>> params = URLUtils.parseParameters(query); 140 141 String clientIDString = MultivaluedMapUtils.getFirstValue(params, "client_id"); 142 143 if (StringUtils.isBlank(clientIDString)) { 144 throw new ParseException("Missing client_id parameter"); 145 } 146 147 X509Certificate cert = httpRequest.getClientX509Certificate(); 148 149 if (cert == null) { 150 throw new ParseException("Missing client X.509 certificate"); 151 } 152 153 return new SelfSignedTLSClientAuthentication(new ClientID(clientIDString), cert); 154 } 155}