asp.net role based authorization with wildcard names - asp.net-web-api

I am trying to implement the role based authorization in .net core web api. I don't have the fixed role names. I have to validate with the common prefix only. For example, in JWT claim the role will be as below.
"roles": [
"Approver#UK",
"Approver#US",
"Approver#DE",
......
]
If the user has approver prefix in the claim, i would allow them to access the api.
I don't want to add "Approver" as a separate role and i cannot put all the roles in the attribute. I am trying the below syntax, but no luck.
[Authorize(Roles = "Approver#*")]
How can i verify the role by prefix or kind of like condition, rather than the full role name.

The example can be found under for dynamic authorization policies.
https://github.com/aspnet/AuthSamples/tree/master/samples/CustomPolicyProvider

Related

How to access user specific resources in webapi when the access token does not include user info

I have implemented OpenId Connect for authorizing my multi tenant app, I have obtained both the Id Token and the access token. The access token does not contain any claims, but I would like to access user specific resources in the web api.
For example, in order for a user to access a certain resource, 1. They must be a tenant admin and 2, they must have permission for that resource (say a specific job post).
My questions.
Do I send the user permissions to the webapi in the request body/query and the webapi trust those permissions?
Should I use the access token to call the Identity Server to get the user information, then proceed if the user has the permissions?
Any other options?
You can always add the necessary user claims inside the access token, and by doing that, you don't have to pass that information separately. You use ApiScopes and APiResources to control what user claims that goes into the access token.
See my answer here: ApiResource vs ApiScope vs IdentityResource
To complement this answer, I write a blog post that goes into more detail about this topic:
IdentityServer – IdentityResource vs. ApiResource vs. ApiScope

Spring Boot Security registration and logging for website with roles, how to do it?

I have a difficulty in understanding Spring Security and any tutorial I found was not tailored to my needs. So maybe I'll explain what I think and what I want to accomplish.
I want to create a website with Kotlin/Java backend and frontend in React. This website would need to have users with different roles (user, admin).
And (I think) the thing I need is some kind of backend that has 2 endpoints:
register (to create users in database)
login (to, based on username and password, fetch user info and role) - as some kind of token? This returned token would be then used by frontend to display specific options (i.e. do not display "ban user" for regular users) and it also would be sent to backend for checking if the person who requests for specific endpoint really should be able to call this endpoint (i.e. it should be forbidden for regular users to use "ban user" endpoint)
What should I read about, what keywords should I look into to achieve this?
For purely the Spring Boot part of the implementation, the following should do
(/register) Signup/Register endpoint taking all required parameters for your business logic. e.g Username , Password , Full Name as well the roles
(/login) For logging in , you need a token forwarded to the front end, which will then use this token in the header for the session. JWT tokens seems like what you need(sample below). For the other part of your requirement, you can keep the user object (with roles) in the session as well as check user role on the backend in the "ban user" endpoint and process accordingly.
JWT Authentication with Spring Boot
I found a good starting point in the following sample
https://github.com/bezkoder/spring-boot-spring-security-jwt-authentication
For a more complete example
https://www.bezkoder.com/spring-boot-react-jwt-auth/
Credits to
https://www.bezkoder.com/
I have come a cross Youtube Video that covers all the scenarios that your looking for and extra, with Email verification links as well. i hope this will definitely help you
Java Tutorial - Complete User Login and Registration Backend + Email Verification

Keycloak: API to check if user token has roles for a particular resource

