-
Notifications
You must be signed in to change notification settings - Fork 32
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
Claims to be used in oAuth Access tokens/ OIDC Identity tokens #100
Comments
Hi @Elisabeth-Ericsson ! Thanks for this issue - I have an impression that we're missing a significant piece of flow in Camara, which is Access Token issuance. Knowing that Camara follows the OpenID Connect framework, we should rather discuss ID Tokens, as JWTs that handle claims, NOT Access Tokens, as these point towards using OAUTH2.0 inside Camara, which is not true. Therefore, Camara has to be very precise about the Authorization/Authentication framework:
I think that OpenID Connect is a better choice, due to telco characteristics (there is almost always data resource - telco services subscriber - behind API calls, that requires some kind of authentication/consent). |
Why not return the "unbundled" scope in "scope" in the access token e.g. We would standardize all the scopes for all purposes and then there is no need to add a new field. Resource servers can have a standard implementation for scope handling by continuing to handle static lists of all supported scopes and there is no need to semantic handling of scopes in the RS. I would like that Camara stays with standard RS implementations. Scopes are proprietary by definition, except the standard scopes defined in OIDC, so we can define whatever we want. But comparing a requested static string to an allowed static string is the "normal" way this is implemented. Semantic handling adds a layer of complexity that gets us into vendor lock-in which Camara should avoid. Adding new fields locks Camara into specific implementations of AZ and RS. I think we should avoid that lock-in. Also, I would like that Camara uses static scopes in the AZ implementation. Bundled scopes need special processing in the AZ and then again we have a vendor lock-in. Maybe bundled scopes were discussed and decided elsewhere in the past. Maybe there are other reasons to add "purpose" or "reason" to access token. If it is only to avoid long lists of long scopes, I would not go there. |
Hi Axel, There are various reasons to make sure that scopes and purposes are decoupled and properly listed in the claim section of the token.
Regarding your statement about bundle scopes: |
@ DT-DawidWroblewski: I agree, I have changed the title of the issue to be more generic. We have to discuss the claims included in the generated JWT token. |
Referring to CAMARA-AuthN-AuthZ-Concept.md, the section under "Access tokens, ID tokens and refresh tokens": Access Tokens can be encoded as JWT. Does this section need updating?
|
Having been involved in authorization code flow implementation for a CAMARA API, I'd like to add some comments for those that might be confused by some of the above discussion:
EDIT |
From Telefonica’s point of view, we do not need and must not standardize the claims or fields of an access_token, because the definition of an access token is an opaque value in the OAuth specs. The way the implementation of an API can check if an access token is valid, is an internal implementation detail of each solution (e.g. you can implement the access_token system using a JWT or using a random unique value string keeping the data associated to the generated access_token in your database) We only can talk about data associated internally to an access_token, but that’s still internal to the implementation. The internal details of the API and the OAuth Server implementation are out of the scope of CAMARA. You can decide to use one or the other system because both have their pros and cons. Regarding the way an application can see the scopes or purposes the access_token has granted is specified in OAuth 2.0 specs (https://datatracker.ietf.org/doc/html/rfc6749#section-5.1). The response to the token endpoint where the APP receives the access_token field can also include a scope field. This scope field is mandatory if the scope parameter requested by the APP is different to the granted scope, and you can always include the scope field in the response, even if it's the same. The scopes in CAMARA have been defined with this format: But from the technical point of view, in the OAuth Spec and its grant type endpoints, that's just a scope (a string the APP can include in the authorization request inside a list of strings separated by one space). So, if the APP asks for ExampleThe application requests a scope with the purpose and technical scope format: The response to the token endpoint would be following: {
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":3600,
"scope":"dpv:FraudPrevention#check-sim-swap check-sim-swap retrieve-sim-swap-date"
} The APP can see that
|
Hi! @nitroduna makes sense, but then we entering a "grey zone" for CIBA spec, as it is designed for OpenID Connect NOT OAUTH2.0:
so either we create a new OIDC CIBA profile, which explains/defines how to use OAUTH2.0 code flow in the context of CIBA, or we leave openid and we comply with the existing standard. Having MNO characteristics in mind (i.e. subscriber authentication, consent acquisition if relevant), OpenID makes more sense (making Mobile Connect OIDC CIBA profile a complete solution for us). |
I do not think that all terms from https://w3c.github.io/dpv/dpv/#vocab-purpose are applicable in Camara. Each Camara API has a small subset of purposes for which this API can be used. The cost for proprietary AZ and RPs is high and it makes it harder for us to switch vendors. |
@nitroduna: Hi Pedro, some input on yesterday's discussion. |
Yes, I see that document has this paragraph
So, the document is wrong and that information should be removed. We think those kind of definitions such as access_token, id_token and others, which are already included in the specs, should not be redefined in our documents. First of all, our solution is an OAuth2 / OpenID Connect solution, so they are built on top of the two main specifications:
The definition of things like The spec of the Our specs should have explicit references to the specs on which they are built, and not to replicate or redefine mechanisms and concepts already defined in the base specs. That's the same thing OpenID Connect specification is doing, which references OAuth2 because it's a spec built on top of OAuth2. We should do de same. Anyway, I'm told that document will be removed in v0.2. It seems the document doesn't represent any agreement. It's a document with inherited recommendations that was used as first steps. So, it doesn't contains any agreement and it will be removed, if my information is correct. Some technical comments (just in case you need more details of the response above)According to the following spec extracted from https://datatracker.ietf.org/doc/html/rfc6749#section-1.4 , the access_token should be a value opaque to the app and other external systems.
It's true that when you have to implement a system with APIs protected with your own OAuth server, you can mainly adopt two approaches: self-contained access_token or stored access_tokens. Both of the two solutions have very important pros and cons, but they are related to the internal code of your system and they are hidden. That considerations can affect to the security of the solution and the performance. Neither of them are better than the other, and the reasons you can find are very debatable. If you implement an OAuth system you have to implement two main components:
So the requirements for access_token are internal for the system. The developer only have to coordinate the implementation of those two components, so that the mechanism used by the first to generate tokens can be used by the second to validate them and recover all the information required to progress the call to the APIs. No other external system needs to know how to use that mechanism, and it shouldn't to avoid security issues. Deciding which mechanism to use and what data to associate with the access token is a developer decision. The two components that need to known that mechanisms are internal to the implementation. APPs using the APIs doesn't need to know that information. If a developer decides to implement a self-contained solution they can use any other kind of codification and not only JWT, that's another internal implementation decision. We can see another important defect of what was written in that document:
That introduces a potential security problem. If you generate your self-contained access_token just using JWS (singed JWT), the APP can decode the token and see all the information used by the internal implementation of the OAuth Server. That is in most of the cases very confidential information which can even contains personal information. So if you want to use self-contained tokens and you want to use JWT, at least you must use JWE (Encrypted JWT) using a highly protected encryption key that only your system can know about (a problem not found in the stored access-tokens solution). |
@Elisabeth-Ericsson CAMARA-AuthN-AuthZ-Concept.md is a document inherited from CAMARA Commonalities, and actually this document was written a long time ago to provide generic AuthN/AuthZ recommendations for CAMARA APIs. It provides a generic description of the API GW model, generic explanation and recommendations about authentication and authorization (PKCE, etc...), lists several existing grant types(*)... but actually we didn't use that document in the working group to document the different agreement reached in our discussions. We used CAMARA-API-access-and-user-consent.md, where we explicitly described the agreements reached. CAMARA-AuthN-AuthZ-Concept.md will be removed after v0.1 as you can see in #103. And for release v0.2 and later, we need to make sure that we document explicit agreements to avoid misunderstandings. The OIDC profile will help a lot with this. In fact, the use of self-contained JWT access_tokens is something we haven't discussed in the WG in the past, and as Pedro said, that should be an operator implementation decision. (*)This document actually mentions additional grant types/flows to those considered and defined so far as a valid option to access CAMARA APIs: Auth Code Flow, CIBA and Client Credentials. And that doesn't mean, for example, that we have agreed that we can use all of them... |
@ALL, but especially @nitroduna and @jpengar: The most important conclusion from this investigation is that there is impact on the L1 service implementation of each L1 service, which needs to evaluate the scope contained in the token and act accordingly. However the methods of evaluation are different depending on option a) (opaque token) or b) (jwt format). If option a) or b) are the CSPs decision, then an L1 service must be prepared for both options and allow integration to any authorization server in case of a). Details on option A- opaque token:
Details on option B - self contained token, jwt format
Option b) might have security impacts, if the token is not encrypted. Independent of the options picked both have impact on the L1 service implementation. |
Thanks @Elisabeth-Ericsson. What you say is right. Let me try to illustrate it with a picture:
{
"access_token": "SlAV3......kKG83",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "..."
} Here, the
All the logic regarding token processing is an implementation detail, done in the CSP side. The same applies if there is an aggregator between the App and the CSP. There are some interesting points in this thread that are still not closed, such as the ID Token format (my suggestion is to discuss it as part of #113 or in a dedicated issue) and the evolution of the short-term agreement (#32) regarding on how to send the purpose. |
Hi all, I also agree to separating the ID token format discussion and the purpose aspect from the access token format. |
There is no conflict between OIDC and OAuth2 regarding access tokens. Implementers discovered, that having a recommendation how a self-contained access tokens should look like
I think this applies to Camara and I believe Camara should use rfc9068. Adding a purpose field to the access token does not violate any standard. And that is true, whether the access token is self-contrained or an index into some database that then contains the purpose field. I suggest that Camara access tokens are self-contained and that can be validated without a network call back to the issuing AZ. Regarding scope values, scope values are in all standards involved a space-delimited list of case-sensitive strings. For the standards it does not matter whether each string has some structure. For the standards it is still a string that is compared character by character, and it does not matter for the AZ nor the RS whether there is a colon in the scope. |
@Elisabeth-Ericsson I understand what you mean, and I totally agree with that; APIs implementations protected by access_tokens emitted by an OAuth server need to have some mechanism to decide if that access_token has the necessary permissions to call the API. But still, we think that’s and shall be internal implementation details of each CSP. That needs coordination between the OAuth Server implementations and APIs implementations (or the component that protect that APIs implementations such as an API GATEWAY). That can be a very internal mechanism, and even more if the provider of the OAuth Server and the Provider of that APIGW is the same, or it can be some mechanism agreed between them if they’re different providers. But no one outside the CSP needs to know about those systems or architectures. There are lot of systems or architectures to resolve that requirement, regardless of whether the OAuth2 implementation is using self-contained or stored access_tokens, such as:
The important thing is that those are internal details. It's all about communication between systems owned by the CSP. Their OAuth Server and their APIs. A CSP doesn’t need to know about the system used by another CSP to allow its APIs to be called with its own generated access_tokens. In fact, you don’t even need to know the internal format used by other CSPs, you can choose the most efficient format for you APIGW implementation. For example, a CSP may decide to parse those scopes formatted as |
Thank you for all of your comments. To summarize the discussion I want to separate the 1) access token handling from the 2) access token content format discussion. |
In my opinion: For point 1) CAMARA should NOT document anything precisely because it does not standardize the implementation. CAMARA doesn't have to say that JWT approach, database approach or any other solution has to be supported. For point 2), if you are referring to the /token response, we have already explained Telefonica's position in previous comments (#100 (comment)). The purpose information is already present in the scope list returned, since it contains the scope string requested by the client, which includes the "dpv:xxxxx" format. |
My summary and understanding of the above: OAuth2 states this about access tokens https://datatracker.ietf.org/doc/html/rfc6749#section-1.4
AZ and RS MUST have an understanding about the access token because otherwise the RS is not able to validate the access token.
From I assume your (@Elisabeth-Ericsson ) concern is with implementation option 3) because then the RS does not know scope nor purpose, right? Do current implementations use option 3)? |
@AxelNennker: thank you for the detailed analysis. Case 3) is the problem.
|
Problem description
There have been several discussion rounds on the format of the scope parameter in the access token request. The agreement for the short term solution describes a proprietary format and has been included in
(1) CAMARA-API-access-and-user-consent-management.md (IdentityAndConsentManagement/documentation/CAMARA-API-access-and-user-consent.md at main · camaraproject/IdentityAndConsentManagement (github.com)).
Another document describes the generic handling of access tokens. This is
(2) CAMARA-AuthN-AuthZ-Concept.md document (https://github.com/camaraproject/IdentityAndConsentManagement/blob/main/documentation/CAMARA-AuthN-AuthZ-Concept.md ).
Here it is stated that: Access tokens should be signed and encoded as JWT (Json Web Token), with the bearer type specified.
In the very same document it is stated that the resulting token must be checked (and therefore contain claims) on:
• Expiry of the token (exp_claim)
• Issuer recognized as a trusted issuer (iss_claim)
• Consumer whitelisted in ACL list (azp_claim)
However, the format of scope claim as consequence of description in (1) for access and consent management and the handling of purpose are not documented. This needs to be agreed urgently, since the service implementations usually evaluate the content of the access token and therefore must know what to expect.
Even though the authorization request uses a custom format for the scope parameter (and includes the purpose in it), this is not allowed in the resulting access token. According to the standard RFC 8693: OAuth 2.0 Token Exchange (rfc-editor.org), 4.2, the value of the scope claim is a JSON string containing a space-separated list of scopes associated with the token, in the format described in Section 3.3 of [RFC6749].
From RFC 6749: The value of the scope parameter is expressed as a list of space-
delimited, case-sensitive strings. The strings are defined by the
authorization server. If the value contains multiple space-delimited
strings, their order does not matter, and each string adds an
additional access range to the requested scope.
Expected action
Thus the scope claim in the access token must have the exact same values as the scope strings defined in the API definition registered with the authorization server.
In case the API name as “bundle scope” is used in the scope request, this bundle scope must be extended to the individual list of scopes as contained in the API definition.
The purpose parameter should be included in the access token as well, but cannot be conveyed in the scope claim of the access token without breaking the standard RFC 8693. Thus the purpose parameter should be included in the access token in a separate claim.
Our proposal is to use “crn” claim describing the call reason. This is a public claim specified by JSON Web Token (JWT) (iana.org). It has been introduced with RFC-ietf-stir-passport-rcd-26 (draft-ietf-stir-passport-rcd-26 - PASSporT Extension for Rich Call Data).
Alternatively, a new claim, e.g. called “purpose” could be requested.
Additional context and example
An example for an access token generated on an authorize request for SIM-SwaP API would then look like:
GET /authorize?response_type=code&client_id=myApp&client_secret=0xahh23457& scope=“dpv:fraud-prevention#check-sim-swap” & redirect_url=aggregator_callback
{
"iss": https://mycsp.auth0.com/,
"sub": "+46772334567",
"aud": " https://mycsp.com/APIexposureService ",
"exp": 1490922820,
"iat": 1490886820,
“client_id”:0x3445a2,
“azp”:”coolApp”,
"scope": " check-sim-swap ",
"crn": " dpv:fraud-prevention "
}
When the request contains the API name instead of a single technical scope (as exemplified below), then the generated access token must contain the list of data scopes provided by the API.
GET /authorize?response_type=code&client_id=myApp&client_secret=0xahh23457& scope=“dpv:fraud-prevention#sim-swap” & redirect_url=aggregator_callback
{
"iss": https://mycsp.auth0.com/,
"sub": "+46772334567",
"aud": " https://mycsp.com/APIexposureService ",
"exp": 1490922820,
"iat": 1490886820,
“client_id”:0x3445a2,
“azp”:”coolApp”,
"scope": "check-sim-swap retrieve-sim-swap-date",
"crn": " dpv:fraud-prevention "
}
Additional context
The text was updated successfully, but these errors were encountered: