Go get access to Users Resources, Policies and Permissions in Keycloak 7.x - keycloak

I am evaluating Keycloak 7.X to be used in our applications consist of approximately twelve microservices (Spring Boot) and four Angular 6.x applications. I plan to use Keycloak adapters for Angular applications as well as Spring Boot instead of OAuth 2.0 for SpringBoot. My proof of concept must demonstrate the following use cases.
(1) Single Sign-On.
(2) Role-Based access control
(3) Policy and Permission- e.g. a user with role "Supervisor" should be able to access the salary of all employees of the organization. However, he/she could give raise to only those employees who work at the same location of the supervisor. In other words, there will an attribute "location" assoicated with each user. Even if the role of the user is "Supervisor", the permssion must consider the attribute "location" to determine access to the resource.
I am planning to use JWT. The JWT will contain the list of permissions and the individual microservice will determine using the combination of "location" and "permission".
Unfortunately, I am unable to configure the client in Keycloak to assign policies and Permissions nor could I find any example on internet.

To use policies and permissions your applications should implement User-Manager Access 2.0 protocol. Read User-Managed Access documentation page for example flow.
I am planning to use JWT. The JWT will contain the list of permissions and the individual microservice will determine using the combination of "location" and "permission".
If the logic behind access definition is located in microservices then you don't need policies and permissions. You can just define roles (e.g. supervisor) and attributes (e.g. location) on Keycloak side and set them to be included in access token (JWT).

Related

Looking for a solution to API Identity and Authorization Management

I've become very frustrated with the landscape of API creation and authentication/authorization. I would like to find a solution that doesn't require lots of additional complexity (creating new services myself, standing up and maintaining an instance of Keycloak, and so forth) – ideally a managed service (like Auth0 ... but Auth0 doesn't meet my requirements) – that centralizes the management of users and permissions, and allows me to add attributes to users.
Some context:
Suppose you have an API that has a variety of routes:
GET /customers
GET/POST/DELETE /customers/{id}
GET /customers/{id}/orders
GET/POST/DELETE /customers/{id}/orders
You can imagine that you have a case where you have users that have read-only access, and others that can read, create and delete customers and orders. You can also imagine that you may have the need to programmatically access the API, via a service account or access token (such as with Github PATs).
This could be set up with FastAPI or some other framework, such that when a route is accessed it checks that the user, or the access token – or in essence the credentials being used to access the API – has the necessary permissions.
What would be ideal, then, is to have a system that allows me to create users, and from that system the users can – provided they have the permissions in the identity management system to do so – create machine credentials (again, like with Github PATs, but perhaps something that can generate a JWT for consistency of credentials). Users can be added to groups that provide them with roles, and therefore permissions, or they can be assigned roles directly. Ultimately, it's a system that:
Allows user creation and management
Allows users to be grouped, groups can have roles that cascade to users
Allows users to be assigned to roles directly
Allow users to create credentials for programmatic access
Does not make management of users, roles, and so forth, onerous
Allows services (such as a REST API) using these identities for authentication to get the permissions and other information associated with credentials. In the case of other information, this could be included as claims in a JWT – this would require a system that allows claims to be added programmatically to the ID token/JWT.
In my experience, the closest thing to this is Keycloak. Unfortunately, it is a decent amount of work to maintain a Keycloak instance. Still, Keycloak does not provide number 4 in the list above. Does anyone else have experience addressing this issue? I would like to avoid have to manage users and permissions myself, because I have limited resources and that isn't my area of expertise.
Similar solutions:
Keycloak – hits most of the points, except for allowing users to create machine credentials. I'd like to avoid having to set up and maintain a Keycloak instance. Not sure if I can add attributes (claims or something else) to a machine/service account JWT.
Auth0 – Hits some of these, but doesn't allow me to add attributes to machine/service account JWTs, although it will add permissions to them (but that isn't enough).

REST best practice cloud

