Trying to pass along x509 client certificate to second server
up vote
0
down vote
favorite
I'm trying to give server "A" the ability to connect to server "B" using the same X509 client certificate it received from the user. Here are the basics of where I am so far:
public int makeRemoteCall() {
URL url = new URL("https://host.com/service/request");
HttpsURLConnection conn = url.openConnection();
SSLSocketFactory factory = getFactoryFromSessionCert();
conn.setSSLSocketFactory(factory);
int responseCode = conn.getResponseCode();
return responseCode;
}
public static SSLSocketFactory getFactoryFromSessionCert() throws Exception {
HttpServletRequest request = getRequest();
X509Certificate certs = (X509Certificate)request.getAttribute("javax.servlet.request.X509Certificate");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("client_cert", certs[0]);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, null);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, null);
return context.getSocketFactory();
}
I am able to retrieve the client's certificate without trouble, and can verify that it does indeed end up in keyStore
. But the certificate doesn't seem to make it into keyManagerFactory
.
I thought the issue was that I'm not providing a password in keyManagerFactory.init(keyStore, null)
, so I tried providing it but without success. And should I even have to? I understand that I would need a password if I were loading certificates and keys from a protected file, but here I'm just trying to pass along an already exposed public certificate.
As further background, this basic scheme works if I replace getFactoryFromSessionCert()
with this:
public static SSLSocketFactory getFactory(File pKeyFile, String pKeyPassword) throws Exception {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return context.getSocketFactory();
}
So, what am I not understanding? And how should I pass along a client certificate?
java ssl x509certificate client-certificates
add a comment |
up vote
0
down vote
favorite
I'm trying to give server "A" the ability to connect to server "B" using the same X509 client certificate it received from the user. Here are the basics of where I am so far:
public int makeRemoteCall() {
URL url = new URL("https://host.com/service/request");
HttpsURLConnection conn = url.openConnection();
SSLSocketFactory factory = getFactoryFromSessionCert();
conn.setSSLSocketFactory(factory);
int responseCode = conn.getResponseCode();
return responseCode;
}
public static SSLSocketFactory getFactoryFromSessionCert() throws Exception {
HttpServletRequest request = getRequest();
X509Certificate certs = (X509Certificate)request.getAttribute("javax.servlet.request.X509Certificate");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("client_cert", certs[0]);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, null);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, null);
return context.getSocketFactory();
}
I am able to retrieve the client's certificate without trouble, and can verify that it does indeed end up in keyStore
. But the certificate doesn't seem to make it into keyManagerFactory
.
I thought the issue was that I'm not providing a password in keyManagerFactory.init(keyStore, null)
, so I tried providing it but without success. And should I even have to? I understand that I would need a password if I were loading certificates and keys from a protected file, but here I'm just trying to pass along an already exposed public certificate.
As further background, this basic scheme works if I replace getFactoryFromSessionCert()
with this:
public static SSLSocketFactory getFactory(File pKeyFile, String pKeyPassword) throws Exception {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return context.getSocketFactory();
}
So, what am I not understanding? And how should I pass along a client certificate?
java ssl x509certificate client-certificates
4
There's a lot of concepts about PKI being misused in your code. You can't use a X509Certificate without a private key to start a SSL connection, the server in the other side will never accept the handshake. If you have plans to just pass the X509 along you can set it in the header of the new request. The simple answer is... you can't reuse the mutual TLS channel in the second server because you don't have the private key to make the key exchange.
– argoth
Nov 19 at 21:06
Thanks, @argoth . I wasn't thinking of it like that, but it makes sense now. So, assuming I can make the second SSL connection with the server's own certificate, can the original client certificate be passed along to the second server in a way that satisfies client authentication? I can make your suggestion of sending it in the header work (thanks!), but what would be the proper way of solving this? I imagine it's a common need.
– Didjit
Nov 20 at 17:58
The more I think about it, the more I realize what I'm really talking about is some kind of centralized authentication. Like Kerberos, except that's overkill for my needs. I'll probably go with putting at least the essential information in the headers or a cookie, but this seems like a really bad practice in general. What would be the simplest legitimate approach?
– Didjit
Nov 20 at 19:41
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm trying to give server "A" the ability to connect to server "B" using the same X509 client certificate it received from the user. Here are the basics of where I am so far:
public int makeRemoteCall() {
URL url = new URL("https://host.com/service/request");
HttpsURLConnection conn = url.openConnection();
SSLSocketFactory factory = getFactoryFromSessionCert();
conn.setSSLSocketFactory(factory);
int responseCode = conn.getResponseCode();
return responseCode;
}
public static SSLSocketFactory getFactoryFromSessionCert() throws Exception {
HttpServletRequest request = getRequest();
X509Certificate certs = (X509Certificate)request.getAttribute("javax.servlet.request.X509Certificate");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("client_cert", certs[0]);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, null);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, null);
return context.getSocketFactory();
}
I am able to retrieve the client's certificate without trouble, and can verify that it does indeed end up in keyStore
. But the certificate doesn't seem to make it into keyManagerFactory
.
I thought the issue was that I'm not providing a password in keyManagerFactory.init(keyStore, null)
, so I tried providing it but without success. And should I even have to? I understand that I would need a password if I were loading certificates and keys from a protected file, but here I'm just trying to pass along an already exposed public certificate.
As further background, this basic scheme works if I replace getFactoryFromSessionCert()
with this:
public static SSLSocketFactory getFactory(File pKeyFile, String pKeyPassword) throws Exception {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return context.getSocketFactory();
}
So, what am I not understanding? And how should I pass along a client certificate?
java ssl x509certificate client-certificates
I'm trying to give server "A" the ability to connect to server "B" using the same X509 client certificate it received from the user. Here are the basics of where I am so far:
public int makeRemoteCall() {
URL url = new URL("https://host.com/service/request");
HttpsURLConnection conn = url.openConnection();
SSLSocketFactory factory = getFactoryFromSessionCert();
conn.setSSLSocketFactory(factory);
int responseCode = conn.getResponseCode();
return responseCode;
}
public static SSLSocketFactory getFactoryFromSessionCert() throws Exception {
HttpServletRequest request = getRequest();
X509Certificate certs = (X509Certificate)request.getAttribute("javax.servlet.request.X509Certificate");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("client_cert", certs[0]);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, null);
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, null);
return context.getSocketFactory();
}
I am able to retrieve the client's certificate without trouble, and can verify that it does indeed end up in keyStore
. But the certificate doesn't seem to make it into keyManagerFactory
.
I thought the issue was that I'm not providing a password in keyManagerFactory.init(keyStore, null)
, so I tried providing it but without success. And should I even have to? I understand that I would need a password if I were loading certificates and keys from a protected file, but here I'm just trying to pass along an already exposed public certificate.
As further background, this basic scheme works if I replace getFactoryFromSessionCert()
with this:
public static SSLSocketFactory getFactory(File pKeyFile, String pKeyPassword) throws Exception {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
return context.getSocketFactory();
}
So, what am I not understanding? And how should I pass along a client certificate?
java ssl x509certificate client-certificates
java ssl x509certificate client-certificates
asked Nov 19 at 20:41
Didjit
1881214
1881214
4
There's a lot of concepts about PKI being misused in your code. You can't use a X509Certificate without a private key to start a SSL connection, the server in the other side will never accept the handshake. If you have plans to just pass the X509 along you can set it in the header of the new request. The simple answer is... you can't reuse the mutual TLS channel in the second server because you don't have the private key to make the key exchange.
– argoth
Nov 19 at 21:06
Thanks, @argoth . I wasn't thinking of it like that, but it makes sense now. So, assuming I can make the second SSL connection with the server's own certificate, can the original client certificate be passed along to the second server in a way that satisfies client authentication? I can make your suggestion of sending it in the header work (thanks!), but what would be the proper way of solving this? I imagine it's a common need.
– Didjit
Nov 20 at 17:58
The more I think about it, the more I realize what I'm really talking about is some kind of centralized authentication. Like Kerberos, except that's overkill for my needs. I'll probably go with putting at least the essential information in the headers or a cookie, but this seems like a really bad practice in general. What would be the simplest legitimate approach?
– Didjit
Nov 20 at 19:41
add a comment |
4
There's a lot of concepts about PKI being misused in your code. You can't use a X509Certificate without a private key to start a SSL connection, the server in the other side will never accept the handshake. If you have plans to just pass the X509 along you can set it in the header of the new request. The simple answer is... you can't reuse the mutual TLS channel in the second server because you don't have the private key to make the key exchange.
– argoth
Nov 19 at 21:06
Thanks, @argoth . I wasn't thinking of it like that, but it makes sense now. So, assuming I can make the second SSL connection with the server's own certificate, can the original client certificate be passed along to the second server in a way that satisfies client authentication? I can make your suggestion of sending it in the header work (thanks!), but what would be the proper way of solving this? I imagine it's a common need.
– Didjit
Nov 20 at 17:58
The more I think about it, the more I realize what I'm really talking about is some kind of centralized authentication. Like Kerberos, except that's overkill for my needs. I'll probably go with putting at least the essential information in the headers or a cookie, but this seems like a really bad practice in general. What would be the simplest legitimate approach?
– Didjit
Nov 20 at 19:41
4
4
There's a lot of concepts about PKI being misused in your code. You can't use a X509Certificate without a private key to start a SSL connection, the server in the other side will never accept the handshake. If you have plans to just pass the X509 along you can set it in the header of the new request. The simple answer is... you can't reuse the mutual TLS channel in the second server because you don't have the private key to make the key exchange.
– argoth
Nov 19 at 21:06
There's a lot of concepts about PKI being misused in your code. You can't use a X509Certificate without a private key to start a SSL connection, the server in the other side will never accept the handshake. If you have plans to just pass the X509 along you can set it in the header of the new request. The simple answer is... you can't reuse the mutual TLS channel in the second server because you don't have the private key to make the key exchange.
– argoth
Nov 19 at 21:06
Thanks, @argoth . I wasn't thinking of it like that, but it makes sense now. So, assuming I can make the second SSL connection with the server's own certificate, can the original client certificate be passed along to the second server in a way that satisfies client authentication? I can make your suggestion of sending it in the header work (thanks!), but what would be the proper way of solving this? I imagine it's a common need.
– Didjit
Nov 20 at 17:58
Thanks, @argoth . I wasn't thinking of it like that, but it makes sense now. So, assuming I can make the second SSL connection with the server's own certificate, can the original client certificate be passed along to the second server in a way that satisfies client authentication? I can make your suggestion of sending it in the header work (thanks!), but what would be the proper way of solving this? I imagine it's a common need.
– Didjit
Nov 20 at 17:58
The more I think about it, the more I realize what I'm really talking about is some kind of centralized authentication. Like Kerberos, except that's overkill for my needs. I'll probably go with putting at least the essential information in the headers or a cookie, but this seems like a really bad practice in general. What would be the simplest legitimate approach?
– Didjit
Nov 20 at 19:41
The more I think about it, the more I realize what I'm really talking about is some kind of centralized authentication. Like Kerberos, except that's overkill for my needs. I'll probably go with putting at least the essential information in the headers or a cookie, but this seems like a really bad practice in general. What would be the simplest legitimate approach?
– Didjit
Nov 20 at 19:41
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53382331%2ftrying-to-pass-along-x509-client-certificate-to-second-server%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
There's a lot of concepts about PKI being misused in your code. You can't use a X509Certificate without a private key to start a SSL connection, the server in the other side will never accept the handshake. If you have plans to just pass the X509 along you can set it in the header of the new request. The simple answer is... you can't reuse the mutual TLS channel in the second server because you don't have the private key to make the key exchange.
– argoth
Nov 19 at 21:06
Thanks, @argoth . I wasn't thinking of it like that, but it makes sense now. So, assuming I can make the second SSL connection with the server's own certificate, can the original client certificate be passed along to the second server in a way that satisfies client authentication? I can make your suggestion of sending it in the header work (thanks!), but what would be the proper way of solving this? I imagine it's a common need.
– Didjit
Nov 20 at 17:58
The more I think about it, the more I realize what I'm really talking about is some kind of centralized authentication. Like Kerberos, except that's overkill for my needs. I'll probably go with putting at least the essential information in the headers or a cookie, but this seems like a really bad practice in general. What would be the simplest legitimate approach?
– Didjit
Nov 20 at 19:41