Docusign Connect mTLS client certificates - docusignapi

Context
I'm using mTLS to secure Docusign Webhooks (Docusign Connect Service). I'm able to make a successful mTLS connection to get certificate fingerprint, according to the documentation.
The next suggested step is to do access control by validating the certificate fingerprint and possibly the Distinguished Name (DN) but I'm confused what should the correct way to do so.
Questions
How do we know which client certificate is going to be sent by DocuSign to our listener in live environment (theoretically can be one of these and which logic is used to determine which one is sent? Should we validate which certification is sent by the DN (e.g. connect.docusign.net)?
What information should we validate from the certificate message? The fingerprint, DN, both or more?
With the above, how can we know all possible fingerprints to validate from server side, assuming different webhooks messages can send different client certificates? Should we compute the fingerprint of all public connect certificates to get a full list?
What is the best way to handle expirations of client certificates?

Re:
Q. How do we know which client certificate is going to be sent by DocuSign to our listener in live environment (theoretically can be one of these and which logic is used to determine which one is sent? Should we validate which certification is sent by the DN (e.g. connect.docusign.net)?
A. Best is to validate based on the certificate's fingerprint matching a fingerprint of one of the expected certificates. DocuSign uses different certificates depending on the platform. But there's a limited set of certs used, so it should not be a big deal to check to see if the offered cert matches one of the expected certs.
Q. What information should we validate from the certificate message? The fingerprint, DN, both or more?
A. I'd recommend the fingerprint since it is more specific than the DN. With the DN, you're trusting the CAs to not issue a cert with a DocuSign DN to a bad guy. It should never happen but it has in the past (not to DocuSign though). See Rogue certificates
Q. With the above, how can we know all possible fingerprints to validate from server side, assuming different webhooks messages can send different client certificates? Should we compute the fingerprint of all public connect certificates to get a full list?
A. DocuSign uses a limited set of five certificates for webhook notifications, see the list on the trust center in the Connect Certificates section. Checking the incoming certificate against five or ten (see below) fingerprints is not a big deal.
Q. What is the best way to handle expirations of client certificates?
A. When the new certificates are announced, compute their fingerprints and add them to your system.
Then test by switching your DocuSign account to use the new certificates. Once the test succeeds, you can delete the fingerprints of the old certs.

Related

DocuSign: How to verify Webhoook requests?

On this page: https://developers.docusign.com/esign-rest-api/code-examples/webhook-status, the last section is called: There’s more. And there you can read that there are 3 ways to check that DocuSign is making the web hook request:
you can check the SSL/TSL certificate of the webhook caller (DocuSign).
set DocuSign to digitally sign the data
DocuSign publishes the IP address ranges
If we examine all these options we have:
This is false, you can't check the SSL certificate of who is making the request to you. SSL certs are designed to be used by clients connecting to servers to check that there is no man in the middle attack. And only the client can verify the cert of a server, not the other way around.
I can't find on the page any mention how to set the signature, and most importantly, how to check it.
The link provided to the Public IPs: https://trust.docusign.com/en-us/trust-certifications/ip-ranges/, does not work.
My questions are:
Where can I find some documentation about the signature process?
Where is the page with the public IPs?
The best way to do that is to create an HMAC key and use that to confirm that the calls are authentic.
Here is a full article on how to do that - https://developers.docusign.com/esign-rest-api/guides/connect-hmac
Thank you for reporting the out of date documentation. I've filed an internal bug report, DEVDOCS-1565, to have it updated.
As Inbar says in his answer, these days, the best solution is HMAC. You can also combine it with Basic Authentication if you're using DocuSign webhooks at the account level.
HMAC gives you the guarantees that the message did originate from DocuSign and that the message was not altered in transmission.
Don't set up a server on the Internet
The old way of receiving webhook messages was to set up a server that is accessible on the public internet. Due to the costs and Information Security issues creating and maintaining a service on the Internet, these days I suggest that you skip it.
Instead, use a cloud PAAS (AWS, Azure, Google Cloud, etc etc) to receive and queue the messages. Then, from behind your firewall, you can dequeue and process them. (With no changes to your firewall.)
See the Connect- series of code examples.
Mutual TLS for checking the client's certificate
Note that you can check the certificate of a client. This feature of the TLS (ne SSL) protocol is called Mutual TLS and is supported by DocuSign webhooks.
But HMAC is better since it also guarantees message integrity.

Public keys in OpenID Connect

I'm currently trying to use IdentityServer4 to build a single-signon experience for my users across different apps I have. They are all hosted in the same local network and no third-party apps authenticate with it. The client apps are still Katana/Owin-based.
I'm using the implicit workflow.
At the moment I still use a certificate randomly generated at runtime to sign tokens.
I wonder
whether I actually need more and what the implications are of leaving it as it is and
how the signature is actually validated by clients.
To the second question I found this piece in the openidconnect spec:
The OP advertises its public keys via its Discovery document, or may
supply this information by other means. The RP declares its public
keys via its Dynamic Registration request, or may communicate this
information by other means.
So does that mean Katana is actually getting the public keys from IdentityServer4 and validates accordingly? And if so, would it matter if it the certificate changes? The time between issuing and validating a token is always very small, correct? So why would I need a proper, rarely-changing certificate?
Generating a new certificate on app startup has a few downsides:
If you restart your IDS4 process you effectively invalidate any otherwise valid tokens as the signature will no longer be valid
Inability to scale out - all servers need to have the same signing and validation keys
Clients might only periodically update their discovery info so you need to allow for a rollover period, something that IDS4 supports as you can have more than one validation key.
See the guidance here: http://docs.identityserver.io/en/release/topics/crypto.html
The next simplest option would be to use a self-issued cert that's installed in the host machine's ceritificate store.
First of all, OpenID Connect discovery is a process of communicating relying party to retrieve provider's information, dynamically. There is a dedicated specification for this, OpenID Connect Discovery 1.0
According to it's metadata section, jwks_uri explains about token signing key publication.
1. So does that mean Katana is actually getting the public keys from IdentityServer4 and validates accordingly?
Yes it should. If your applications (relying parties) want dynamic information, you should go ahead with discovery document to retrieve token signing key information.
2 And if so, would it matter if it the certificate changes? The time between issuing and validating a token is always very small, correct?
Discovery document is part of OpenID Connect dynamic (reference - http://openid.net/connect/ ). So yes, it can be used to convey certificate changes to relying party (token consumers)
3. So why would I need a proper, rarely-changing certificate?
Certificate must be there to validate id tokens issued by identity provider. So at minimum, certificate must live till last token expires. Other than that, one might be using proper certificates issued by a CA, which comes with a cost. So, some implementations could have rarely changing certificates.
Bonus : how the signature is actually validated by clients.
You hash your received message, compare it against decrypted signature using public key of the certificate. Also, if you are wondering the format of key information, it is a JWK defined by RFC7517.
P.S - ID Token validation is same as validating a JWT explained by JWT spec.
Note - I am not an expert in PKI domain. Some expert could point out something else for short lived certificates independent of OpenID Connect protocol.

TLS man in the middle security certificates

First of all, I apologize for sending yet another question about this seeing as there are so many related posts. After reading through them and related sites I'm still not clear on a few points.
Browser connects to server through secure socket
Server responds with its public key with its certificate. This is the step I have the most trouble with. In this message from server to client, can the certificate be easily separated from the server's public key? If it's a root certificate (one which is already included in the browser) then a man-in-the-middle can't fake it, but what if it's not? Can't whatever this online mechanism the client uses to verify the certificate be hijacked? Furthermore, if the client's computer is compromised, the root CA's can be compromised, right? Any steps that avoid this? One last thing: It is said that a certificate is insecure until signed. I can't figure out what this means, especially since a certificate can sign itself. I think it's supposed to mean that someone is assuring the authenticity of the message, so a certificate signing itself sounds insecure ("Are you a REAL certificate?"..."ummm, sure, sure I am"). If the mechanism for authenticating a certificate is the internet, I'm wondering how is that secure. Is signing a certificate the same as thing (literally) as saying the client verifies the certificate?
Session key is encrypted with public key and sent to server. This session key is a symmetric key that both server and client will use for remainder of encrypted communication.
I must say, most information online is so vague. So many holes in explanations and hand-waving going on. My guess is that very few people know the actual mechanisms very well?
You've left out several steps. One of them is that the server sends a digital signature over the entire handshake so far, signed with its private key. Only the server can do that, with its own certificate. Nobody else's. The client verifies the digital signature using the public key in the certificate that was sent. That proves that the server owns the certificate. It also proves that the server is the same entity that sent all the other handshake messages.
BTW your step 3 is imaginary. The session key is never sent at all. It is computed independently at both ends.
EDIT Comments on your answer:
Server (from JoesGoods) gets a certificate from the CA via?
Usually via an Internet browser.
Can this be hijacked?
No more than any other secure SSL session can be.
The certificate is "signed"
Correct.
which means a bit of it is encrypted using the CA's private key.
No. You made that up.
Specifically the bit that has the web server's info (JoesGoods' server info)
No. You made that up.
The entire certificate is signed, and that does not mean 'encrypted', with the CA's private key.
Bob's browser connects to server through a secure socket and sends a "hello" packet.
The socket isn't secure at this point. It's just plaintext.
The server sends its public key and certificate to Bob.
No. The server sends its certificate. The public key is already inside the certificate.
the browser checks that the webserver (JoesGoods) matches what's in the signed portion of the certificate
The entire certificate is signed. The client checks that the server it is connecting to matches the subjectDN of the certificate.
The webserver's public key is also signed with the CA's private key
Because it's in the certificate. Otherwise there is no other way this can be accomplished. That's why it isn't sent separately, and it's also why the entire certificate is signed, not just the bits you like.
The browser sends a client key exchange packet to the webserver (JoesGoods) using the webserver's public key included in step (2).
This part is cipher suite-dependent. What you have described applies to RSA cipher suites. Diffie-Hellman is a different story, and there is room for expansion to include others.
This client key is used to generate symmetric keys to conduct the remainder of the exchange. This client key is called a "premaster secret" and is a random key. Since the symmetric keys are created using this key, I wonder why not just send the symmetric key itself since the connection is encrypted and validated at this point.
Because it wouldn't be nearly as secure.
You also have some of these steps out of order.
I really don't see the point of enumerating all these steps informally when they are already completely specified in RFC 2246. There's enough misinformation about TLS floating around the Internet already, such as this piece of unmaintained drivel.

Can I use a self-signed SSL certificate for commercial purposes?

I'm making a server-client to use ssl for sign up and login process.
(and this is for iphone if it matters)
I just started looking at what ssl is and how to use it, and
saw there is a certificate in the process which can be bought or self-signed.
If I use self-signed certificate in web server, web browser would alert that cert is self-signed, that I understand.
But what would happen if I use self-signed certificate in regular application with tcp(not http), specifically iphone.
I just want to make the signup/login
info(their password) to be secure,
and hoping that using self-signed
certificate would be ok for this
purpose. But I also need to make
sure this won't cause "not trusted
certificate - alert" type of
interruption when used in application
other than a web browser.
Edit
I understand that "not trusted certificate alert" is saying client shouldn't trust this server.
But in my situation, client doesn't need to authenticate with the server.
The server just needs to get client's password in a secure way.
To answer your question: You can, but you shouldn't!
First, using SSL only for authentication isn't secure at all. The authentication process probably produces some kind of session (e.g. cookie) which is then transfered without encryption. Therefore, the session can be stolen (see Session hijacking).
Second, using a self-signed certificate allows man-in-the-middle attacks. So, someone can steal the user's password and he probably won't even notice it. The user doesn't know the difference between the alert that pops up when the client receives your self-signed certificat and the pop up that shows when the attackers self-signed certificate is used.
My advice: Don't use self-signed certificates. When an attack happens it's bad for you and your customers.
When you use an SSL connection to encrypt a login dialogue with a password the server sends the client a public key (in the form of a certificate), and the client generates a one-off session key, encrypts it using the server's public key, and sends it to the server. The server can then decrypt the session key because it has the private key.
The user then encrypts his password using the session key and sends that to the server, which can decrypt it because it knows the session key.
Now, without PKI if an attacker wanted to learn your password he could spoof the server. He'd send you his public key and you'd generate a session key, etc., in the usual way and send him your password which he would be able to decrypt because you'd be using his key without knowing whether you can trust it.
PKI protects you against this kind of attack by requiring that public keys are distributed as certificates. If you trust the CA that signed the certificate you can tell that the public key really does belong to the server and that it's safe to use it to encrypt your password. If you don't use a certificate -- or if you use an untrusted certificate -- you generally have no idea who you are sending your password to.
You don't give enough information about your own particular use case to say for certain whether you can use a self-signed certificate ... For example: It may be that you have one fixed certificate that is distributed in advance by some trusted channel and that you can check that the correct certificate is being used when you begin your SSL conversation. If that's the case then your client already knows that it has the correct public key and doesn't need to be able to check a signature. In general, though, you need a proper certificate signed by a trusted CA or else you have no security.
That's the entire point of trusted signing authorities - anything signed by someone else is supposed to give a security alert. So, no, there's no useful way to override this (unless you have control over the client computers - e.g. a self-signed certificate used for company-internal sites, when you can add your own CA into the clients' list), either for web browsers or anything else.
With a self-signed certificate, how can a user know whether the certificate is yours or an attacker's? He can't.
If you completely control both ends of the process (server and client), you can of course instruct the client to always trust "certificate from Eugene with a fingerprint of A01AABB546AC", for example, but then you need to build your own certificate infrastructure (expiration/revocation).
You will add no theoretical security by using a self-signed certificate, because of the possibility of man in the middle. The counterparts (your client and your server) in this communication will have no additional information about who is talking or listening, whereas the point of this kind of encryption is to make sure that there are only two participants in the communication and that the identity of at least one of them is known.
In your case, the password will not be transferred to you securely, because you don't know if it has passed through a third party on the way. Likewise, the user won't know who he sends the password to.
In practice, a man in the middle attack will be a bit of work to set up, and maybe that obstacle is some kind of security, but contrast that to the annoyance of forcing your users to accept a security warning with unclear consequences, and indeed the risk of "false sense of security".
There are companies that offer free certificates with the lowest form of validation (they will only check that you "own" the e-mail address hostmaster#domain). That way you won't have to do with the warning, either.
Unless there is a way for you to package your certificate or its fingerprint with the app, as Piskvor said.
Moved to answer - for this type of thing you should be fine. The only thing the users won't get is a way to confirm the trust level of the cert (like you could do with a signed cert in a browser for example) but as per your comment to #Piskvor that doesn't sound like an issue: you aren't using it for that.

Which parts of the client certificate to use when uniquely identifying users?

I'm designing a system where users will be able to register and afterward authenticate with client certificates in addition to username/password authentication.
The client certificates will have to be valid certificates issued by a configured list of certificate authorities and will be checked (validated) when presented.
In the registration phase, I need to store part(s) of the client certificate in a user repository (DB, LDAP, whatever) so that I can map the user who authenticates with client certificate to an internal "user".
One fairly obvious choice would be to use certificate fingerprint; But fingerprint itself is not enough, since collisions may occur (even though they're not probable), so we need to store additional information from the certificate. This SO question is also informative in this regard.
RFC 2459 defines (4.1.2.2) that certificate serial number must be unique within a given CA.
With all of this combined, I'm thinking of storing certificate serial number and certificate issuer for each registered user. Given that client certificates will be verified and valid, this should uniquely identify each client certificate. That way, even when client certificate is renewed, it would still be valid (serial number stays the same, and so does the issuer).
Did I miss something?
You have several solutions:
Storing a fingerprint.
Yes you are right, a collision is theoretically possible but the probability is really really low and you can consider it does not happen : 2 users in your system will not have accidentally the same certificate fingerprint. However hash algorithms are getting weaker over time and an attacker may try to forge a certificate whose fingerprint matches a registered one. This attack is called second preimage attack and is pretty hard to do since the attacker does not try to forge some random data matching the fingerprint but a real X.509 certificate which can pass the initial validation phase (i.e. hacking the PKI). Pretty hard :) But if you really want to prevent yourself against collision you can store 2 fingerprints with 2 distinct algorithms (e.g. SHA-1 and SHA-256).
Storing the certificate issuer and serial number. Yes it can be used as a unique certificate identifier. As you wrote, the standard (RFC 5280 obsoletes RFC 2459) indicates [The serial number] MUST be unique for each certificate issued by a given CA. However it also means that when the certificate is renewed the serial number changes since a new certificate is issued by the CA.
A final remark: you want to handle certificate renewal and it is a good idea, a lot of software editor forget that certificates have to be renewed. But you must be aware that almost everything may change in the certificate: the subjet name (people may change their name, women get married...), the issuer name (the certificate supplier company may change...), the key algorithm, the key size, the extensions... In your system the certificate renewal process will probably be pretty close to the initial user certificate registration.
The best way to uniquely identify a user is by email address. In the registration process a valid email address must be mandatory. Then you associate the certificate serial number and issuer or perhaps a hash of the the certificate itself with the email and the user id. Then, when the certificate expires or the user changes the certificate he/she will have a "renew certificate link" where he enters the email address and he receives a link to upload the new certificate. You can then replace the old serial/issuer with the new one.
I decided to concatenate the issuer name, a delimiter |, and the DN.
Hopefully, this solves the problem of using serial numbers which change on renewal.

Resources