Blocking Unauthorized Login
This is not really the way apps are intended to work. Technically, an app should separate authentication and authorization. A user logs in. The client checks what their authorizations are. The client grants the limited access.
However, in practice, not all apps are built like this. This creates the problem, how do we limit authorization to a client, which only checks if a user is logged in?
Here are some related topics/issues:
- https://github.com/keycloak/keycloak/issues/12880
- https://github.com/sventorben/keycloak-restrict-client-auth?tab=readme-ov-file
- https://github.com/keycloak/keycloak/discussions/29940
- https://keycloak.discourse.group/t/allow-users-only-for-specific-clients-in-a-given-realm/2384
I think the best way of handling this is to:
- limit the number of clients that work this way
- this is not a standard or recommended approach, and is easily configured incorrectly
- follow the ChatGPT solution outlined below, which creates a custom flow
- block all other types of flows for this client
- this is really important to avoid security issues
Prompt:
In KeyCloak, there are many authentication and authorization functions. Technically, these should be completely independent of each other, and a client should authenticate a user, and then decide what the user can do based off of authorization.
The problem is that not all clients are built this way, and may just allow full access to authenticated users. This is unfortunate, but sometimes the clients are valuable or necessary anyway.
In KeyCloak, how can I configure SSO so that it blocks authentication to a client, given some authorization condition is not met? Specifically, I want to only allow users from a specific group to be allowed to authenticate.
ChatGPT:
Here’s the approach I ended up with in Keycloak. The key idea is that you must stop the user in the authentication phase (i.e. in the browser flow) rather than waiting until after they’ve already gotten a token. You can do this entirely with built-in functionality—no custom coding required.
Copy the Built-In “Browser” Flow
- Go to Authentication → Flows
- Hover over the Browser flow, click on the dropdown on the right, and choose Copy.
- Give it a distinct name, e.g.
browser-only-group-X.Create a “Group Membership” Condition
We’re going to make the flow refuse to continue unless the user is in Group X.
- In your new flow, click Add execution
- Under Provider, choose “Condition – User in group”
- Once it’s added, click its Actions → Config
- In Group, type the exact name (or path) of your group, e.g.
/X- Save → back to the flow
Wire the Condition into the Flow
You need to tell the flow what to do if the user is not in your group.
- Find the “Condition – User in group” execution you just added
- Click Actions → Add flow
- Select Flow type “Alternative” (this automatically creates a branch if the condition fails)
- Call it e.g.
reject-if-not-in-group- In that newly created sub-flow, add a single execution:
– Provider: “Error”
– Alias: something like “User not in Group X”
– Make sure it’s REQUIREDThe result is:
- If the user is in Group X, the main Browser flow continues as normal.
- If the user is not in Group X, we jump into
reject-if-not-in-groupand immediately throw an Error screen.Assign Your Custom Flow on the Client
- Go to Clients → (your client) → Authentication Flow Overrides
- Under Browser Flow, pick the new flow you made:
browser-only-group-X- Save
From now on, whenever anybody hits that client’s login endpoint…
• If they’re in Group X → they proceed through the normal Browser flow and get a token
• If they’re not in Group X → they land on your “User not in Group X” error page and never complete the loginThat gives you exactly what you want: “only users from a specific group can ever finish authentication at this particular client.”
No comments to display
No comments to display