I have a keycloak server setup. I am using the token endpoint: http://localhost:8080/auth/realms/demo/protocol/openid-connect/token to authenticate a user and generate a token. This token I understand can be used in subsequent calls to verify if it is a valid user.
However, I am not sure how do I use this to authorize the user? ie verify if this user has the roles to access a resource.
I see that it is possible to configure a resource URI under the client section. But once that is done, I want to be able to read the token and verify if this user has the roles to access this resource.
Right now, this is what I am doing:
I have used spring boot here.
doSomething(String token)
{
1. get token info using: http://localhost:8080/auth/realms/demo/protocol/openid-connect/userinfo
2. from this get the roles the user has
3. Manually check the roles required for the above function. (Right now, this is set in a simple switch statement)
4. If the role obtained from step 2 matches what we get in step 3, go ahead. Else return failure.
}
I want to know if step 3 above can be done in a better way. I know taht you can set a resource in clients from the keycloak console. What I was hoping is we could replace the 4 steps above with something like:
keycloakAPIToAuthorizeToken(token,resource)
which would tell me whether this user has the roles (obtained from token) to access this resource.
Please suggest if this is doable.
Thanks in advance.
Om
There are MANY ways to do this. One of them is to use Keycloak's roles, and assign those roles to users. That way, in your server/api you can check if the user has that role and proceed or reject the call.
Example, in my api project, I have some endpoints that are exclusive for system administrators, so I have a role SystemAdministrators:
and then, if you go to Users, Role Mappings, you can add that role to the users to set as admins:
Then, any api call should include a bearer token (obtained from the Keycloak login), in your code, you can decode this jwt (it will depend what language you are using, I use python so its pretty simple), it will have an element "realm_access" and inside it, a "role" element, example:
"realm_access": {
"roles": [
"offline_access",
"uma_authorization",
"SystemAdministrators"
]
},
If that element contains the role SystemAdministrators, you know is a system administrator.
I found this is the simplest way to do it. You can get fancy and use role attributes to determine individual options inside screens, etc (attributes are key/value pairs so the way I implemented this is, the key is an option name and the value is the permission level, for example: "screen1": "read", "screen2": "write", and so on. For this, you would need to use the keycloak admin api: https://www.keycloak.org/docs-api/6.0/rest-api/index.html#_roles_resource which has many endpoints that can help you.

laravel passport protecting a single route with multiple grant types as an OR statement

Leveraging Laravel Passport ... is there a way to protect one API route with two grant types but as an OR statement and not that both need to pass?
I have been looking for some sort of solution for this but can only think of creating two separate routes - one for the "client credential grant" and the other route for the "password grant" ... which ideally I would like to just have one API route and depending on the grant type you end up using the JSON we spit back changes...
As an example if you look at the docs for the Uber API you can see they protect certain routes with both a server token and OAuth token: Server token or OAuth 2.0 user access token with any valid scope. link: https://developer.uber.com/docs/riders/references/api/v1.2/products-get

How to check caller is part of AD Security group in WebAPI layer?

I have a website (WebApp) from where I make Ajax calls to my WebAPI layer that accepts JWT Bearer Token auth. I have integrated Adal.js into my front end script layer and the config values look like this.
var config = {
instance: "https://login.microsoftonline.com/",
tenant: "tenant.com",
clientId: "CLIENT_ID OF THE PORTAL APP", // Web-Portal app
redirectUri: "http://localhost:8241/",
popUp: true,
cacheLocation: "localStorage" };
The WebApiConfig looks like this:
var webApiConfig = {
resourceId: "CLIENT_ID OF API APP", // Web-API app
resourceBaseAddress: "http://localhost:9020/"
};
It all works fine, I am able to authenticate/authorize and call my webapi via an access token via Implicit oauth flow.
Now I would like to be able to retrieve the User's security group membership values for the logged in user so that at the WebAPI layer, I can make sure the user belongs to a particular security group as part of the authorization logic. So I set the GroupMembershipClaims: "SecurityGroup" in the App's manifest xml in Azure AD (I did this for the WebApi App manifest first, but then also in the WebApp app manifest).
However, looks like GroupMembershipClaims are only included in the idtoken and not the accessToken. And given it is the accessToken that is sent to the WebAPI, I am unable to do this check at that layer. I guess I could make the check at the WebApp layer, but given this WebApi layer will be called from many other frontend apps (which are not owned by me, I am primarily an "API provider"), that is not a secure soln.
So how do I solve this? I guess one way is to use the "on-behalf-of" flow on the WebApi layer to make calls to Graph API to find this out? I am afraid that will require more permissions than available at User scope.
Thanks!
It's a good question.
My immediate first thought was "well you can get them from Graph API", but I see you already thought of that :)
If you want to do that, you can use On-behalf-of like you said, and use this operation on MS Graph API: https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/user_getmembergroups.
You would need these delegated permissions: User.Read and Group.Read.All.
So you would need the permission to read all groups in addition to the basic User.Read.
There are a couple other options.
You can define roles in your API.
I wrote an article on how to do this: Defining permission scopes and roles offered by an app in Azure AD.
So if you define a role like this in the API's manifest:
{
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"displayName": "Administrator",
"id": "179c1dc0-4801-46f3-bc0d-35f059da1415",
"isEnabled": true,
"description": "Administrators can access advanced features.",
"value": "admin"
}
]
}
You'll need to make the id a unique GUID for each role, you can use online generators or PowerShell for that [System.Guid]::NewGuid().
These roles can then be assigned to users, and if you have at least Azure AD Basic, you can assign them to groups.
Roles are included in access tokens, so you can check these quite easily in your API.
The other idea I had was to have the API and front-end use the same registered app in Azure AD.
This way you could pass the Id token to the API instead of an access token, and you'd get the groups.
But since you might have other front-ends too, I doubt this would work for you.

Resources