I have a set of REST services on IBM cloud. Ingress is integrated with Appid for authentication. Ingress adds the token id & access id to the authorization header.
Now on the API side (springboot) do I need to validate the user again on every request ? will this be redundant ? If no, which appid api can be used to authorize the user. Any reference to similar example
Already gone through the example on IBM cloud site. One is about ingress & appid integration, but does not talk about REST services layer how to handle the authorization tokens there.
Another is only about spring and Appid, (does not talk about ingress)
Authentication versus Authorization is where the line is drawn. The Ingress integration with App ID does the authentication for you and your REST service (application) can be assured that the request if it comes through is authenticated. Now just because the user exists in your system and has provided the right credential does not mean that he is allowed to access the service he is trying to access or view the data he's trying to view which is where the authorization comes into play - the REST service can use the authorization tokens to figure out if the user has the right access to use the service.
Here's a good article that talks about the use of Roles - https://cloud.ibm.com/docs/services/appid?topic=appid-tutorial-roles
In any application - REST, UI or otherwise - multiple levels of security may be necessary depending on your requirements. Authentication verifies the user is who they claim to be, authorization checks what permissions the user might have. Each application might have its own rules for what the user can access.
In your case, you have authenticated the user facilitated via Ingress with AppID, which supplies a user principal (identity) to your application. However, should every user have access to all of your application endpoints? If the answer is no, then you will need an authorization model, for which a common approach is RBAC (role-based access control).
Even without an RBAC requirement, it is still wise the validate the user's principal in some form for each request. For example, perhaps the user belongs to a domain that you might not expect, or should no longer have access to this specific REST application. Your application server may have features that assist you with a simple authorization feature, or you can custom build your own validation.
At present, as the identity provider, AppID can be the store of the user's role for RBAC. However your application or application server must decide what to do with that role.
If you are looking for a Cloud-centric authorization solution, you may want to consider exploring Istio's authorization policies:
https://istio.io/docs/concepts/security/#authorization-policy
https://cloud.ibm.com/docs/containers?topic=containers-istio

Exposing Cognito Protected AWSGateway APIs to clients

