Proposal to Mandate Use of Signed Authentication Requests for CIBA
Closed this issue ยท 20 comments
Problem description
OIDC CIBA (and hence the current CAMARA interoperability profile) allows for two types of authentication request - unsigned and signed.
If requests are unsigned, an attacker with access to the unencrypted request can modify the request parameters without detection.
Signed authentication requests prevent the request parameters being modified by an attacker who has access to the unencrypted request. Signed requests are created by encoding all of the authentication request parameters as claims of a signed JWT with each parameter name as the claim name and its value as a JSON string. The JWT is secured with an asymmetric signature as described in the OIDC core specification. The signed JWT is added to the /bc-authorize
request as an additional form parameter request
.
Possible evolution
To verify the signature, the API provider must validate the signature using the client's public key. As the client themselves must be authenticated using private_ket_jwt, this key will already be known to the API provider. The additional implementation complexity of signed over unsigned authentication requests is therefore minimal.
It is therefore proposed that, for the CAMARA interoperability profile, CIBA authentication requests must be signed by the API consumer.
The advantages of this are:
- It is more secure than unsigned requests
- It removes one more option from all the options that API providers still need to support
Alternative solution
Additional context
If requests are unsigned, an attacker with access to the unencrypted request can modify the request parameters without detection.
If requests are unsigned, an attacker with access to the unsigned request can modify the request parameters without detection.
Note: Speaking currently as me not as DT.
My 2 cents.
ICM requires the use of TLS 1.2 or better for all network connections. TLS already provides encryption and integrity protection for data transmitted over the network, ensuring that communication between client and server is secure from eavesdropping and tampering.
ICM also requires the use of private_key_jwt for client authentication. Using private_key_jwt, the server can already validate that the request was indeed made by a particular client.
So, in terms of security, I don't see much benefit in using signed request when using TLS and private_key_jwt. CAMARA should consider the cost-benefit of mandating signed request. One of the biggest challenges raised for CIBA and the 3-legged flows was the complexity. Now, even considering that the implementation cost in the server side is minimal, there is indeed a cost in the overall flow in the client side to generate the signed request and in the server side to also validate the request signature. There should be a clear benefit to requiring a signed request.
Also, CAMARA would have to define the server behavior when a client sends an unsigned request. Most likely this would be an error that should be defined. And CAMARA would have to deal with the backward compatibility, since existing clients using unsigned requests would have to make the corresponding adaptations.
If requests are unsigned, an attacker with access to the unencrypted request can modify the request parameters without detection.
If requests are unsigned, an attacker with access to the unsigned request can modify the request parameters without detection.
Not a typo. By "unencrypted", I meant "outside of the TLS tunnel". Inside the TLS tunnel, I think it safe to assume that neither a signed nor unsigned authorisation request can be tampered with. But in some scenarios, TLS will not be "end to end", and for some implementations, TLS termination will not be done by the authorisation server itself. So there will exist network locations where access to the unencrypted request is possible.
Given TLS is mandated for the /bc-authorize
endpoint, I assume this was why signed authentication are defined as an option in the standard.
ICM requires the use of TLS 1.2 or better for all network connections.
Not only ICM. The CIBA standard itself mandates that TLS is used for the /bc-authorize
endpoint.
Communication with the Backchannel Authentication Endpoint MUST utilize TLS
And yet it was still felt necessary to define signed authentication requests as an option, perhaps because there may nonetheless exist network locations between the client and authorisation server itself where access to the unencrypted request is possible.
there is indeed a cost in the overall flow in the client side to generate the signed request and in the server side to also validate the request signature. There should be a clear benefit to requiring a signed request.
But signed authentication requests are already an option that needs to be supported by the server, inherited from CIBA. Is your position that we should keep both options, or is it that we should mandate unsigned authentication requests to reduce this cost?
And CAMARA would have to deal with the backward compatibility
The requirement to maintain backwards compatibility does not apply here any more than it applies to all the other breaking changes that are being made by CAMARA.
But signed authentication requests are already an option that needs to be supported by the server, inherited from CIBA. Is your position that we should keep both options, or is it that we should mandate unsigned authentication requests to reduce this cost?
@eric-murray I have a different understanding. IMHO, since the CAMARA OIDC profile does not define anything on top of the CIBA standard on this matter. I think the server will at least support unsigned request and those who have the specific security requirement will implement signed and may require it from the client...
And I'm just gathering as much information as possible to make a WG decision.
What about signed request in authorization code flow? This issue is just being addressed in CIBA.
Why would we mandate this and not just say 'SHOULD'? At the end of the day carriers are going to ignore mandates they don't agree with.
My understanding is that it is not mandated that the OIDC server supports signing... in the CIBA specification backchannel_authentication_request_signing_alg_values_supported
metadata parameter is documented as:
If omitted, signed authentication requests are not supported by the OP
Why would we mandate this and not just say 'SHOULD'? At the end of the day carriers are going to ignore mandates they don't agree with.
Well, the problem with "nudge theory" is that it is not very effective. If we only tell the client that they SHOULD use signed authentication requests, that tells them that they MAY still use unsigned requests. So the authorisation server will still need to implement support for both unsigned and signed requests., which increases implementation and support complexity. The purpose of this proposal is primarily to reduce overall implementation complexity, whilst maintaining overall security by proposing the more secure of the two options.
Now if a particular API provider decides that they will anyway not support unsigned requests (say, for security reasons, or because a high %age of clients actually pay attention to the "SHOULD"), the problem now is that a prospective client will not know of that restriction from the CAMARA Security and Interoperability Profile, which is meant to define a set of options that any prospective client KNOWS will be supported.
Only when the client gets access to the API Providers openid-configuration
file will they learn that their unsigned requests will not work. Such situations will discredit CAMARA if API Providers will not (or cannot) support the CAMARA Security and Interoperability Profile.
And compliance with the Profile benefits aggregators, who might otherwise implement both signed and unsigned authentication request support, only to find that some CSPs support only one or the other.
Standardising on a single option benefits everyone, even prospective clients who need to overcome the pain of learning how to sign a JWT.
I have a different understanding. IMHO, since the CAMARA OIDC profile does not define anything on top of the CIBA standard on this matter. I think the server will at least support unsigned request and those who have the specific security requirement will implement signed and may require it from the client...
This, at least, must be clarified. My understanding of the CAMARA Security and Interoperability Profile is that any options of the underlying OIDC standards that are not excluded MUST be supported by the API Provider. If this is not the case, then how does a prospective client know whether the options they want to use (say, a signed or unsigned authentication request) will be supported?
More generally, this may come to the question I raised before as to whether an API Provider can omit to implemented some options as long as they implement the one that is "RECOMMENDED" by the Security and Interoperability Profile, or the client is told that they SHOULD use, The objection raised then was just this - if the Profile says it remains and option, then some clients will expect to be able to use that option, and so it must be supported. Which means that terms such as "RECOMMENDED" and "SHOULD" are meaningless for the API Provider.
If we can come to some agreement on how API Providers can handle "RECOMMENDED" options that allows them not to implement those not recommended, then I'm happy for signed authentication requests to just be RECOMMENDED.
What about signed request in authorization code flow? This issue is just being addressed in CIBA.
The authorisation code flow has many more options for passing request parameters. I'd prefer to resolve this for CIBA first (where there are only two options), before considering restricting the options for the authorisation code flow.
CIBA authorization servers can indicate which signing algorithm they support in their meta data.
backchannel_authentication_request_signing_alg_values_supported: OPTIONAL. JSON array containing a list of the JWS signing algorithms (alg values) supported by the OP for signed authentication requests, which are described in Section 7.1.1. If omitted, signed authentication requests are not supported by the OP.
It is standard security best practice to reject requests with signed data if the signature cannot be validated.
The value of signed requests is that the OP can prove what it received. As @eric-murray said, in many architectures there are many teams and sometimes different organizations and legal entities involved. TLS termination is usually at a server/load-balancer/API-gateway other than the "real" application server/OP. Signed requests ensure integrity regardless how many entities are involved. Also, the OP is double-sure that the client really sent the CIBA request because the OP has authentication by client credentials and the valid signature.
Another aspect is that in general key should be used for one purpose.
If a key is used in private_key_jwt then, in general, it is better to use a different key for signing.
Which complicates the whole matter.
The security person in me recommends using signed request, the operations person in me fears that this introduces a complexity that can lead to service disruption. key rotation is a beast.
Another aspect is that in general key should be used for one purpose.
If a key is used in private_key_jwt then, in general, it is better to use a different key for signing.
Which complicates the whole matter.
Whilst I agree this is better (i.e. more secure) in that two keys need to be leaked before the client is hopelessly compromised, I think this decision can be left to the client themselves. If they wany to use a single key for both client authentication and authentication request signing, they should be allowed to do that. And if they want to use separate keys, they should be allowed to do that as well.
This way, clients who dislike key rotation can concentrate on the single key they anyway require for private_key_jwt
. Removing the option of signing requests would not remove the need for key rotation.
Ericsson's view is that CAMARA should not mandate signed authentication requests. This is an optional feature in the standard for CIBA, for sure more secure to use it, but OPTIONAL.
It is not an issue for aggregators acting as clients to send signed requests. We think that it is rather an issue for Telco operators to provide / support the signing procedure. This will raise the barrier for fast adoption.
This is an optional feature in the standard for CIBA, for sure more secure to use it, but OPTIONAL.
And yet private_key_jwt
itself was another OPTIONAL feature of OIDC that CAMARA has now made mandatory without any objection.
The fact that an option exists in OIDC is no argument in itself for keeping it in CAMARA. Otherwise, we would not need to define a profile to reduce the number of options, and could just say "anything defined by OIDC must be supported by all API providers".
It is the large number of remaining OIDC options that will be the barrier to fast adoption, because no API provider will support all the remaining options. Anything that remains an OPTION for the client becomes MANDATORY for the API provider to support. But few, if any, API providers will do that, and what we will find here is that some API providers support signed requests only, some support unsigned requests only, and a few might support both.
And a developer will not know who supports which option until the are onboarded, and only then will they find out if their own implementations are actually compatible with the API provider's implementation.
Of course, there is a role for aggregators to support all options and then interwork with the individual API provider implementations. But we should try to avoid the situation where the ecosystem requires aggregators to perform this role because of the complexity for API providers to implement all options.
As mentioned above, I am happy to make signed authentication requests RECOMMENDED, and for API providers to be allowed only to implement the recommended option where one is defined. Recommended options should always be supported.
As explained in #194 (comment), I don't see much benefit in using signed request when using TLS and private_key_jwt. Considering the cost/benefit of mandating signed request, if CAMARA wants to remove one more option from all the options API providers still need to support (as the issue initial description suggests), then IMHO I would mandate unsigned reques, aiming for the simplest solution.
I don't see much benefit in using signed request when using TLS and private_key_jwt
I think there are two benefits to consider:
- For security purposes, where the TLS termination point is before the authorisation server. Signing the authentication request eliminates the possibility that the request parameters are tampered with inside the implementing organisation itself.
- For audit purposes. If the API caller has signed the request, they cannot later claim that they did not request a particular scope or purpose for a particular end user.
Whether or not this represents "much" benefit will depend upon the specific implementation. Vodafone believe the cost/benefit supports mandating signed requests, because an API client must anyway know how to sign JWTs if we are mandating private_key_jwt
. I don't really understand the argument that it will be straightforward for them to sign the client_assertion
but really difficult to sign the request
.
I'd be interested in other views on the cost/benefit analysis. In particular, whether the above benefits are also valuable to other organisations. If it can be shown that there is no benefit to signed authentication requests if private_key_jwt
was being used, then I'd support removing signed requests as an option, though it would make me wonder why OIDC specified that option in the first place.
I can see that no agreement on one or other authentication request mechanism can be reached, and so I opened a PR which recommends the use of signed requests for CIBA, but still allows the use of unsigned requests.
It is clear that the authorization server MUST validate the signature as per https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.7.2
It is also clear that the AZ returns HTTP 400 Bad Request with the error set to invalid_request
is the signature is not valid.
https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.13
No need to mention that because this is CIBA standard.
What we might want to do is adding this invalid_request
to #220 , right?
No need to mention that because this is CIBA standard.
I don't mention it. This is the proposed additional text in PR #217:
It is RECOMMENDED that signed authentication requests be used, as specified by OIDC CIBA Core. The same key MAY be used for signing the authentication request as is used for client authentication.
What we might want to do is adding this invalid_request to #220 , right?
The 400 invalid_request
error response is already included in #220.
No need to mention that because this is CIBA standard.
I don't mention it. This is the proposed additional text in PR #217:
It is RECOMMENDED that signed authentication requests be used, as specified by OIDC CIBA Core. The same key MAY be used for signing the authentication request as is used for client authentication.
What we might want to do is adding this invalid_request to #220 , right?
The 400
invalid_request
error response is already included in #220.
I totally agree. I wrote "No need to mention that" because this is standard, and not because I thought you mentioned it.
Sorry, for the misunderstanding.