Skip to content
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

Support identity impersonation #201

Closed
mitar opened this issue Jan 30, 2020 · 12 comments
Closed

Support identity impersonation #201

mitar opened this issue Jan 30, 2020 · 12 comments
Labels
rfc A request for comments to discuss and share ideas.

Comments

@mitar
Copy link
Contributor

mitar commented Jan 30, 2020

Is your feature request related to a problem? Please describe.

in our system we would like to allow admins to impersonate regular users. The rest of the stack should see the same token as the regular user, only that the admin would authenticate as the user. This would be used to help with user support.

Describe the solution you'd like

Another endpoint to authenticate the admin user as the request user. It would otherwise return same OpenID Connect responses, only that it would not require the user to be authenticated, but the admin.

Ideally, the token provided to the app would have additional fields documenting who is impersonating the user.

Moreover, this action should be logged/auditable.

Describe alternatives you've considered

Alternative is for the user to share username and password with the admin, but this is not really nice.

@aeneasr
Copy link
Member

aeneasr commented Jan 30, 2020

Thank you for sharing this idea.

This is a tricky area because impersonation can easily lead to privilege escalation and other attack vectors. ORY Kratos does not know who has what rights so it can not distinguish if the user being impersonated has more access privileges than the one that's performing the impersonation.

A threat agent (could be a disgruntled employee) might be able to abuse impersonation to do serious harm. This also rings true if the threat agent does indeed have privileged access anyways but wants to impersonate another user to perform abusive action in their name. While audit logs are useful after the fact, they usually lack to track all of the things the person could have done (e.g. setting up a rootkit on a VM).

In general I don't think it's a good idea to issue credentials on behalf of another user without their explicit consent not only on the authentication itself but also on the scope. What we might be able to do is to use a "Device OAuth2 Flow" (think Amazon FireStick) where one party explicitly confirms (a) authentication and (b) scope and (c) access duration and (d) is able to revoke the authorization.

I also think that it is very important to mark impersonated tokens (if issued...) as such. This allows backends to reject impersonated tokens for sensitive operations.

Alternative is for the user to share username and password with the admin, but this is not really nice.

That's more than not really nice, it's the worst that can happen to any IT security, an absolute nightmare and never to be done ever!

@aeneasr aeneasr added the rfc A request for comments to discuss and share ideas. label Jan 30, 2020
@mitar
Copy link
Contributor Author

mitar commented Jan 30, 2020

This is a tricky area because impersonation can easily lead to privilege escalation and other attack vectors.

Or it can also be seen as feature, sudo. For regular use of the app you do not have too many permissions, but you can trigger impersonation of root user when you need that.

I in fact find impersonation as a basic feature an identity infrastructure service should provide because it enables interesting other use cases.

But yes, I am not sure how can a service like ORY Kratos figure permissions out, but maybe it can just delegate to the app to allow or deny the request? And then the app can do this with some policy, or with a prompt to the user, or whatever?

I also think that it is very important to mark impersonated tokens (if issued...) as such. This allows backends to reject impersonated tokens for sensitive operations.

I agree. The default fields in the token should be standard, but then additional fields could explain who is in fact behind the token. And then apps can or deny, log, or even display it to other users (commented by X on behalf of Y).

@aeneasr
Copy link
Member

aeneasr commented Jan 30, 2020

Thank you for the quick reply.

Regarding use cases, I think t his should be based on demand and not "could be useful" :) Impersonation is very dangerous, and adding it needs to be rooted in a concrete and useful way that can not be achieved otherwise, specifically:

  • Support impersonation: Your support staff should have a dedicated screen for account management and support. Impersonation is not useful if the user wants to "show you" something that is broken (i.e. due to some browser plugin). Here you need screen share, not impersonation.
  • Multiple profile: This is achieved through account switching (see Google Login)
  • Two accounts: Open two private browser windows
  • Anonymous: This is actually a nice feature but does not need impersonation. Instead it would be cool to issue temporary IDs. Maybe we can figure something out here!

In summary, none of the use cases convince me to introduce such a dangerous feature.

I agree. The default fields in the token should be standard, but then additional fields could explain who is in fact behind the token. And then apps can or deny, log, or even display it to other users (commented by X on behalf of Y).

