-
Notifications
You must be signed in to change notification settings - Fork 9.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[OpenAPI.Next Proposal] Add client certificate to authentication methods #1004
Comments
There are a number of client/service interactions where this would be a good choice. In particular this fits when the security requirements can be met by mutual authentication of client and server. |
I vote for this, we have some real world use cases where we would like to use something like this. Also, this feature has already been proposed but than somehow got ignored: #451 (comment) One thing though that from my point of view requires consideration:
I personally take the realist's view. Still, it will be somewhat hard to cramp a TLS based client certificate authentication into the existing Security Scheme Object - this one is heavily based on HTTP. Smartest solution I see for now is adding another type and making all the other fields optional for it. A typical client certificate security definition would therefore then look like this: {
"type": "tls",
"description": "Cert must be signed by evilcorp.com CA"
} type: tls
description: Cert must be signed by evilcorp.com CA |
Concur. I have a number of customers who require TLS with client certificates. If we don't add it to OpenAPI I'll have to write an extension. Better to have it as part of the spec. |
Within the Dutch public sector we have identified this requirement as well. |
We also plan to implement a REST API service for EU Customs & Taxations IAM system between European Commision and member states. In that case, it is far more easier for us to use two-way SSL as it is already the case for the SOAP WS already exposed. But for the moment my major problem is the lack of implementation at server-side. I had to switch back to Swager 2.0 api because of that. I hope that a 3.0 implementation will come soon, but I have doubt that the 3.1 will met my dead lines. Do we have an idea when 3.1 specifications will be frozen? |
@tobilarscheid I support your realist view. The Dutch municipalities are aiming to convert/replace their current monolithic information systems with an API-first software landscape, fulfilling societal demand for automation, transparency and privacy. To facilitate this we are setting up an open source inter-organisational system facilitating federated authentication, secure connecting and protocolling in a large-scale, dynamic API landscape. In this landscape we want to use two-way TLS. |
On the subject of TLS client certificate authentication, as a straw man, would the following be sufficient to indicate that the client MUST provide a TLS certificate? components:
securitySchemes:
clientCert:
type: clientTLS
serverSelfSigned: true The default value of Client-side tools would be free to identify or prompt for the relevant certificate using any means they wish. |
Hi @MikeRalphson, thanks for your input. The solution looks like a good first step to me. However I do not quiet understand the emphasis on |
Hello,
I agree. Moreover, self-signed certificates are not used in production
environements.
If you want to put more information useful for the client side, you could
optionally list the CA certificates or URL of CA or eIDAS / alternate LOTL
(for European Union) that are trusted for an 2 WAY SSL authentification
with this service. But it should only be informative.
Pascal
…On 15 May 2018 at 09:55, tobilarscheid ***@***.***> wrote:
Hi @MikeRalphson <https://github.com/MikeRalphson>, thanks for your
input. The solution looks like a good first step to me. However I do not
quiet understand the emphasis on serverSelfSigned - why would that be
something so important to include it here right away?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#1004 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AiSLQN7RoFEVJbRJioNpVCP_r5vMt_-_ks5tyonbgaJpZM4MmFhZ>
.
|
@tobilarscheid @bourgpa re: self-signed certificates, this is completely up for debate, and is potentially an unwanted feature / in the wrong place, but I wanted to bring up the subject.
This, unfortunately. is not the case in my experience. When an organisation manages their own CA, they sometimes issue self-signed certificates both for servers and clients. They may also have a place in microservice environments. Personally, my feeling is that we should not list CAs, root certificates, CNs, or tread on the toes of TLS's negotiation of ciphers etc by including this information, but we are open to all use-cases and perspectives regarding this feature. |
It really does not matter for security who signed the certificate as long as you trust the signee - on the other hand accepting a certificate that is signed by someone you don't trust / know is typically a bad idea. Because of this I deem the flag unnecessary / even misleading.
You are right that this is part of the TLS handshake already. Might still be nice to include just for informational purpose, but that could be something that can live in a comment field or the like as well IMHO. |
It may matter to the client's authentication libraries, which often must be passed a flag to disable the checking for self-signed certificates.
Indeed, specification extensions / the new draft features approach may be a way to make this extensible. |
that's what I say you should never do and specifically should not be promoted by this standard here. |
I understand your concern, but allowing the description of a particular API implementation is not necessarily promoting it. cf. |
We may be making this harder than it has to be. |
@cmheazel If docs tools are going to implement "try it" functionality against servers that are in a dev environment where certs are self-signed, they are going to need to know to turn off any cert validation. |
As above, this is the option we're discussing. |
Sorry, I miss-read the example. This relates to issue #1552 |
@darrelmiller But is that in-scope for OAS? In my experience, client side certificates are configured once and never modified. Any changes required for a dev environment are passed out of band. |
@bourgpa I have similar requirements too (always for public administrations). @MikeRalphson what do you think of using the more general x509 reference?
|
@ioggstream fair question. All TLS communication uses x509 certificates, but we probably want to make it clear that for this |
Perhaps we should introduce security scheme types for both TLS and TLS_Mutual_Authentication. This makes it clear that the client certificate is being used within the context of the TLS protocol. |
How does this square with your earlier comment
? TLS usage is a function of the
Not directly in this issue, I feel. That is a much bigger change and focuses on one particular approach to crypto. I expect @isamauny and other interested parties to comment here if this particular proposal conflicts with the crypto extension proposal. |
@MikeRalphson I made my point. Since the consensus seems to be that TLS-level security is in scope for OAS, we move on. |
To me, just introducing
|
My understanding is that the first two are always negotiated from a common set of values between the client and the server. I understand the possible need to constrain those sets to comply with certain crypto standards but I think this is at least an issue to be addressed once we have consensus on adding the new The third is (I still believe) a slightly different case. The use of self-signed certificates is not negotiated between client and server, and in order to make any kind of connection, a hint is required to the client side by the OAS document, not the server that it should enable this mode. In my experience it is difficult to obtain useful connection error messages from aborted TLS connections and always diagnose the cause. Providing this hint is a security feature, in that the client knows not to try and attempt a second connection with 'defences lowered' if this hint is not present. One argument is that this hint should be at the I'm leaning towards |
@MikeRalphson As for the self-signed certificates. Last, but definitely not least, whether a certificate is self-signed or signed by a Certitificate Authority (which could be self-signed, non-WebPKI or anything really) is not important, what is important is whether the certificate is trusted (directly or indirectly via trust chain) or untrusted. And that is not a binary option, it is a property of the client, so there is nothing really you can say unambiguoasly from the server about that. |
The following property would be sufficient to indicate a client certificate is required. This does not allow the certificate selection to be automated.
Meta data necessary to allow automated selection of certificate:
Can we do this as a draft feature? |
@MikeRalphson
This information should IMHO be at the server level as it's not Authentication related. |
@pleothaud |
@darrelmiller what does "selfsigned: bool" indicate ? |
fully agree on that one. Authentication generally and client certificate authentication over tls make sense to document in the API spec, as it typically has a "business" meaning for using the API. TLS Versions and protocol details should really be left to be documented by their appropriate means (= tls handshake) as there are purely infrastructural. |
My point here is that a client should be able to know if it can/want to consume an API based on this API's contract, which is the OAS file. So, as TLS protocol version and suites have an impact on this decision it makes IMHO sense to provide this information in the OAS file. WDYT? |
No I do not think the TLS version has any bearning on whther the app wants to use an API. |
@tobilarscheid It means that the certificate being presented by the client is one of these https://en.wikipedia.org/wiki/Self-signed_certificate. The property MUST only have the value true in development scenarios. |
@darrelmiller what if the client send a certificate signed by a CA that is not trusted by the server ? |
As others pointed out this is at best misleading. A self signed certificate can be absolutely fine in various scenarios, including production ones. Being self signed says nothing about the trust the server gives to this certificate. IMHO by adding this strange property to the spec we would only contribute to more people misunderstanding the whole certificate / trust / CA / signing complexity! |
@tobilarscheid As I understand it, a self-signed certificate is the most common way that developers create certificates for testing purposes. Unless a server explicitly has this certificate in it's trusted root store then I'm assuming the self-signed certificate would be considered untrusted. Do you think it would be better to name the property "untrusted" and include the explanation that this would allow a certificate to be used that includes some certificate in it's chain of trust that is untrusted by the server? |
untrusted would definitely be a much better definition, I am still unsure you need/want it, but at least it would be more accurate |
so when our team is testing / developing with certificate based authentication we always use a dummy CA who's key is shared among all developers. But I get that this is just anecdotal evidence as well. |
All, why don't we take a step back and look what we are trying to achieve: documenting the API contract. And transport is part of the contract even if, as you all mention, the TLS negotiation happens at a different level. Let's take this security profile as an example, as it's the kind of information we are trying to capture by extending the specification: http://openid.net/specs/openid-financial-api-part-2.html#tls-considerations. At the TLS level, there are two things we need to be able to express: So yes, this is all happening magically behind the scenes... But how will the API consumer know about those constraints ? The issue with protocol-level negotiation is that if it fails ( because you present the wrong cert, self-signed or not, because you don't support the cipher suites the server requires, etc.) all you get is a protocol level error, which we all know are hard to debug. Put yourself in the position where you consume APIs you have no control over, how will you know a cert is required, that the protocol is TLS 1.2 (what happens when this becomes 1.3 and some old clients don't support it), etc. I guess you can say: run openssl -connect xxx and you will know. You guys know that because you are security specialists, but most people don't master this stuff at all, and that's why it's complicated for many people to understand what the problem can be. If you have helped debug as many TLS connections issues as we have, I am sure you will agree. If you write, plain and clear:
Then Yes, you repeat what the protocol will negotiate , but at least it's clear to the consumer. The inherent complexity of the TLS protocol is such that to precise what the server expects you have to add multiple meta-data. That does not happen with Basic. Or you just say: I need a cert, you figure out how to talk to me. And if it fails, you figure out how it fails by opening a ticket with the provider, play with openssl, or whatever means at your disposal to understand the source of the issue at the TLS level. We opted for the first approach, because: We are not trying to replace the TLS transport negotiation here, we are just trying to express as clearly as possible the transport constraints for the API consumer benefit. |
@isamauny @tobilarscheid I stand on those points:
@darrelmiller I suggest just to reference the certificate fields to be examinated not their values. Eg the authentication layer validates:
But the OpenAPI doesn't list all possible IP values (which could be thousands). The same for issuers: you might advertise that you're validating the issuer, but not listing the valid issuers as that may vary. |
Sorry for the long reply.
TL;DR: we only need to tell the client needs a cert, and nothing else
Isabelle wrote:
All, why don't we take a step back and look what we are trying to
achieve: documenting the API contract. And transport is part of the
contract even if, as you all mention, the TLS negotiation happens at
a different level. Let's take this security profile as an example, as
it's the kind of information we are trying to capture by extending
the specification: http://openid.net/specs/openid-financial-api-part-
2.html#tls-considerations.
This is a normative spec not data exposed at runtime, not the same
thing.
At the TLS level, there are two things we need to be able to
express:
a) I require TLS protocol level x.y and those are the cipher suites I
will accept.
Is this something that will be setup at the provider level and
negotiated at part of TLS protocol ? Yes, absolutely.
It can be influenced by proxies and other middle boxes, not something
the OAI provider have necessarily direct knowledge.
b) I require a client cert for mutual TLS (some of the exchanges in
that security profile above require that).
Again, is that something that's part of the protocol , yes.
And the server will advertise the CA it accepts and the client can
pick a cert from a list in a browser when asked to present one.
The server may not want to advertise (or know) all the CAs it trusts.
May even be different CA sets depending on which frontend the client
ends up hitting (on premise client vs off-premise, proxied vs direct,
etc..)
So yes, this is all happening magically behind the scenes... But how
will the API consumer *know* about those constraints ?
The only thing the API consumer really needs to know is if it
can/should use a certificate to access an API, the rest is better
handled at connection time by proper error reporting.
The issue with protocol-level negotiation is that if it fails (
because you present the wrong cert, self-signed or not, because you
don't support the cipher suites the server requires, etc.) all you
get is a protocol level error, which we all know are hard to debug.
It may be hard with bad clients, but TLS gives you specific errors,
from the RFC of TLS v1.0:
bad_certificate
A certificate was corrupt, contained signatures that did not
verify correctly, etc.
unsupported_certificate
A certificate was of an unsupported type.
certificate_revoked
A certificate was revoked by its signer.
certificate_expired
A certificate has expired or is not currently valid.
certificate_unknown
Some other (unspecified) issue arose in processing the
certificate, rendering it unacceptable.
unknown_ca
A valid certificate chain or partial chain was received, but the
certificate was not accepted because the CA certificate could
not be located or couldn`t be matched with a known, trusted
CA. This message is always fatal.
Put yourself in the position where you consume APIs you have no
control over, how will you know a cert is required,
This is the only information we need to publish, that the API requires
a client cert.
that the protocol is TLS 1.2 (what happens when this becomes 1.3 and
some old clients don't support it), etc.
This is discoverable, you connect to the server and it will tell you if
the TLS versions your client supports are acceptable, if they aren't
there is nothing the client can do anyway.
I guess you can say: run openssl -connect xxx and you will know.
No, you just connect to the server and handle an error of:
handshake_failure
Reception of a handshake_failure alert message indicates that
the sender was unable to negotiate an acceptable set of security
parameters given the options available. This is a fatal error.
And properly translate it to the user
You guys know that because you are security specialists, but most
people don't master this stuff at all, and that's why it's
complicated for many people to understand what the problem can be.
And we do not need to make the problem worse by publishing redundant
information that quickly gets out of sync with reality, and worse, may
be actually believed as truth by the client.
If you have helped debug as many TLS connections issues as we have,
I am sure you will agree.
I agree software needs to properly handle errors, adding a second layer
of negotiation for the same parameters is just going to make problems
worse, not easier.
If you write, plain and clear:
- I need a client cert
This is what this issue is about, exposing an indicator that a client
cert is needed.
- It can/can't be self-signed (as you say, it's all about trust and
if you choose to trust self-signed in production, then fine)
This is not a binary option, so whatever is said by the server will be
meaningless. Self-signed is inherently *not* trusted, "trust self-
signed" really just means "accept untrusted" unless you use a scheme
like TOFU, but no TLS client or server implementation does that today,
and again requires no indication if that were the case.
- It has to be signed by these CAs (because I won't trust any other)
This *could* be published, but often people do not want to disclose
this information to anonymous clients, it also, again requires a way to
make sure the exposed data is true, and if you have middleboxes doing
the auth part for you, then you may not know what certs are accepted by
the middle box.
- And the value of subject name must be XXX (because I will verify
it)
This is not necessarily a valid criteria, people may accept any cert
from Issuer X, or expect other extended attributes to match or a
million different criteria.
Then Yes, you repeat what the protocol will negotiate , but at least
it's clear to the consumer.
It will be as clear as it is today, only with double the failure
points, where reality does not match the lies published.
The inherent complexity of the TLS protocol is such that to precise
what the server expects you have to add multiple meta-data. That does
not happen with Basic.
No web server published TLS protocol details on port 80, end browsers
have mostly no issues using HTTPS every day.
Or you just say: I need a cert, you figure out how to talk to me.
This is the only sane way unless you can guarantee your application
stack is fully integrated 100% all the way down to the TLS crypto
library used on the frontend terminating server (think cloudflare,
akamai, etc..), something less and less true in this day and age. Often
between the client and the application there are multiple hops an re-
encryption.
And if it fails, you figure out how it fails by opening a ticket
with the provider, play with openssl, or whatever means at your
disposal to understand the source of the issue at the TLS level.
If you do not have a valid cert, you need to get a valid cert from
whomever owns the authentication infrastructure anyway. If your client
does not support a TLS version new enough to connect likewise your only
recourse is to change client. The fact OAI publishes some duplicated
meta-data is not going to help with those issues anyway.
We opted for the first approach, because:
a) it's clearer as it describes the server setup.
Aside for requiring a client cert (which is what we want to express
here) everything else is exposed by the [frontend] server already via
the TLS protocol, and can be easily probed if that is what you really
want (I think you don't, except for QA or similar scenarios where yes
they can use things like openssl -connect if they have specific
requirements for testing).
b) it allows the client/test tooling to automatically validate that
the cert it has is actually valid according to the specs (with no
need to connect and fail)
And then you still have to handle the fallout when the validation was
faulty and the certificate is not accepted by the server anyway. You've
just done the work twice needlessly, connects are cheap.
c) it allows to generate a clear description of the transport
contract as part of the API documentation.
If that was needed you'd have this in since the start, as most servers
run on HTTPS, yet no API spec I know of goes out and publishes the TLS
parameters just because the API will be exposed over HTTPS instead of
port 80, I don't buy this argument.
We are not trying to replace the TLS transport negotiation here, we
are just trying to express as clearly as possible the transport
constraints for the API consumer benefit.
you seem to advocate for client to get protocol version and certificate
authority information and fundamentally pre-negotiate assuming that
info is valid when all that is needed is for the client to just handle
errors and translate them to users in a comprehensible way.
The same error messages you could give to users based on version field
in the API can be given if the negotiation fails which boils down to:
your client can't connect to this server. Telling a user "because the
version is x.y.z instead of x.y.f" won't really make a useful
difference it's not like they can tweak a knob in the client
configuration to get a new (or old) TLS version magically supported.
Simo.
|
Thanks Simo. We obviously come to this from different angles, and I totally understand and respect your position, even if I still think we could do a better job at documenting TLS requirements. Not pre-negotiate, not replace trust mechanisms, just document. And yes, there are potential issues for contract being disconnected from reality, but if we say that the transport requirements are actually part of the API contract, then changing the server setup does indeed change the contract and therefore the API definition will have to be kept up to date with those changes. So it all comes down to deciding that the transport setup is of the contract, you say No and you have your reasons, I say Yes and I have mine. Peace :) |
Although I understand your angle Isabelle, what I am saying is that the API cannot faithfully report on the (TLS) transport layer, so it shouldn't; doing so would cause the API to lie most of the time and that is not good for anyone. |
Hi everybody! @MikeRalphson @darrelmiller any news on the subject? My proposal on which there was some consensus was: For
|
@MikeRalphson @darrelmiller as we merged #1764, we could:
feedback wellcome! |
As long as we link back to this issue and summarise people's suggestions (not easy!) I'd be happy to close this issue. |
Use of client certificate for authn is very popular and support is ubiquitous.
The text was updated successfully, but these errors were encountered: