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.Collections; 023import java.util.List; 024import java.util.Map; 025import javax.net.ssl.SSLSocketFactory; 026 027import com.nimbusds.common.contenttype.ContentType; 028import com.nimbusds.oauth2.sdk.SerializeException; 029import com.nimbusds.oauth2.sdk.http.HTTPRequest; 030import com.nimbusds.oauth2.sdk.id.ClientID; 031import com.nimbusds.oauth2.sdk.util.URLUtils; 032 033 034/** 035 * The base abstract class for mutual TLS client authentication at the Token 036 * endpoint. 037 */ 038public abstract class TLSClientAuthentication extends ClientAuthentication { 039 040 041 /** 042 * The validated client X.509 certificate from the received HTTPS 043 * request, {@code null} for an outgoing HTTPS request. 044 */ 045 protected final X509Certificate certificate; 046 047 048 /** 049 * The SSL socket factory for an outgoing HTTPS request, {@code null} 050 * to use the default one. 051 */ 052 private final SSLSocketFactory sslSocketFactory; 053 054 055 /** 056 * Creates a new abstract mutual TLS client authentication. This 057 * constructor is intended for an outgoing token request. 058 * 059 * @param method The client authentication method. Must not 060 * be {@code null}. 061 * @param clientID The client identifier. Must not be 062 * {@code null}. 063 * @param sslSocketFactory The SSL socket factory to use for the 064 * outgoing HTTPS request and to present the 065 * client certificate(s), {@code null} to use 066 * the default one. 067 */ 068 protected TLSClientAuthentication(final ClientAuthenticationMethod method, 069 final ClientID clientID, 070 final SSLSocketFactory sslSocketFactory) { 071 072 super(method, clientID); 073 this.sslSocketFactory = sslSocketFactory; 074 certificate = null; 075 } 076 077 078 /** 079 * Creates a new abstract mutual TLS client authentication. This 080 * constructor is intended for a received token request. 081 * 082 * @param method The client authentication method. Must not be 083 * {@code null}. 084 * @param clientID The client identifier. Must not be {@code null}. 085 * @param certificate The validated client X.509 certificate from the 086 * received HTTPS request. Should not be 087 * {@code null}. 088 */ 089 protected TLSClientAuthentication(final ClientAuthenticationMethod method, 090 final ClientID clientID, 091 final X509Certificate certificate) { 092 super(method, clientID); 093 sslSocketFactory = null; 094 this.certificate = certificate; 095 } 096 097 098 /** 099 * Returns the SSL socket factory to use for an outgoing HTTPS request 100 * and to present the client certificate(s). 101 * 102 * @return The SSL socket factory, {@code null} to use the default one. 103 */ 104 public SSLSocketFactory getSSLSocketFactory() { 105 106 return sslSocketFactory; 107 } 108 109 110 /** 111 * The validated client X.509 certificate from the received HTTPS 112 * request. 113 * 114 * @return The validated client X.509 certificate from the received 115 * HTTPS request, {@code null} for an outgoing HTTPS request. 116 */ 117 public X509Certificate getClientX509Certificate() { 118 119 return certificate; 120 } 121 122 123 @Override 124 public void applyTo(final HTTPRequest httpRequest) { 125 126 if (httpRequest.getMethod() != HTTPRequest.Method.POST) 127 throw new SerializeException("The HTTP request method must be POST"); 128 129 ContentType ct = httpRequest.getEntityContentType(); 130 131 if (ct == null) 132 throw new SerializeException("Missing HTTP Content-Type header"); 133 134 if (ct.matches(ContentType.APPLICATION_JSON)) { 135 136 // Possibly request object POST request, nothing to set 137 138 } else if (ct.matches(ContentType.APPLICATION_URLENCODED)) { 139 140 // Token or similar request 141 Map<String,List<String>> params = httpRequest.getQueryParameters(); 142 params.put("client_id", Collections.singletonList(getClientID().getValue())); 143 String queryString = URLUtils.serializeParameters(params); 144 httpRequest.setQuery(queryString); 145 146 } else { 147 throw new SerializeException("The HTTP Content-Type header must be " + ContentType.APPLICATION_URLENCODED); 148 } 149 150 // If set for an outgoing request 151 httpRequest.setSSLSocketFactory(sslSocketFactory); 152 } 153}