In fact, I think it should be the other way around. The primary user identifier of the session is the admin, and there is an additional field "impersonates": "...." which points to the user being impersonated. That way you have to knowingly implement this feature in your backend which leads to much better security (because the feature does not work implicitly but explicitly).

@mitar
Copy link
Contributor Author

mitar commented Jan 30, 2020

Thank you for the quick reply.

Thank you for even quicker reply. Given that this is labelled with rfc I will continue the debate here and kindly disagree, but I do respect your direction with this project and of course take it where you find the best.

Impersonation is very dangerous, and adding it needs to be rooted in a concrete and useful way that can not be achieved otherwise

I see it on other hand as a basic security primitive. Which of course has to be implemented well (both from security and UI/UX perspective). SETUID bit is an example of an implementation of this primitive, and of course it can be misused, but it is also very understood. Having SETUID for web applications seems as evolution of the primitive.

Support impersonation

Please see some of reasons to have support impersonation here.

Multiple profile: This is achieved through account switching (see Google Login)

I know that I read somewhere in documentation what Ory does this (if user first logs with one account and then another and then figure that they are the same), but I cannot find it now.

So without knowing details how Ory does this, without support for impersonation target app has a problem: what if both accounts A and B created some content, and that content has userId stored alongside the content. When you merge A and B, what do you do about those userIds? With impersonation support, you can leave them as-is, only you augment stored data to add that user B impersonated user A during that time, linking them together.

Two accounts: Open two private browser windows

But I want users to have only one username/password. And see from one dashboard all their profiles. Not that they have to logout and login. That was so much pain with Twitter if you wanted to use multiple accounts there. They finally added support for that.

Anonymous: This is actually a nice feature but does not need impersonation. Instead it would be cool to issue temporary IDs. Maybe we can figure something out here!

So I do not explain this feature in detail there, but in my view anonymous use requires a balance. App might dislike anonymous users because it requires to know who is who, for example, an online voting app. On the other hand, anonymous contributions even in context of a voting app could be useful so that people can anonymously raise comments during voting. But then, those comments might be moderated and moderators might want to ban a particular person (and not just their anonymous identity).

So in my view it is important that app can or a) get information about impersonation b) or get a pointer to where it can get this information. Anonymous users would be in the category b), and if moderator wants to deanonymize the comment to be able to ban it, it would have to follow the pointer to the identity service which would provide then this information (if moderator has permission to do so), but the fact of deanonymization would be logged. Other users would then be able to decide if moderator overstepped or not their role, and most importantly, the anonymous user would be informed that they were deanonymized. So this is the flow I am trying to implement.

Of course there might be other ways to achieve anonymization, but generally they are already available (simply registering a new account and things like that). So here the idea is how to provide support for a responsible anonymization.

In fact, I think it should be the other way around.

I understand your position, but I disagree. This is like saying that sudo would just add optional additional information and apps could or could not respect it. An interesting approach. but could be nightmare to debug. I think it is better if apps do not have to do anything special, it just works for them, but a) apps can opt-in to show extra information about impersonation happening b) the identity provider handles all the complexity of logging, checking for permissions, and checking if app allows impersonation.

BTW, I completely agree that user has to be able to give consent for impersonation to happens in the support impersonation use case. But in my view this is separate from the security primitive of impersonation itself. When you call sudo fobar the sudo program should prompt the user foobar to allow that or not, but security primitive of changing the user is independent from this consent. But I can also see that the primitive itself would be made that the consent is always required. This could be implemented maybe with a special scope, impersonate and you have to obtain OAuth token from the user for this scope if you want to impersonate.

@aeneasr
Copy link
Member

aeneasr commented Jan 31, 2020

I see it on other hand as a basic security primitive. Which of course has to be implemented well (both from security and UI/UX perspective). SETUID bit is an example of an implementation of this primitive, and of course it can be misused, but it is also very understood. Having SETUID for web applications seems as evolution of the primitive.

