CIBA and Lodging Intent

Issue #228 closed
Dave Tonge created an issue

We discussed on the call today that we should include a reference to the lodging intent document in the FAPI CIBA profile.

Furthermore we should discourage implementers from passing “intent ids” in the login_hint_token.

We should also make sure that FAPI CIBA supports the solutions outlined in the lodging intent document, e.g. dynamic scope and a separate param.

Comments (31)

  1. Dave Tonge reporter

    @Joseph Heenan I had a discussion with Ralph about this. Potentially OB may be able to use "dynamic scopes" i.e. a scope of intent_id:123

    I really think we need to get a clause in that suggests this as one of the possible options and discourages the overloading of the login_hint or login_hint_token with intent ids. I’ll have a go at drafting one a bit later.

  2. Joseph Heenan

    An extra informal call has been scheduled at the usual FAPI WG time on Friday (tomorrow, 21st June) to discuss how to deal with this.

    OB seem to be mostly open to all options, albeit some OB members were slightly reluctant to reopen the issue with the banks.

  3. Takahiko Kawasaki

    I'm sorry I've not followed every discussion but...

    It is natural for developers to think scope values are static because no rule has been agreed regarding the way to represent dynamic scope values in (1) scope_supported server metadata (RFC 8414 and OIDC Dynamic Client Registration), (2) scope response parameter from the token endpoint, (3) scope property in responses from the introspection endpoint (RFC 7662), and so on.

    In addition, some specifications state that unrecognized scopes should be ignored, and this requirement easily makes server-side developers believe that scopes are static. It's because there is no way to ignore scopes if scopes are generated dynamically.

    Introducing new rules into the existing scope parameter will result in requiring existing specifications that use the scope parameter to be updated. It is not only specifications but also libraries, applications, backend systems, and frontend UI of existing implementations that will be affected.

    Why don't we define a new parameter like dynamic_scope or something similar, or define a new parameter that represents dynamic values for scopes, instead of introducing new rules into scope that may break the existing ecosystem and become an entry barrier that can block many implementations?

    For example,

    dynamic_scope={
      "intent_id": 123
    }
    

    Well, it seems to me that it does not necessarily have to be "scope". What is needed is a way to pass dynamic key-value pairs to the server. So the name of the parameter doesn't have to include scope. For example, key_values, dynamic_data, data, etc. would work like this.

    data={
      "intent_id": 123,
      "favorites": {
        "sports": [ "soccor", "baseball" ],
        "fruits": [ "apple", "banana" ]
      }
    }
    

    It would become similar to the existing parameter claims (OIDC Core 1.0, 5.5), but claims is dedicated to a specific narrow purpose. So, it would be better to avoid using claims as a generic way to convey arbitrary key-value pairs to the server.

  4. Torsten Lodderstedt

    I’m fully supporting your proposal to introduce a dynamic scope parameter. I called it !structured scope! in my recent blog post https://medium.com/oauth-2/transaction-authorization-or-why-we-need-to-re-think-oauth-scopes-2326e2038948. I would even go a step further and include the intent data within this structure making it nicely self-contained.

    But I think this is not mutual exclusive to dynamic scopes using the existing scope parameter.

    We have been using dynamic scopes like “ais:1234355“ for quite a while now and never encountered problems with libraries (only with AS/OP implementations but they are catching up). We only use the static part of the scope in the before mentioned metadata structures since the dynamic part is irrelevant for announcing support for a certain type of scope value.

  5. Takahiko Kawasaki

    Hi, Torsten. Thank you. I know your blog as I told previously that I had been impressed very much. One concern is that if we introduced a rule into "scope", we would have to reach a consensus on the format, too. "{scope_name}:{value}" is not the only option. What if the value is an array? What if the value is an object? Squeezing various data into a string is likely to face some problems which are currently unforeseeable, my intuition as a programmer tells me.

  6. Torsten Lodderstedt

    Hi Taka,

    I understand an agree. I think the utility of the dynamic scope in the traditional scope parameter is limited and I would only define a simple syntax to convey the reference to a lodging intent resource. Anything going beyond that should go into a well-defined, structure (JSON) scope parameter value.

  7. Joseph Heenan

    In an attempt to drive this to a conclusion, I have tried to enumerate the options I believe we have:

    1. Do nothing; ecosystems may well decide to use login_hint_token to pass extra context, which is undesirable as it is defined as 'A token containing information identifying the end-user for whom authentication is being requested', and using login_hint_token precludes using login_hint or id_token_hint for their intended purposes.
    2. Endorse use of login_hint_token for this purpose & redefine it (undesirable for similar reasons to '1')
    3. Emphasise that new (not defined by FAPI-CIBA) parameters should be used to pass intent
    4. Dynamic scopes with a lodged intent id, e.g. scope=openid payments:5514cacc-93da-11e9-bc42-526af7764f64
    5. Dynamic scopes without lodging, e.g. scope=openid payments:{"amount": "100.00", "to-account": "22-21-11 23467755"} (or variants thereof that add base64 encoding etc)
    6. Structure scopes, https://medium.com/oauth-2/transaction-authorization-or-why-we-need-to-re-think-oauth-scopes-2326e2038948, e.g. a new claim in the signed request called structured_scope containing {"payment":{ "amount":"123.50", "to-account": "22-21-11 23467755"}}, or {"payment":{"intent_id":"5514cacc-93da-11e9-bc42-526af7764f64"}}, and removing the current scope parameter or passing purely scope=openid.
    7. Define a new a new claim in the signed request that is used alongside existing scopes, e.g. intent containing a JSON object "intent":{"payment":{ "amount":"123.50", "to-account": "22-21-11 23467755"}} or "intent":{"id":"5514cacc-93da-11e9-bc42-526af7764f64"}

    (Note that for context this discussion is ONLY about CIBA, and that the decision has already been made that FAPI-CIBA implementers draft 1 will require the AS to issue an id_token, as CIBA core already does - see issue #229. This position may change in later drafts, but there is not time to change it before ID1.)

    I believe we have the option to endorse multiple methods and leave the final decision to the ecosystem.

    If there are any further suggestions please comment and I will assign a number to your suggestion.

  8. Torsten Lodderstedt

    Thanks for compiling the options 🙂

    I’m leaning towards (4) as it is close to the current design of UK OB and matches BG design. It makes (at least this part of) FAPI more generic and versatile.

    I would also recommend to start working towards (6) and add it in a future revision.

  9. Takahiko Kawasaki

    At least, "5. Dynamic scopes without lodging" will break almost all existing implementations. They would split the scope value into the following scope names.

    1. openid
    2. payments:{"amount":
    3. "100.00",
    4. "to-account":
    5. "22-21-11
    6. 23467755"}

    So, "Dynamic scopes without lodging" should be dropped first.

  10. Takahiko Kawasaki

    Regarding "4. Dynamic scopes with a lodged intent id".

    Some existing authorization servers use the format of layer1:layer2 as static scope names. For example, repo:invite, admin:repo_hook, user:follow can be found in "Available scopes" in GitHub Developer site. It may be interesting to notice that Google’s scopes such as https://www.googleapis.com/auth/analytics.manage.users have the format of layer1:layer2 (layer1 is https in Google's case), too. Microsoft also has defined scopes that start with https: such as https://outlook.office.com/mail.read. channels:history and chat:write:bot are examples from “OAuth Permission scopes” of Slack.

    We don’t have to dare to introduce conflicting rules if we have other options.

  11. Joseph Heenan

    So please pretend I didn’t include any spaces in the example for ‘5’. oops. Thanks Taka. I guess that’s why the examples in Torsten’s blog used base64 encoding for this style.

  12. Takahiko Kawasaki

    I feel like emphasizing again that what is needed is not necessarily scope but a mechanism to convey arbitrary key-value pairs to servers. The reason I think so is that Intent ID of Open Banking doesn't necessarily have to be handled in the OAuth layer. From a viewpoint of OAuth, Open Banking is an application in upper layers.

    Scopes determine whether API accesses are allowed or not. Whether API-specific request parameters are valid or not (e.g. age must not be negative, wday must be in the range from Sunday to Saturday, intent_id is valid), is another protection mechanism in a different layer.

    If payments, intent_id or anything similar should be handled as a kind of scope in the OAuth layer, when the value of payments or others is invalid, the authorization server should return an error in the format that conforms to RFC 6750 like the following.

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: Bearer realm="example",
      error="insufficient_scope",
      scope="payments"
    

    Is this what Open Banking wants to do?

  13. Joseph Heenan

    @Takahiko Kawasaki

    I feel like emphasizing again that what is needed is not necessarily scope but a mechanism to convey arbitrary key-value pairs to servers.

    Is this solution ‘7’ (or possibly ‘6’), or did I miss a difference? (Neither of those solutions defines the /content/ of the payload, just that it is a JSON object.)

  14. Takahiko Kawasaki

    Joseph, yes, what I think would be desirable is a mechanism that doesn’t have to abuse scope, so 6 or 7 would work.

  15. Dave Tonge reporter

    So OpenBanking are not going to move away from the “lodging intent” pattern any time soon (nor is Berlin Group). So for those immediate use cases we need a way of passing the “intent id”.

    It seems to me that option 4, should be an option for that.

    From an API gateway point of view I understand that you wouldn’t then be able to use scope to simply block access to an API, but I don’t think this is that big a deal. Blocking by scope when most of the authZ params are in a lodged intent is not that valuable.

    I think we should at least say something along the lines of

    In scenarios where complex authorisation parameters need to be
    conveyed from the Client to the AS, implementers should consider
    the "lodging intent" pattern described in 
    [Financial_API_Lodging_Intent]. Both the use of paramterized scope
    values and an additional request parameter are supported by this
    specification.
    
    Implementers should not use the login_hint or login_hint_token to
    convey "intent ids" or authorization metadata.
    

    I'm really not sure if we could arrive at a consensus to use structured_scope or some other named top level param in the CIBA spec. I would hope that as a WG we would be able to evolve the lodging intent document in line with Torsten’s blog post.

  16. Nat Sakimura

    I am catching up with the thread,but I am posting this before I forget. I may change my opinion after reading the thread but …

    1. Esp. to @Takahiko Kawasaki : The statement “claims is dedicated to a specific narrow purpose” is actually false. We designed it as an extension point: a mechanism to convey arbitrary key-value pairs to servers. At the time WG also discussed about the structured scope option and WG concluded that it was a bad idea. Thus, we introduced “claims” in lieu of introducing structure to scope. “claims” is a JSON object so it is much more flexible than parameterized scope as you point out. You can also see https://nat.sakimura.org/2019/05/12/comments-back-to-transaction-authorization-or-why-we-need-to-re-think-oauth-scopes-by-torsten/ for more background.
    2. Whatever the mechanism for lodging intent is, including the intent identifier in the login_hint_token is a bad idea. I think there was a comment explaining the absurdity of it on the list. Instead, we should use a separate parameter. I am arguing for claims as it was created as an extension point pointed by openid in the scope value, but I can live with another parameter name. I cannot agree to including intent identifier in the login_hint_token though.
    3. Main difference between using clamis and another top level name is whether to inherit the rich structure defined in the claims object.

    TTL

  17. Takahiko Kawasaki

    @Nat Sakimura

    If claims was created as an extension point (I’m sorry for not knowing the history and didn’t recall the content of your blog when I posted the above although I had already read it in the past), it seems it is the best to utilize claims, by including structured_scope or something similar as suggested by Torsten (Transaction Authorization or why we need to re-think OAuth scopes) or directly inputting key-value pairs into claims. As Open Banking already utilizes claims to convey a value of openbanking_intent_id, there should not be big hurdles in utilizing claims.

  18. Nat Sakimura

    claims has a bunch of features. One of it is to specify where the response should come from. For example, if the request were:

    “claims”:{
        “userinfo”:{
            [… parameters …]
        }
    }
    

    then what is being requested will be returned from UserInfo Endpoint. I.e., the second level names under claims indicates the location where the response should be returned from.

    If we are to utilize claims for the intent_id, then we should consider from where the response should come from and create that entry.

    Inheritance of such semantics is both blessing and curse for claims. If we go with another parameter, we do not inherit such features but we have freedom of doing whatever it suits.

  19. Takahiko Kawasaki

    If we should stick to the semantics of claims (the second level names under claims indicates the location where the response should be returned from), it would be difficult to utilize claims as a free space to store any arbitrary key-value pairs.

    I reread Nat's and Torsten's blogs and noticed again that necessary discussion (at least to me) has already been done there. In the end, I'm feeling like supporting structured_scope in a request object which is described in Torsten's blog.

  20. Takahiko Kawasaki

    One point to be commented is that scope should continue to exist even after structured_scope is introduced. I mean:

    {  
       "iss":"s6BhdRkqt3",
       "aud":"<https://server.example.com",>
       "response_type":"code",
       "client_id":"s6BhdRkqt3",
       "redirect_uri":"<https://client.example.org/cb",>
       "state":"af0ifjsldkj",
       "code_challenge_method":"S256",
       "code_challenge":"5c305578f8f19b2dcdb6c3c955c0a…97e43917cd",
       "scope": "openid sign payment",
       "structured_scope":{  
          "sign":{  
             "credentialID":"qes_eidas",
             "documentDigests":[  
                {  
                   "hash":
                     "sTOgwOm+474gFj0q0x1iSNspKqbcse4IeiqlDg/HWuI=",
                   "label":"Mobile Subscription Contract"
                }
             ],
             "hashAlgorithmOID":"2.16.840.1.101.3.4.2.1"
          },
          "payment":{  
             "type":"sepa-credit-transfer",
             "instructedAmount":{  
                "currency":"EUR",
                "amount":"123.50"
             },
             "debtorAccount":{  
                "iban":"DE40100100103307118608"
             },
             "creditorName":"Merchant123",
             "creditorAccount":{  
                "iban":"DE02100100109307118603"
             },
             "remittanceInformationUnstructured":"new Smartphone"
          }
       }
    }
    

    (Examples in Torsten's blog don’t include scope)

  21. Nat Sakimura

    @Takahiko Kawasaki At least, Userinfo and id_token are two top level claims under “claims” and they indicate the location where the response are included. It does not mandate the additional entries needs to indicate the location but that may appear a bit wiered as well. That’s what I called “curse”.

    I also have to say that I do not like the name “structured_scope”.

  22. Takahiko Kawasaki

    One small thing I forgot to mention is that even if claims is used, using structured_scope (or other new name) is better because it can keep the namespace of "authorization request parameters" cleaner. (I remember the same thing is written in Torsten’s blog.)

  23. Dave Tonge reporter

    We discussed this issue on the ad-hoc call today.

    Those on the call agreed that the login_hint and login_hint_token should not be used for this purpose.

    There was a good discussion on the other options but there was a feeling that the FAPI CIBA profile is the wrong place to specify how complex authorisation parameters should be conveyed.

    Here is some proposed text to add to the FAPI CIBA profile that discourages implementers from using login_hints and points them in some better directions. Hopefully the “lodging intent” document will be developed to be a good reference point for both redirect and decoupled flows.

    In scenarios where complex authorisation parameters need to be
    conveyed from the Client to the AS, implementers should consider
    the "lodging intent" pattern described in 
    [Financial_API_Lodging_Intent]. The use of parameterized scope
    values or the use of an additional request parameter are both 
    supported by this specification.
    
    Implementers should not use the login_hint or login_hint_token to
    convey "intent ids" or any other authorization metadata.
    

    Please can WG members provide feedback on this text as soon as possible as we would like to move FAPI CIBA to implementers draft

  24. Vladimir Dzhuvinov

    Late to this thread, but so glad the login_hint / login_hint_token road was not taken. The semantic overloading of parameters feels horrible in so many ways, it confuses specs, implementers, software code and may even cause security issues.

    Everything that the “structured scopes” (as JSON object) convey can also be done with the existing OAuth 2.0 scope.

    One simple, standard and human readable way to encode arbitrary parameters is the URL encoding:

    sign?credentialID=qes_eidas
    &documentDigests[0].hash=sTOgwOm+474gFj0q0x1iSNspKqbcse4IeiqlDg/HWuI=
    &documentDigests[0].hashlabel=Mobile%20Subscription%20Contract
    &hashAlgorithmOID=2.16.840.1.101.3.4.2.1
    
    payment?type=sepa-credit-transfer
    &instructedAmount.currency=EUR
    &instructedAmount.amount=123.50
    &debtorAccount.iban=DE40100100103307118608
    &creditorName=Merchant123
    &creditorAccount.iban=DE02100100109307118603
    &remittanceInformationUnstructure=new%20Smartphone
    

    Developers are fairly familiar with it and libraries for URL encoding are readily available.

    Those who prefer to work with the JSON object presentation can use a simple tool to convert to / from it.

    If the static scope value is prefixed with an URI (good practise), then the whole scope value can be parsed as an URI and the parameters extracted as query parameters.

  25. Log in to comment