p2-inc / keycloak-orgs

Single realm, multi-tenancy for SaaS apps
Other
362 stars 65 forks source link

[Discussion] Organization tiering (permissions) #148

Open GME-O opened 6 months ago

GME-O commented 6 months ago

Hi

I'm putting this question here to have some feedback.

We have a SaaS solution currently based on Keycloak and we are looking to move toward multi-tenancy with Organizations where some users can self-manage themselves (admin of the organization can invite users to the organization). This extension looks interesting (did some test on https://github.com/p2-inc/phasetwo-containers) and it answer our problem regarding organizations.

However, in our case we want to apply a "tier" (Freemium, Premium, etc) on the Organization (which is then inherited by users of the organization) and an user can belong to multiple Organizations. So we have:

I there a way to achieve that ?

I noticed that we can't assign realm roles on an Organization. But we can assign attributes on the organization. And we could leverage "user attributes" to keep track of the "active-organization-id". So I had in mind to setup a custom JS based policy which:

  1. validate token.
  2. decode token.
  3. verify that this active organization is in the list of the organizations the user belongs to.
  4. leverage Organizations API to GET attributes of this active organization.
  5. validate feature access based on tiering of the active organization.

Also we are looking to move this check step on an API Gateway, so that's something which could be done outside keycloak custom policy. I would be interested to have some ideas or feedbacks on how we could set this up with keycloak-orgs.

Thanks in advance Best regards

xgp commented 6 months ago

For your tiering question, it seems like something you probably want to keep in application state rather than in the Organization.

We haven't really had requests to get this working with Keycloak Authorization Services. However, what you suggest for your JS policy sounds reasonable.

There's both a mapper for Organization Roles and Organization Attributes, so you could have everything in the token without calling the API. We are aware of customers mapping those to the token and then doing custom authorization in their own API gateway (or in the case of AWS, using an Lambda Authorizer).

GME-O commented 6 months ago

First of all, thanks,

So you would recommend to keep the "tier" and "organization_tier" link outside keycloak or keycloak-orgs, like in a micro-service (or nano-service) and leverage this service to assign, verify or remove tiering of an Organizations ? (And of course query this API to retrieve tiering & verify it).

Would that be something you might be interested to have ? (proposition to contribute on that maybe)

We are indeed looking at Lambda Authorizer for our API Gateway. On the "Organization Roles" I was mainly thinking of realm-role not accessible to Organization where we could define tiering vs "Organization Role" which is what you can create in the organization and assign to user you invite.

xgp commented 6 months ago

I don't have a concrete idea of how you would implement it, but I just don't see a strong case for including it here.

We made the decision pretty explicitly not to mix Realm Roles with Organization Roles. In general, if that's something that you need to do, this probably isn't the best extension for it.

MGLL commented 6 months ago

Hi,

I have noticed that an user with manage-organization role can modify the organization attributes through the REST API (PUT .../realms/testing/orgs/ID).

Is there a plan to make some attributes read-only to users but manageable to keycloak admin ? Similar to this: https://www.keycloak.org/docs/latest/server_admin/#read_only_user_attributes

(Also tried to see if spi-user-profile-declarative-user-profile-read-only-attributes would also restrict for attributes on organization but it's not working)

Best regards

xgp commented 6 months ago

Users with the realm-management Client role manage-organizations have complete control over all aspects of the Organization.

Users with the manage-organizations Organization role have control over the settings and attributes of an Organization.

There is no plan to make Organization attributes read-only, or make the management of them subject to some fine-grained permissions.

The SPI you mentioned pertains to the Keycloak declarative user profile functionality, and has nothing to do with Organization attributes.

MGLL commented 6 months ago

Thanks a lot for all your answers.

I'm looking to implement something like "organization read-only attributes" similar to declarative user profile for "organization meta-data" (I'm actively looking at Keycloak codebase around the mechanism for user read-only attributes as inspiration). The idea is to have attributes restricted to the realm admin / manager and users in organization can't modify so we can keep track of specific info.

I had in mind to create a separate SPI, but actually I would need to influence the OrganizationResource (updateOrg) flow to validate attribute change. I have read your license, and I will clearly put in a NOTICE.md my modification. But let me know, if you would like to have this, I will try to do a proper PR.

But I'm struggling a bit with something, and I would be really grateful if you could help me. I have read:

I'm able to remote debug Keycloak based on quarkus with IDEA (going through code with breakpoints), but it's not clear how I could "live code" or "debug" external SPI like keycloak-orgs.

I had in mind to build the modified keycloak-orgs and put it in the quarkus/dist/src/main/content/providers, run "kc.sh build" in the bin folder and then run again ../mvnw -f server/pom.xml -Dsuspend=true compile quarkus:dev -Dquarkus.args="start-dev". But, by doing that, would I be able to set breakpoints in keycloak-orgs for debugging? I have a but difficulties to visualize how it works as keycloak-orgs code won't be in the same location as keycloak code and I will have my remote debugger in the keycloak repo window.

I guess you already have gone through all that and you are able to do "live code" or "live debug" your SPI with keycloak, could you indicate me how I can do it?

Again, I would be really grateful. Thanks again for your support!

MGLL commented 6 months ago

Hello @xgp

So I managed to extend organization update flow with attributes validation based on Keycloak declarative profile (partial adaptation, as I focused on attribute update process and don't support configuration through API).

You can have a look here for modificiations:

Also added & modified code is on this branch:

Added specific tests there:

Let me know if you are interested. (Tried to do a separate SPI, but as I have to influence updateOrg resource flow, I basically need to copy/paste & override full Organization* resources. Also, I will need to override Admin UI to leverage new endpoint for Platform Admin update flow)

Best regards

MGLL commented 4 months ago

Some update on this topic. I will much likely work on a separate extension (the name will probably be "keycloak-orgs-subscription" (following licensing according to your license)).

The topic is to be able to assign "realm roles" to organization which are inherited by users (similar to assigning roles to a group in Keycloak).

The Use Case:

This way, we could also use it in the Authorization setup (role based policy).

Plan: Base scope

Bigger scope Probably extend it with more logic like timed subscription (add timestamp to make subscription expires)

xgp commented 4 months ago

Thanks for the update on this. Also happy to look at this as a PR, depending on the final feature set you decide.

MGLL commented 4 months ago

@xgp Here is the "requirements" I will use, let me know for any adjustments (naming or anything) before I start working on it or provide the PR. I will probably start working on this during this week.


Objective:

I'm able to assign one or more Realm Roles to an Organization and the members of the organization inherit the roles in the tokens through a mapper. Similar to the Group in Keycloak.

On top of that, I'm able to define an expiration date to those roles assignations. This expiration date is optional (so an assignation/tier could never expire).

Use Case

As a SaaS Platform with tiered context (Freemium, Premium, etc), I would like to leverage the Keycloak Realm Roles to define and assign those tiers (as my platform already use those realm roles).

Then, it could be used in the Authorization system of Keycloak if necessary (or any own or 3rd party system).

Out of Scope

Client specific roles.
Could be added later.

Implementation Details

Database:

Create a new table: organization_role_mapping Columns:

CRUD:

Implementation will be similar to the Keycloak approach.

Example body:

[
    {
        "id": "ROLE-ID",
        "name": "ROLE-NAME",
        "description": "DESCRIPTION",
        "composite": false,
        "clientRole": false,
        "containerId": "REALM-NAME",
        "expirationDate": "yyyy-mm-dd hh:mm:ss"
    }
]

Expected response status: 204.

Example body:

[
    {
        "id": "ROLE-ID",
        "name": "ROLE-NAME"
    }
]

Expected response status: 204.

Additional CRUD (optional)

Mappers:

At least one mapper will be added:

Business Logic:

MGLL commented 1 month ago

@xgp hi, I will start to work a bit on that as it start to be an important need. I have a question regarding entity and the keycloak org implementation:

(I will start with p2_organization_role_mapping locally while waiting your feedback)

xgp commented 1 month ago

@MGLL Thanks for the clarification request. We haven't yet, but we plan to migrate tables in our extensions to the prefix EXT_P2_, so in your example, a table name would be EXT_P2_ORGANIZATION_ROLE_MAPPING. If you start working on this now, I would request to please use this prefix.