How can I configure authorization in keycloak based on last login - authorization

There are varying levels of data that a given user may have access to. I want to configure an endpoint so that last time the user supplied their credentials defines the level of authorization they have.
e.g.:
> 1 hour = level 1
< 1 hour > 10 minutes = level 2
< 10 minutes = level 3
I looked at the time-based policy but that does not appear to do what I want. I prefer to leverage keycloak to do this rather than hack up the client to derive these levels itself. The user should be able to request a resource, and the credentials they access that resource with define presumably the access-level (role does not appear to be appropriate for this case), which defines what they have permission to read vs. what would be empty. I looked at the custom authenticator, but that seems only for authentication as opposed to authorization. Like a dynamic time-based policy.
Is this feasible via keycloak? And is it a server feature? How can I configure something that changes with time?

This purely seems like a Server feature and you've to program it internally based on the keycloak access token expiration time.
Keycloak's Time based policy covers the authorization of a user under certain period of time (A user can access app/api/webpage only in the period of time for which time based policy has been implemented, a user accessing the feature before or after time-based policy's mentioned time can not access it). it doesn't cover the hierarchical authorization level that you require.
The only solution i can find to your problem is JavaScript-Based Policy , though you still need to define the rules programmatically as defined in documentation:
You can use this type of policy to define conditions for your permissions using JavaScript. It is one of the rule-based policy types supported by Keycloak, and provides flexibility to write any policy based on the Evaluation API.
Here you can read in details regarding Javascript-based policies:
https://wjw465150.gitbooks.io/keycloak-documentation/content/authorization_services/topics/policy/js-policy.html
So, keycloak doesn't provide any solution for your problem out of the box, you've to do it programmatically inside your Server or through Javascript-based policies

Related

Is there a way to override the exp property on access tokens in Amazon Cognito?