Use-case:
We have a few AWSGateway APIs which our clients can use to do somethings in the backend. These APIs are Cognito protected. Currently our clients are using this APIS through an android app which was built using Cognito Mobile SDKs.
Now we are trying to expose these APIs to our clients to be integrated into their internal workflows.
I was trying to find what is the best way to do this. Currently I am not able to find any resources on how to do this.
I have seem the server side user of AWS Cognito but I don't think that is what we want to do here.
Thanks.
To answer your question correctly we need more information.
Can the internal workflows be configured to use REST Services?
What authentication processes does the internal workflows support?
SDK or no SDK
You can access the webservices in API Gateway via a generated SDK or your own code.
Instructions to generate an SDK from the API Gateway Console are found here.
To invoke the webservice with authentication can be done in four ways IAM, API Keys, Cognito, custom authoriser. I am going to mention the first three.
IAM
Step 1, create a user in IAM with an access key and secret key.
Step 2, is too setup a role to access the API using IAM. Go to
IAM, select roles, create a role, and grant it access to your
API Gateway functions. Which would look something like this:
Sample IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::account-id:user/Alice",
"account-id"
]
},
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-api:region:account-id:api-id/stage/GET/pets"
]
}
]
}
allocate this role to the user you created. Policy examples are available here.. For more authentication options that include local certificates etc look here.
Step 3, call the API using the AWS Secret and Key SDK.
API Keys
If you add keys to your APIs the mobile app will fail as it does not have these keys. It would be best to deploy a different version of your APIs that could wrap the existing ones, could provide additional functionality specific to the workflow. To find out how to do this follow this link.
The advantage of API keys are that you can throttle access to your API Gateway functions, remove the keys at will, recycle them etc.
Cognito - Federated Users
Your mobile users are actually authenticating using federated users. However, one of the federated user channels happens to be cognito. You can add more, OpenAuth, Google, Facebook, SAML, etc, here you could add the Authentication type used by your client. A user would then use their username and password, to authenticate to the clients security provider, those credentials are then passed through to the API via federated users, and therefore federated users must be setup to use the same authentication mechanism as your client. See the following blog post
For this solution we have multiple options. 1. Pass the user credentials through to the API with federated users, this assumes the users interface calls the webservice but as you mentioned it is workflow, and I assume the user does not access the service directly as they do with the mobile application. i.e. services are called by a machine as a background process on a server. Which means this solution will not work. Option 2. is to create a new user, in cognito for the client. This is the same as accessing the service via the mobile app. To do this needs a little work extra work on the client as you need to retrieve the temporary access tokens.
Step 1. Use the SDK, or code the interface to the API on your own.
Step 2. Generate a user in Cognito for the backend system to use.
Step 3. Use the cognito user to obtain access tokens
Step 4. Use the access tokens to access the webservice in API
gateway.
Suggested solution
Create a second version of your API as a wrapper or extension to your mobile API and use API Keys as described above. Why?
Can throttle access to the APIs
A different version means you can extend it and add additional functionality specific to workflow
Easiest to implement as there is no key exchange, such updates to
the request header.
EDIT: My suggestion of solution 2 is incorrect. AWS Documentation says the following To include API methods in a usage plan, you must configure individual API methods to require an API key. For user authentication and authorization, don't use API keys. Use an IAM role, a Lambda authorizer, or an Amazon Cognito user pool.
AWS Also says the following is available for controlled access
Resource policies let you create resource-based policies to allow or deny access to your APIs and methods from specified source IP
addresses or VPC endpoints.
Standard AWS IAM roles and policies offer flexible and robust access controls that can be applied to an entire API or individual
methods.
Cross-origin resource sharing (CORS) lets you control how your API responds to cross-domain resource requests.
Lambda authorizers are Lambda functions that control access to your API methods using bearer token authentication as well as
information described by headers, paths, query strings, stage
variables, or context variables request parameters.
Amazon Cognito user pools let you create customizable authentication and authorization solutions.
Client-side SSL certificates can be used to verify that HTTP requests to your backend system are from API Gateway.
Usage plans let you provide API keys to your customers — and then track and limit usage of your API stages and methods for each API
key.
Not all the approaches above are intended for authorisation, for example CORS actually protects the user from cross site scripting, and as seen API Keys are only for usage plans. Resource policies just further secure the API by limiting access to IP Addresses, thus your only options really are IAM Roles as described in option 1, and federated users as described in option 3 or your own custom lambda authorize, if you are using Lambda, or your own authorizer if you are using something other than lambda wrapped with API Gateway.
I guess it will be service to service or (Server to Server) communication, for this terminology used is Oauth Standard is client_credentials grant type.
Please refer the documentation for getting token
Once the token is acquired, you need to pass this token either Authorization or API Gateway Custom Header for AWS Cognito.
You can use API Tokens alone for authorization (unless this has been removed recently)
I have used them on multiple applications.
This is not recommended for Authentication -- but it is application specific if they are sufficient for authorization
They have been supplemented by more secure methods at the expense of significant complication for both client and server.
API Tokens have the advantage of ease of use for issuer, client and server as they do not require complex signing or protocols -- however they are not as fundamentally secure as they may be reused and generally do not expire as quickly. Otherwise they are equivalent to bearer tokens.
Security is very context dependant -- consider these question:
what exactly are you protecting against (providing security for) ? What is the risk and cost of a security breach ? What is the cost/effort to implement and use it?
Many security 'holes' are not in the authentication protocol handling itself but rather in how data is managed 'outside the box' -- No security is perfect, meaning aiming for perfect security has unbounded cost with decreasing effectiveness. Generally, it is recommended to balance the risk and cost of potential loss vs cost to implement and maintain.
You can have a 'highly secure' API but also have a high risk of breach and data loss due to handling before and after passing through the protected gateway. There are many reasonable cases where instead of focusing on securing the 'front door' with bank vaults and armoured trucks, instead securing the data handling such that no data that is a significant security risk passes through the front door.
AWS Provides a range of technical features -- but it is ultimately up to each customer to implement them appropriate for their use. API Keys do have a range of appropriate use cases, particularly in server-to-server communications, especially where personal identity (and PI data) is not involved, or where the API involves mainly services instead of data (e.g say a image thumbnail API that stores no state and provides no access to data). When backed by use of HTTPS/SSL and possibly other security factors such as account passphrases, IP range whitelists, and a general policy of least-access.
Don't underestimate the "Sticky Note" factor. If you make secure access too painful to your users they will find a way to make it less painful, but less secure then simpler measures which they would not have had an incentive to circumvent.

