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:
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
Most Efficient Way to Compare Two Ienumerables (Or Lists) in Linq
Pass Variable in Json String in C#
How to Disable Uwp App Suspension
How to Set a Cookie on Httpclient'S Httprequestmessage
Itextsharp Pdfptable How to Make a Border Around Entire Table
Generate C# Class from SQL Server Table Without Store Procedure
How to Rename Keys Within a Json File
How to Generate Database Tables from C# Classes
Change Datagrid Cell Colour Based on Values
How to Remove Time Portion of Date in C# in Datetime Object Only
How to Insert 10 Million Records in the Shortest Time Possible
How to Upload File to Server With Http Post Multipart/Form-Data
System.Collections.Generic.List Does Not Contain a Definition for 'Select'
Getting the Latest File Modified from Azure Blob
C# Download Big File from Server With Less Memory Consumption
Discord.Net C# 1.0.2 How to Send Messages to Specific Channels