You probably mean su, right? I think su and UNIX primitives in general are very nice. Keep in mind that for most su interactions (unless you're literally root) you'll need the password of the user.

I know that I read somewhere in documentation what Ory does this (if user first logs with one account and then another and then figure that they are the same), but I cannot find it now.

Ory is a conglomerate of several applications that solve very clear-cut problems (e.g. OAuth2). OR Kratos - which isn't even officially released yet - solves login and would solve account switching in the future.

But I want users to have only one username/password. And see from one dashboard all their profiles. Not that they have to logout and login. That was so much pain with Twitter if you wanted to use multiple accounts there. They finally added support for that.

Right, that would be "linking" two accounts though, not impersonation. I believe that we could achieve that in Kratos. Linking requires consent (and proof of identity) from both parties.

Of course there might be other ways to achieve anonymization, but generally they are already available (simply registering a new account and things like that). So here the idea is how to provide support for a responsible anonymization.

No one is anonymous on the internet, but the general use case would be for the site admin to decide. They can either use temporary profiles or not :)

I understand your position, but I disagree.

PHP shows all error messages per default. This is very useful for debugging. When you go into a production environment, you sometimes forget to set everything so that it's production ready and just copy the already working (sometimes hard to get to work) config files. Now, when your database goes down, PHP shows (or used to show) the host, username, and password in clear text to help you debug. What a nightmare for small site operators!

Ory's philosophy is to make insecure things hard and being secure easy. That's why we focus so heavily on this space. I understand the "hey I really want this feature and as easy as possible" but we have to thing about the other 99% that don't need it and that would be very surprised if something like the PHP example happened. I don't think we'll find common ground here ;)

@aeneasr
Copy link
Member

aeneasr commented Jan 31, 2020

I thought about this a bit more (so thank you for your well-written input!). You do have I point with impersonation, although I feel that most use cases described do not warrant an impersonation functionality because they can be solved in different and much more secure / bespoke ways. Our vision for Kratos is to do things right and give devs the freedom to adapt to their use cases - not build a full-stack cover-all monster that ends up unusable in the end.

I think impersonation can be solved with the OAuth2 Device Authorization Grant (https://tools.ietf.org/html/rfc8628). The problem is that the party that wants the access token is on a different device than the person that's authenticating and giving consent - which is exactly the case when we talk about support or remote help. The support desk would send the customer a link - the customer would complete the challenge and relay the code back to the support desk - the flow is completed and support has access with the requested scope and can act on behalf of the customer.

I think it's very important to differentiate between acting on behalf of someone and merging, account switching, anonymous users. These are all very different domains and mingling them together will end up - in my opinion - in a huge, insecure mess. When I talk about impersonation, what I mean is acting on behalf of someone else. I think that all the other use cases (except for google ads) do not cover that, which is why I'm reluctant to consider them valid use cases for this particular terminology.

@mitar
Copy link
Contributor Author

mitar commented Jan 31, 2020

You probably mean su, right?

su is just one of the programs which is using SETUID bit. In general, SETUID allows a caller of a program to impersonate the user who is owner of the program. This is a basic building block of unix security model. See also this patent where the whole addition to it, I would say, is adding support for impersonation:

An additional access control bit is added to each executable file. When this bit is set to one, the identification of the current user is changed to that of the owner of the executable file. The program in the executable file then has access to all data files owned by the same owner. This change is temporary, the proper identification being restored when the program is terminated.

solves login and would solve account switching in the future.

So how it is planned for Ory to solve the problem when same user logs through two different methods and create two different accounts which then in app create content associated with those two different accounts and the user then wants to meld/merge those accounts together. What will Ory then do?

Right, that would be "linking" two accounts though, not impersonation. I believe that we could achieve that in Kratos. Linking requires consent (and proof of identity) from both parties.

Not really. If the case of old Twitter, I have to be able to present myself to the Twitter app once as account A and once as account B, while I would be logged into Ory only once.

So maybe I was unclear here. Linking is where I would use Twitter's account A and Twitter's account B to both allow me to login into the same Ory identity. That is linking. Linking multiple social account to the same Ory identity.

I am not talking about this. I am talking about apps which use Ory as identity provider. In that case same Ory identity might once want to be seen to the app as account A, but at some other time as account B.

Our vision for Kratos is to do things right and give devs the freedom to adapt to their use cases

Yes, I think you are doing a great job here, BTW. I am really impressed with the quality of both software and documentation.

not build a full-stack cover-all monster that ends up unusable in the end.

I agree with this as well. This is also my plan with my own project for identity infrastructure service, Charon. I limited set of features which I believe are needed to describe a particular vision of security. I am trying to do there things a bit differently than how they are done traditionally, one of them is heavy use of impersonation primitive to implement few common scenarios. But this is also an experiment, to see how it will work out. On other hand I think Ory is trying to be much more traditional and stable approach here, which is great as well. Most people do not want an experimental approach which maybe turns out to be a total failure.

But before I start working on that I am exploring others, and Ory looks really great. So I thought of seeing how would you feel about adding such feature.

I think it's very important to differentiate between acting on behalf of someone and merging, account switching, anonymous users. These are all very different domains and mingling them together will end up - in my opinion - in a huge, insecure mess. When I talk about impersonation, what I mean is acting on behalf of someone else. I think that all the other use cases (except for google ads) do not cover that, which is why I'm reluctant to consider them valid use cases for this particular terminology.

A completely valid point. I will then experiment with this inside my own project and let's see where I get. :-) I on the other side see that if you have a well thought and implemented security primitive, it is good to use it for multiple user-facing features because you have then less code paths you have to make sure they work well.

@mitar
Copy link
Contributor Author

mitar commented Sep 4, 2020

So since then I realized that there is a standard claim to do exactly this, in a way I would like, act (actor): https://tools.ietf.org/html/rfc8693#section-4.1

So if impersonation is happening, subject/issuer stays the same, but actor can be set to the user who is doing the impersonation. This is different from what you wrote above, that you would prefer if the subject would be who is doing the impersonation, and then additional field which app which supports it should check to see in which name it should act. I do not like your proposal, but I do like act claim. :-)