I have a requirement to be able to specify session timeouts on a per user basis. (So that it may be a different value for each user) It seems natural to use the 'exp' property on the access token to accomplish this, (as that it's purpose in the oauth spec), but cognito seems to ignore updates to this in the preTokenGeneration trigger. Is there a way to update this on a per user basis? Or do I really need to define some custom attribute that will be checked on the Id token?
Great question. I'm sure you know that since August 2020 Cognito allows you to configure access token expiry time from 5 mins to 1 day. The configuration is per app client. If you were able to split your users across app clients that could be an option (e.g. admins with long sessions login on one page, normal users on another). You could lock the app clients down to certain users using a pre-authentication trigger. That's not a very configurable solution though.
I also wonder what you mean exactly by a session? For example, this would typically mean one of two things. Either your session expires and you have to login again after a fixed length of time (e.g. AWS is 24 hours). Or if you are idle for a certain amount of time (say 30 mins) your session is ended. Could you elaborate on your requirement a bit?

Is the appropriate way to fetch user roles/permissions/information from an ID Token or an API endpoint (or other)?

When creating an Angular web application that also has a backend API, I feel like there are a few different options when it comes to getting User Info such as roles/permissions/display name/email/etc.
We can use an ID Token to store user claims like this. That token can be put into local storage or a cookie and the Angular app can read it and render the UI/guard against unauthorized route navigation/etc as soon as the app spins up (since the ID token is available right then and there).
We can NOT use an ID Token for this information at all and instead have an API endpoint that we have to call every page re-load to fetch this data. The server would decode our access token/ID token and return the data in JSON format.
Lastly, there could be some hybrid solution where basic User Info like names/emails are stored int he ID token and available right away, but user permissions (which could be a larger payload and maybe not wanted in a token that should be small) could be fetched via an API
Is there maybe a 4th option I didn't think about?
I haven't been able to find many conventions around which of these options is the best. I like the ID token option as it requires no "blocking" of the UI until the API request is done making the page load that much faster, but I'm not sure if that goes against other conventions.
All your approaches rely on a permissions-based system where you would have been granted permissions upon login. These are sometimes referred to as birth rights since they are typically given when the user is created or whenever their permission sets change. The typical way to carry birth rights around is to have them as scopes / assertions inside an identity token (e.g. OAUth 2.0) that you pass along from service to service.
You can also have your applications retrieve additional permissions / roles / entitlements from a backend store (a database for instance) based on the user ID so that you know what your user can or cannot do.
So far this is essentially role-based access control / permissions-based access control.
The main challenge with that approach is role explosion / permissions explosion as well as token bloat (too many permissions in the token) and administration pains - you have to assign roles and permissions to users all the time. You have to deprovision. It becomes a management nightmare and a risk you may have the wrong permissions set for users. You then need to think about identity and access governance as well as recertification. Heavy.
What's the alternative?
You definitely need some roles - yes - but they should be kept to a minimum - essentially the business roles you need in your apps e.g. a doctor, a nurse, a non-medical staff rather than doctor_hospital1_unitA.
You should then express your authorization as plain-old English policies using any number of attributes - not just user attributes but also contextual information (time, location), resource information (what type of object, who owns it, where is it? How sensitive is it?), and action information (view, edit, delete...).
Sample Policies
A doctor can view a medical record if they are assigned to the patient the medical record belongs to
A nurse can view a medical record if the medical record is in the same unit as the nurse
A non-medical staff can view the financial section of a medical record but not the medical section.
Attribute-Based Access Control
Following this approach is called attribute-based access control (abac). In ABAC, you clearly decouple your app from the authorization process. Authorization is expressed as policies rather than code which makes it easier to:
update
audit
review
How to implement?
You have several options to implement ABAC (from open-source to commercial). You can go down the XACML (xacml) path, the ALFA alfa path, or others. They all have similar architectures with:
the notion of a policy decision point (PDP): a service that evaluates the authorization requests against the set of policies you defined and produce decisions (Permit / Deny) that can be enriched with additional information e.g. order to do two-factor Authentication.
the notion of a policy enforcement point (PEP): an interceptor that sits in front of or inside your API that will send an authorization request to the PDP.
I've written about the architecture more in detail in this SO post.
ALFA Example
In ALFA, a sample policy would look like:
policyset viewMedicalRecord{
target clause object == "medical record" and action == "view"
apply firstApplicable
policy allowDoctors{
target clause role == "doctor"
apply firstApplicable
rule allowAssignedPatient{
permit
condition patient.assignedDoctor == user.name
}
}
}

Grails 3 and Spring Security - authenticate user in filter

I'm developing a Grails 3 web-app powered with Spring Security plugin, which already makes large use of #Secured annotations to protect controllers and actions according to the privileges of single logged-in users.
The login is currently managed via the usual username/password pair.
Now a new requirement came up, involving a custom request header, having as value a sort of 'authorization token':
this token identifies a group of users (let's call it team)
if this token is recognized as valid, matching against DB, then the whole application should behave as a predefined user (let's call it John, part of the team) was logged-in. In this sense it should act as a pre-authentication. This user will have his own roles, so the application will respond accordingly, as if John would had logged in with his own username/password.
if the token is not recognized, 401 status must be returned.
if the token is not passed, the application must have its current behavior, to the token management should be considered optional must not impact the current implementation at all.
I considered defining a custom filter (I also took a look at this post, which however has different requirements), but I cannot even determine:
the feasibility of this task
whether or not filters are the best approach (but I guess so as Interceptors are triggered too late, and I need some additional logic to be evaluated before Spring Security comes into play)
possibly, the best filter to extend
So any suggestion is welcome! Thanks in advance
Not an expert on this, but I would implement a custom UserDetailsService and set the authorities based on the token condition. You might also be able to do it in an AuthenticationSuccessListener.

Rest API design, storing access tokens

I'm trying to wrap my head around restful API design on a bigger scale than one simple installation.
My setup would look something like his:
The question is, after a user has been authorized to do requests they get the access token. Should EVERY following request first go to the proxy, then to the auth server to check the token and finally get the data from the resource server?
Considering you need somewhere to store the users permissions/roles on what URIs he is allowed to use.
I was thinking if you move the tokens and the permission/roles to the rest proxy. Stored in a memory cache like Redis? And when a permission/role is updated on the auth server, it pushes those changes to the proxy. The proxy would not need to make additional calls to the auth server every single time reducing it to just 1 call to the resource server. Or maybe this is how everyone does it, two internal calls every request?
It is not a great idea to authenticate the token on every request. Instead , save the token in some fashion either in Redis or in a map on your resource server whose expiry time can be set in synch with the token expiry time.
Using Redis you can store these tokens along with the role against a single key say userId and set token's expiration time(by setting the expiry time of a key) .In this way once the token expires the calls will automatically be redirected to the authentication server on its own.
User roles and permissions should be saved on the resource server either as a separate set in Redis for maintaining permissions list to check against the user role which you will pick from Redis again (or depending on how you rest API facilitates setting permissions on resources as certain Rest API facilitators have inbuilt APIs for restricting resources via annotations). This permission list can be updated as and when modified.

ADFS 2.0 - using claim rules to find out when password expires

I need ADFS 2.0 to tell my relying party application when current user's password will expire. Basically, I need to extract all the data from AD, using ADFS claim rules, to repeat logic of this article: http://blogs.msdn.com/b/adpowershell/archive/2010/08/09/9970198.aspx
I can access user-level AD attribute "Pwd-Last-Set" without problems (other than changed value caching for around 20 minutes), but:
I can not access domain-level attributes (like Max-Pwd-Age) from claim rules. How can I do that?
I can not find appropriate attributes for some of the data, like DomainMode.
May be there is some ready solution to this problem, which my googling skills where too weak to find?
You can only access AD attributes that pertain to the logged-in user.
For this kind of thing, I would suggest writing a custom attribute store which returns the info. you require.