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