So, a question could be: does Kratos plan to support impersonation and act claim.

@mitar
Copy link
Contributor Author

mitar commented Sep 6, 2020

Thus, when principal A impersonates principal B, then insofar as any entity receiving such a token is concerned, they are actually dealing with B. It is true that some members of the identity system might have awareness that impersonation is going on, but it is not a requirement. For all intents and purposes, when A is impersonating B, A is B within the context of the rights authorized by the token.

@aeneasr
Copy link
Member

aeneasr commented Sep 7, 2020

It's interesting that there could be a chain of actors, so principal A impersonating B impersonating C, although I doubt the usefulness of such a feature in real world scenarios. It would be interesting to see the decision/reasoning process behind the proposal but I assume that this path was taken to keep backwards compatibility with the original OAuth2 spec. I am still hesitant to give that an ok from my side but I do get the argument! I'd also be open to reopen this issue and discuss it further with the community!

@mitar
Copy link
Contributor Author

mitar commented Sep 7, 2020

When I made the comment I have not yet read the whole spec.

It would be interesting to see the decision/reasoning process behind the proposal but I assume that this path was taken to keep backwards compatibility with the original OAuth2 spec.

So I think it is interesting to read the introduction to this spec. They define "delegation" and "impersonation":

When principal A impersonates principal B, A is given all the rights that B has within some defined rights context and is indistinguishable from B in that context. Thus, when principal A impersonates principal B, then insofar as any entity receiving such a token is concerned, they are actually dealing with B. It is true that some members of the identity system might have awareness that impersonation is going on, but it is not a requirement. For all intents and purposes, when A is impersonating B, A is B within the context of the rights authorized by the token. A's ability to impersonate B could be limited in scope or time, or even with a one-time-use restriction, whether via the contents of the token or an out-of-band mechanism.

Delegation semantics are different than impersonation semantics, though the two are closely related. With delegation semantics, principal A still has its own identity separate from B, and it is explicitly understood that while B may have delegated some of its rights to A, any actions taken are being taken by A representing B. In a sense, A is an agent for B.

So it seems what I envision as impersonation they name "delegation". Their "impersonation" is similar, but without information about delegation. Which is what I thought standard OAuth delegation is about. So to me their terminology is switched around. But OK.

@jetaggart
Copy link

@aeneasr We have a flow where we register users via the identity API and have registrations turned off for self service (we're using custom UI). How can we login after registration in this case? I have a POC that orchestrates browser login via the api and manually returns set-cookie from the browser login flow inside our API but this feels hacky. Is there a way to generate a cookie for a user so we can cookie them on hitting our registration endpoint to prevent them from having to log in immediately after registration?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rfc A request for comments to discuss and share ideas.
Projects
None yet
Development

No branches or pull requests

3 participants