Keycloak - Limit users access per client/application

I've just setup my first Keycloak server to offer SSO between two applications. These are not Java applications, and one is connected with SAML-2 and the other with OpenID Connect.
So in Keycloak I have Realm-1, and then Client-1(application1) and Client-2(application2) and user-1 and user-2.
Now I want user-1 to only be allowed access to Client-1, and user-2 to be allowed access to both Client-1 and Client-2. Should be simple enough.
I have tried to read up on Roles and Authorization, but I find the documentation(or maybe just the topic) very confusing. I have been playing around with it with no success. I was expecting an interface to just map a group to a Client, and restrict access to the Clients by adding/removing users from groups.
If you are using SAML:
Create a new role in Keycloak.
Assign this role to the group.
Create new authentication script in Keycloak. Configure which role is allowed upon login (e.g. user.hasRole(realm.getRole("yourRoleName")) ).
In client setting, under "Authentication Flow overrides" choose the created authentication(from step 3).
If you are using openid, look at the comment in this thread

SAML: group memberships

I was told that it is possible to give information about group membership during a SAML authentication request. We have to connect to an application that does use SAML (we are at the end that is creating the SAML answer XML). Authenticating a user works fine but I can't find a way to specify a "member of" or similar attribute.
Can you explain to me how to pass group memberships in SAML during authentication or have an example ?
I know there is a possibility to take care of authorization in SAML at a socalled Policy Decision Point. But this would mean that a SAML flow would happen for each or some (if batched) entities we want to check authorization for.
Let me give you an example what we are trying to do. This example is made up but shows the problem we want to solve.
Let's assume you have a hard drive with lots of directories and files on it. We use SAML to authenticate the person that tries to access that drive. Members of the group "admin" are allowed to read and write and members of group "user" are only given read permission.
Because of this we want to send the group memberships of a user when he or she authenticates. Because otherwise it would mean that the application has to check for every file if the user is in the necessary group. If it was clear from the beginning (after authentication took place) that someone is a member of a specific group the application can cache that in memory.
As with most things in SAML, this depends on the identity provider as well as the application.
Many identity providers have access control to allow or deny specific users or groups to access an application. Sign-on is then denied by the IdP after authentication based on the ID of the application (from the SAML request) and access control configured in the IdP. If you just want to control who has access to the application, then this is all you need, and most, if not all, identity providers should have you covered.
Sometimes you also want different users or groups to have different permissions inside the application, or you want memberships in certain groups on the IdP to be mapped to membership in groups inside the app's own user and group database (or other application-specific group-like concepts). There is no standard for this, but some identity providers allow the definition of attribute mapping rules based on group membership. For example, in ADFS, you can create a claim rule that sets a specific SAML attribute to a specific value if and only if the user is a member of a specific group in AD. You would then set up such a rule and set a SAML attribute that your application understands to a value it understands.
Alternatively, if an application supports configuration of multiple IdPs, then you can configure one app / IdP mapping per group, and for each group add an attribute mapping rule with a hard-coded group name in an attribute that your application understands.