Client Specific Role Based Authentication

Keycloak: Role based client log-in access restriction for users

The solution proposed by @Stuck is a great start, but it has a significant flaw: When the user has already authenticated, e.g. via the standard flow of another client that did not require the role, the password form flow will never be triggered. Consequently, the user will be logged in via the cookie flow without ever checking for the role.

In other words: If there are other clients (such as the account console) that do not require the role, anyone can bypass the role check.

To fix this there needs to be an additional flow layer that includes all authentication executions, that is followed by the authorization step (no matter what authentication flow was used). The final result will look like this:

Sample Image

Client-side JWT role-based authorization

As you noted, the client-side code can be tampered with and so it is not a safe place for logic that restricts the user's access.

Assuming that the features of the dashboard are actually capabilities provided by an API (e.g. viewing data retrieved through a GET request, or manipulating data through a POST, PUT, DELETE request), you could protect those API endpoints instead. So even if a malicious user tampered with the client-side code, they would not be getting or changing any protected data.

But to your specific question about how to secure the pages in a SPA, there is no such a way. Even if the code is obfuscated, it is still all there for a sophisticated user to dissect and alter arbitrarily.

Add client-specific roles automatically to userdata from IDP on first login with keycloak as an identity broker

In Keycloak's admin console under menu item "Roles" you'll find a "Default Roles" tab. There you can select global roles and/or client specific roles to be assigned automatically to new users.

How to use role based authentication on client side reactjs?

You can just use the following structure inside of your RemittancePage jsx template:

this.props.user.permissions === 'ADMIN' ? <Grid.Column floated='right' width={5}>
<Button primary className={styles.formButton}>Remittance</Button>
<Button primary className={styles.reportButton}>Generate Report + </Button>
</Grid.Column> : null

Assuming you have user passed to props.

Basically, same as in plain JS. Just an inline conditional.

Authorization based on roles

Use 2 guards.

First one to authenticate:

auto-login-all-routes.guard  

Then a custom guard to listen oidcSecurityService.userData$ and check for roles.

Keycloak: How can user be filtered for a specific OIDC client by 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.

Is possible to create a role based application with OAuth2?

OAuth doesn't solve this problem and it is best solved via claims in your API. OAuth should deal with authentication only. My below post may help you to think about the best separation: https://authguidance.com/2017/10/03/api-tokens-claims/

In a nutshell you will have to look up user rights such as roles after the OAuth processing completes.



Related Topics



Leave a reply



Submit