Identityserver3 - User Impersonation - identityserver3

I have read the issues about impersonation, and from what i could find so far it can be achieved. I'm not sure tho if the following could be done using it.
A user doesn't have permission to do a certain operation, but it can be done if a supervisor grant him access.
The grant would be only for that operation/request.
is this something that can be done using impersonation, or there is a better approach for this?
Thanks in advance.

Quick brain dump of what you could do: You would have to implement this yourself in the user service in IdentityServer. One approach is to pass a custom param in the acr_values from the client with the ID of the user you want to impersonate (you will also have to pass prompt=login to force the request to go to the login workflow and thus the user service). In your user service implementation in PreAuthenticate you can check if the user is already authenticated, the custom acr_values is present, and the user is allowed to impersonate the user being requested. You'd then assign the AuthenticateResult on the context with the identity of the new user. This short circuits the login process and will return back to the authorization endpoint, and then back to your client app.

Related

Impersonate user for specific client

I deploy a Keycloak-Instance. A requirement is for the Helpdesk to be able to impersonate users.
There is a impersonation-button in the Admin-GUI, great. But the Impersonation-Button gets me access_token for the account-console. I need token for other Clients. Is there a way of "Log into App X as User Y with Using my Admin-Permissions"?
The Impersonation-Endpoint seems not to provide a feature to specify the app to impersonate (https://www.keycloak.org/docs-api/15.0/rest-api/index.html#_impersonate).
EDIT: I'm sorry, it was caused by a bug on my side! Make sure that you aren't logged in in any other app in the realm and that you also don't trigger the logout-function of any app after pressing Impersonate! (or otherwise you have to redo everything)
Thanks in advance!
Impersonation in keycloak is realm level. The access_token that you got from impersonate button is not limited to account-console, it can be used by other clients(or applications) from same realm. Try accessing any other application/client from same realm. You should be able to directly access that application.
If you want to limit impersonation to specific client then you have to extend the Authenticator and implement logic yourself.

What is the proper way to implement "type password again to continue" for critical actions in REST

As the title suggests, I'm trying to implement the mechanism of retyping the password again before proceeding any critical action, e.g. change email, deactivate an account, invites a new user, ... etc.
The problem is, I'm confused about how it should be done in the REST world.
Should it be like, first, use the password to authenticate the user, but with a different backing authentication made especially for this action and use the resulted token to access this protected resource later? E.g. a JWT token with a specific claim for this action and guard that endpoint with this custom authentication to authenticate for this custom token?
Or should it be done in one request providing the password and based on password check the action will be proceeded or denied?
Or should it be something else?
Thanks in advance for your help, I really appreciate it.
Note: I'm using DRF that's why I added it's the tag to the question, but as this is a general question

Keycloak: How can user be filtered for a specific OIDC client by role?

We have one realm with many users and multiple OIDC clients configured. We would like to connect another application (OIDC Client) to the realm. Unfortunately, the client cannot check for any attributes or roles to be present.
How can I configure Keycloak to authenticate with a specific OIDC-client but return failing authentication if users have not a specific role?
Generally this type of option will not work, since authorization redirects occur before you know who the user is, and therefore before you know which roles are involved.
WHAT I WOULD DO
Make an authorization redirect perform only the following job:
Signing in the user and returning the user id (sub claim), along with perhaps a couple of scopes
Then manage roles within your app - the second app should call a Web API that does this:
Get claims from the access token, and also from other sources, then use them for identification and authorization
If a user authenticates but is not entitled to use a particular app, detect this via an API call, then present an Access Denied page in the app after login.
To reach this you should implement the AuthenticatorFactory and Authenticator interfaces of Keycloak. Look here for more infos.
In the authenticate() method you will write something similar to this:
If(client == yourClient){
// Check for roles
}
Otherwise, expected behaviour in case of failure.

Authorization new user - keycloak

I want to secure my user registration page with keycloak but couldn't think of any approaches while reading the docs. The best option for me:
New user register, but his account is unavailable.
When ADMIN accept this new account, user can log in.
Is it possible do it in keycloak ? Or any similar solution ?
Sure you can do it. The easiest way is to give a default role to newly registred users. The default role would give only minimal privileges. Then ADMIN can promote the user to the more appropriate group or role.
Probably to "automate" or smoothen the second part of this flow you might need some flow customization. Cf. https://www.keycloak.org/docs/latest/server_development/#required-action-walkthrough and related.
Another solution is to give to the default minimal role the possibility to request acceptation, or make the request automatically at first logging (eg. mail sent to ADMIN).
EDIT
Programmatically it is also possible to make calls to the Keycloak Admin API (through native Admin Client). For example, you can write some logic (and associated UI or whatever) that will assign or remove groups from a user.
See. Admin REST API

Restricting REST API results based on the user

I am building a messaging application using BackboneJS which naturally persists using a REST interface.
The issue I'm having is that I don't know how to restrict what data a user can pull back from the API. For instance a call to /messages would, at the moment, return messages for ALL users. I would like that resource to only return messages belonging to the current user.
Searching online seems to indicate that oAuth2 is the best way to solve this issue but all the tutorials talk about been redirected to another place to confirm access and retrieve an access token.
Given that my users will have already logged into the message application and that the REST API is actually part of the same application I don't like the idea of asking the users to confirm that my own app can access my own API.
Is there a better way?
oAuth2 is probably your best bet -- you definitely don't want to roll your own security. However, the flavor of oAuth2 you are thinking of is probably not what you want.
oAuth2 has four different flavors, known as authorization grant types:
Authorization code: This is the type you are thinking about. It is often called three-legged oAuth, because there are three actors in the token granting process (app, resource owner, and user). The app asks the user whether it is ok for the resource owner to give specific type(s) of access to the resource. It is a rather complex process that allows the validation of user credentials without allowing the app access to them. This is not necessary in your case, since you are both the app and resource owner.
Client credentials: This is a method for authorizing a client application with the server. It does not use user credentials at all. If you completely trust your client application (all client applications) to correctly protect user data and not expose other user's data to the user using the app, or you are providing only non-user data via the API (for example, map data or catalog data), you might be able to use this fairly simple type of oAuth2. However, if you want to be vigilant in protecting user data (and not allow apps to get to the data without the user providing credentials), you might not use this one.
Resource owner password credentials: The username and password of the user is passed via https to your backend server, which authenticates and authorizes access by providing an access token. The access token can then be passed with each call, and it remains valid for accessing the backend until a configurable time period has elapsed. This means that someone intercepting the token could only use it successfully for a limited amount of time (some number of minutes, generally). The interceptor would not know the username and password of the user. In addition, you can supply the app with a refresh token, which can be used to get a new access token once it has expired (until the refresh token expires -- usually with a significantly longer expiration date). Since the credentials are not passed across the wire often (and must only be passed encrypted), this is often the best solution for protecting user credentials and not requiring the user to pass them in often (good user experience). Implementation is much simpler than for the authorization code grant type.
Implicit: This is the least secure method -- no credentials are validated server side at all. This is usually used for client side scripting languages where credentials cannot be stored safely. If you are worried about security at all, avoid this type if possible.
So, check out OAuth 2.0, and look for the resource owner password credentials grant type.