[FOLIO-1332] SPIKE: Design/Discuss Overrides Created: 09/Jul/18  Updated: 03/Jul/19  Resolved: 04/Oct/18

Status: Closed
Project: FOLIO
Components: None
Affects versions: None
Fix versions: None

Type: Umbrella Priority: P2
Reporter: Cate Boerema (Inactive) Assignee: Kurt Nordstrom
Resolution: Done Votes: 0
Labels: RFC, core, sprint42, sprint43, sprint44, sprint45, sprint46, sprint47, sprint48, ui-core
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original estimate: Not Specified

Issue links:
Blocks
blocks UIU-445 Allow for the cancellation of a fee/f... Draft
Relates
relates to MODAT-34 Add functionality to use override tokens Open
relates to MODLOGIN-74 Add ability to create override tokens Open
relates to UIU-583 Change due date by escalating permiss... Open
relates to UXPROD-239 Loans: Policy Overrides (Q1 2019 work) Closed
relates to UXPROD-1609 Loans: Policy Overrides - override no... Closed
relates to UXPROD-1847 Loans: Policy Overrides - override mu... Closed
relates to FOLIO-1233 Implement refresh tokens Closed
relates to OKAPI-656 Add support for additional token header Closed
relates to STCON-74 Handle request and use of override token Closed
relates to UIU-582 Permissions for change due date Closed
relates to UXPROD-1245 Loans: One-time escalation of a user'... Draft
Sprint:
Development Team: Prokopovych

 Description   

We held a meeting yesterday and have come to the following:

  • We are introducing the concept of an "Override Token" (term might change), which would be a secondary token that would be sent along with the standard access token in a different header for the request. This token would be an opaque, signed token that would carry in its payload a list of extra permissions that would be granted to the user. It would carry an expiration time, so as to become invalid after a short period.
  • When mod-authtoken receives this Override Token, it will decrypt it and add the contained permissions to the user's permissions for the current request. It will also add these permissions to the tokens generated for any modules along the current request chain, so that the modules will be able to take advantage of the override for the request.
  • The process of minting a new Override Token will be done via a new endpoint on mod-login, perhaps /authn/override. The supervisor user will provide, to the endpoint, their credentials, along with the userid being granted the token, a list of the supervisor's permissions that will be granted by the token, and the time-to-live of the token. The response from the endpoint will be the override token. The advantage to this scheme is that the supervisor never exposes their access token to the user's browser, which helps close a potential security hole.
  • The following components would need to be changed to make this work:
    • mod-authtoken: Would need to be able to recognize and decrypt the new tokens, and to incorporate the contents into the request chain.
    • mod-login: Would need new endpoint to permit minting of the Override Token
    • okapi: Would need to recognize the new header (X-Okapi-Override?) and pass along accordingly
    • stripes: Would need changes to be able to provide login for supervisor to create override token, and would need to be able to attach the new token to the overridden request in the new header.


 Comments   
Comment by Cate Boerema (Inactive) [ 16/Jul/18 ]

Per Jakub Skoczen, I am assigning this to Kurt Nordstrom

Comment by Cate Boerema (Inactive) [ 20/Jul/18 ]

Hi Kurt Nordstrom, do you have an update on this? Did you determine if this should stay assigned to you for analysis or if it's a frontend-only thing?

Comment by Kurt Nordstrom [ 20/Jul/18 ]

Cate Boerema Here are my thoughts on the matter:

Yes, we currently could implement an override functionality directly in the front end. However, this is slightly problematic, as it will mean that an access token for the superuser will be exposed in the user's browser, and a mischievous user could use their browser's dev tools to extract it, and then re-use the token for gaining access to endpoints.

This raises the topic of token expiration and refresh tokens, which is something that we have discussed in the past, but haven't formally implemented yet. What this feature would allow us to do would be to have the superuser token be created with a short time-to-live, so that the window of opportunity for mischief was very small. It would also improve security overall by reducing the usefulness of token leakage.

See https://folio-org.atlassian.net/browse/FOLIO-1233

My recommendation would be to raise the priority of implementing refresh tokens and token expiration and make it a blocker for this story.

Comment by Jakub Skoczen [ 24/Jul/18 ]

Kurt Nordstrom Expiration/TTL makes sense to me. I am not clear we need the full capability of "refresh tokens" for this?

Comment by Kurt Nordstrom [ 25/Jul/18 ]

Okay, here is how I currently see things:

  • One thing we absolutely do not want is a long-lived token for a superuser sitting in the user's browser data after the override has occurred.
  • Honestly, we don't want ANY long-lived tokens hanging out in the user's browser data, but that can be a different problem for a different day.
  • If we want to implement an override system without making things significantly less secure than they currently are, one option would simply be to add a flag to the login endpoint which would specify that we want a token that will die soon. This token will live long enough to execute the superuser's commands and then expire.
  • Yes, there is still the fact that this is a 'voluntary' request for a short TTL token from the front-end, but the truth is that with the current set up, any kind of token request is 'voluntary'. Any user spoofed into putting their username/password into the wrong form can potentially return a long-lived token that can be leaked. The only real way to provide security here is to make ALL access tokens short lived and implement a refresh token system that is more secure.
Comment by Cate Boerema (Inactive) [ 27/Jul/18 ]

Thanks Kurt Nordstrom. Are we almost ready to get started on development? Emma Boettcher has created some stories we can work from, in case the Fee/fine-related stories are still blocked (Jakub Skoczen asked that she create these): UIU-582 Closed and UIU-583 Open . I'll link them here.

Comment by Kurt Nordstrom [ 27/Jul/18 ]

Cate Boerema If we want to proceed with the short-term solution, all we'd need for the backend would be an optional flag to the login module to tell it to request a short-lived token as opposed to a long-lived one.

Comment by Cate Boerema (Inactive) [ 30/Jul/18 ]

Excellent! We had a chat about this in today's roundup and I think everyone understands what needs to be done, as Emma talked us through her stories ( UIU-582 Closed and UIU-583 Open ). If you are looking for your next story, you might pick those up and get the backend changes ready.

I guess we can close this spike if the solution is designed and documented (at least at a high level) in this ticket (I think that's what you have done in the comments above). Please close this ticket if you agree.

Comment by Jakub Skoczen [ 20/Aug/18 ]

Kurt Nordstrom let's decided how would we utilize the refresh token functionality to provide this.

Comment by Cate Boerema (Inactive) [ 03/Sep/18 ]

Kurt Nordstrom and Jakub Skoczen, can we call this done already? It's sprint review time and, while we won't have anything to show for this (I assume), it is a significant piece of design work we did and I'd like it to display in the list of completed work. Please mark as Closed > Done if you think this is complete. Thanks!

Comment by Heikki Levanto [ 05/Sep/18 ]

In my humble opinion, messing about tokens is a wrong approach. It is tricky to get right, and may lead to security problems.

I think a safer, saner, and simpler solution would be to let everyone keep using their own tokens, but add a facility in mod-permissions, where a supervisor has the ability to grant some of his own permissions to a given user, for a limited time. UI-wise, this could be done in a new tab or popup on the users screen, where the superuser logs in, makes the permission-giving call, and closes the tab. Or it could be a function the supervisor can invoke on his own screen. In any case, the supervisor could select the (top-level) permissions to grant, and the time they should be available.

In mod-permissions, we would need to add a timeout field to the permission structure, and when checking permissions, see if the user has some that have timed out, and delete them. There may be some issues with caching the permissions, but I am sure we can find a way around those.

It could even be possible to restrict the temporary permission to a single request, by noting the first time it is being used, attaching the request-id to that, and later verifying the request-id. But this could get tricky when expanding permissions, etc. Probably not needed for the first version(s).

Of course the supervisor would have to have a permission to delegate his permissions to another user. This could be a general one, or restricted to some top-level permissions.

Comment by Kurt Nordstrom [ 05/Sep/18 ]

Heikki Levanto It would seem tricky, with the 'temporary permissions' approach, to attach the needed permissions upgrade to a particular request, though. In essence the supervisor is boosting the user's privileges (albeit temporarily), but not restricting what the user might do with them. Even if we attach a request id, it seems like it would be tricky to peg that to one particular request that the override is granting the ability to do.

Comment by VBar [ 07/Sep/18 ]

I'm liking Heikki's "temporary permissions" approach, but I do have concerns about privilege escalation be it through a superuser context or a supervisor impersonation.

Have we considered supporting the notion of allowing multiple tokens for a user?

  • User hits the override block
  • Supervisor acts on the override
    • Presumably the Supervisor has been issued a required permission in order to issue the override
    • Only the specific permission needed for the action is granted.
  • The result is that the user is issued a second token that carries only the required permission and is short-lived.
    • Override request could optionally allow setting the TTL.
    • the temporary permission is not permanently attached to the user
    • temporary token is essentially a bearer token
    • original user token remains untouched.
  • The second token is submitted along with the user's normal token on the request
    • The normal token is rejected as before
    • The second (bearer) token is accepted and the action is allowed.
  • Bearer token lifecycle
  • The bearer token would need to be actively removed from the user's state once it expires.
  • The bearer token could even be "single use" and invalidated the first time it is accepted in order to prevent reuse in a different context.
Comment by Cate Boerema (Inactive) [ 19/Sep/18 ]

Guys, this spike has been open for almost an entire quarter. Can we document a decision by the end of this week (September 21)?

Comment by Kurt Nordstrom [ 19/Sep/18 ]

We held a meeting yesterday and have come to the following:

  • We are introducing the concept of an "Override Token" (term might change), which would be a secondary token that would be sent along with the standard access token in a different header for the request. This token would be an opaque, signed token that would carry in its payload a list of extra permissions that would be granted to the user. It would carry an expiration time, so as to become invalid after a short period.
  • When mod-authtoken receives this Override Token, it will decrypt it and add the contained permissions to the user's permissions for the current request. It will also add these permissions to the tokens generated for any modules along the current request chain, so that the modules will be able to take advantage of the override for the request.
  • The process of minting a new Override Token will be done via a new endpoint on mod-login, perhaps /authn/override. The supervisor user will provide, to the endpoint, their credentials, along with the userid being granted the token, a list of the supervisor's permissions that will be granted by the token, and the time-to-live of the token. The response from the endpoint will be the override token. The advantage to this scheme is that the supervisor never exposes their access token to the user's browser, which helps close a potential security hole.
  • The following components would need to be changed to make this work:
    • mod-authtoken: Would need to be able to recognize and decrypt the new tokens, and to incorporate the contents into the request chain.
    • mod-login: Would need new endpoint to permit minting of the Override Token
    • okapi: Would need to recognize the new header (X-Okapi-Override?) and pass along accordingly
    • stripes: Would need changes to be able to provide login for supervisor to create override token, and would need to be able to attach the new token to the overridden request in the new header.
Comment by Mike Taylor [ 19/Sep/18 ]

That seems like a much more complicated scheme than the original.

How is the client (Stripes or a module) able to know which specific temporary permissions to request?

The advantage to this scheme is that the supervisor never exposes their access token to the user's browser, which helps close a potential security hole.

But the supervisor exposes their credentials to the user's browser, which seems like a much worse security hole (since in general credentials last much longer than tokens generated from them).

Comment by Marc Johnson [ 19/Sep/18 ]

Mike Taylor Good question about the awareness (and coupling) around the specific permissions.

Could it initially be all of the permissions of the supervisor (which admittedly is another potential security challenge)?

the supervisor exposes their credentials to the user's browser

As I understand it, we don't have an approach where the supervisor's credentials aren't exposed to the original user's browser. At least not where the user experience is where the supervisor performs their login in the original user's browser, which is what I believe is described in scenario 2 of UIU-445 Draft . Is there an alternative I'm not aware of, which does not involve this exposure? Or are you stating that there is a security risk of credentials capture, which is significantly higher than token capture?

Comment by Mike Taylor [ 19/Sep/18 ]

Could it initially be all of the permissions of the supervisor (which admittedly is another potential security challenge)?

It could – but only at the expense of sacrificing all the flexibility that (presumably) this more complex approach is intended to get us. If that's all we wanted to do, then the simpler `sudo`-like approach would seem the better way to do it.

As I understand it, we don't have an approach where the supervisor's credentials aren't exposed to the original user's browser.

I agree. All I'm saying is that, given that this seems to be a hard requirement, it seems a bit pointless to worry that the supervisor's much shorter-lived session token is also available to the user's browser.

Comment by Heikki Levanto [ 19/Sep/18 ]

We discussed this briefly in yesterdays call. Although the use case here is that the supervisor will walk over to the assistants browser and type in credentials, this design leaves open the possibility that in some future version the supervisor may do this on his own browser, get some opaque token, and pass it to the assistant via a Folio notification, email, or other channel.

As to the permissions, yes, we can start with all permissions, but most likely the UI module that handles the situation will have a good idea of what is needed here - the operation to forgive a fine clearly needs some fine-related permissions, and not purchase-order permissions...

Comment by Heikki Levanto [ 19/Sep/18 ]

I just came to think that the override endpoint should be in a separate interface than the regular login service. We already have alternative login methods, and maybe not all of them are suitable for authenticating a supervisor that happens to walk by the browser, without his session cookies from some other system present... Keeping the service in a separate interface will make it possible for the module to declare that it does not support the override service, and for some other module to step in and do it.

Comment by Marc Johnson [ 19/Sep/18 ]

Mike Taylor Agreed, thanks for clarifying my understanding of your thoughts.

Comment by Marc Johnson [ 19/Sep/18 ]

The topic of which permissions apply to a given operation may well overlap a little with UXPROD-1828 Closed

Comment by Marc Johnson [ 19/Sep/18 ]

Heikki Levanto I think a separate interface is worth exploring (we may need to figure out endpoints, as RAML Module Builder does not support overlapping paths in interface definitions AFAIK).

There is a note in UIU-445 Draft that states this should work with SSO logins as well as internal, so it would likely need implementing by both.

Comment by Kurt Nordstrom [ 19/Sep/18 ]

Heikki Levanto I like the idea of being able to perform an override via multiple authentication services. Need to think through how to implement that in a way that leaves the door open for future expandability.

Comment by Mike Taylor [ 19/Sep/18 ]

Heikki Levanto Your point about separating interfaces is well taken.

Generated at Thu Feb 08 23:12:34 UTC 2024 using Jira 1001.0.0-SNAPSHOT#100246-sha1:7a5c50119eb0633d306e14180817ddef5e80c75d.