Adding Permissions to Claims - Microsoft.Identity.Web & B2C - asp.net-core

I'd like to ask for advice or direction to any article/documentation on how to add custom claims to user identity. Project I am working on is using Azure B2C with Microsoft.Identity.Web.
I am searching for a robust way of adding a custom claim during web request in an web app. The claim would contain permissions obtained from an application database. So I also need a way to store that claim between requests, so I don't trip to database on every request.
The model of roles and permissions stored in the database is quite complex and dynamic (managed by admins), thus simple storing custom claim in B2C via graph API is an option.
I was thinking about stepping in with a middleware doing claims transformation:
Is this ok with Microsoft.Identity.Web or is it something that I shouldn't do?
Still not sure how to persist the claim between requests - is there any robust way while using Microsoft.Identity.Web?

If you want to have permissions in the token, and I presume that would be the optimal way, then I'd go with saving those in the user object as a Base64 encoded JSON for example. You can have quite complex structure which AAD B2C would just return in the token for the user. Then you may do what you want with this value in once it hits your API. It's in the token so it's properly signed and you get the token with every request so you don't think about reaching to any database.

Related

User models and Auth0

I am developing an app in Aurelia which has a .net core backend. I have already implemented user Authentication with Auth0 in the frontend.
The problem comes as I am not sure if its good practice to implement a way so that users from auth0 database are linked with my user model in .net core and in my database. When a user registers/logs in I can get the corresponding user model from my database.
Basically I would be using the auth0 database jsut for logging in and my database for the user details.
If it is good practice how should I go around and doing it? Is a 'post user registration' action good? Any help appreciated :)
It is a common approach to let the Authentication Service keep only the minimum amount of data it needs to authenticate a user, and then have additional, business-related data in a separate service. These should be linked upon user registration.
Note, that if that data in the separate service would be used to perform authorization decisions, then the Authorization Server (Auth0 in your case) should be able to read that data when issuing tokens, and relevant information about the user should end up in the signed token in form of claims. This gives you the assurance that this data is not tampered with.
Have a look at this article that my colleague wrote: https://curity.io/resources/learn/integrate-identity-business-data/ as it describes in more detail what you need.

Handling authorization with IdentityServer4

I'm extremely confused on how to use a centralized IDP with both authentication and authorization. The architecture for my project was to be a single web API and one React client. I wanted to keep things structured out into microservices just to try something more modern, but I'm having major issues with the centralized identity, as many others have.
My goal is fairly simple. User logs in, selects a tenant from a list of tenants that they have access to, and then they are redirected to the client with roles and a "tid" or tenant id claim which is just the GUID of the selected company.
The Microsoft prescribed way to add identity in my scenario is IdentityServer, so I started with that. Everything was smooth sailing until I discovered the inner workings of the tokens. While some others have issues adding permissions, the authorization logic in my application is very simple and roles would suffice. While I would initially be fine with roles refreshing naturally via expiration, they must immediately update whenever my users select a different tenant to "log in" to. However, the problem is that I cannot refresh these claims when the user changes tenants without logging out. Essentially, I tried mixing authorization with authentication and hit a wall.
It seems like I have two options:
Obtain the authorization information from a separate provider, or even an endpoint on the identity server itself, like /user-info but for authorization information. This ends up adding a huge overhead, but the actual boilerplate for the server and for the client is minimal. This is similar to how the OSS version of PolicyServer does it, although I do not know how their paid implementation is. My main problem here is that both the client and resource (API) will need this information. How could I avoid N requests per interaction (where N is the number of resources/clients)?
Implement some sort of custom state and keep a store of users who need their JWTs refreshed. Check these and return some custom response to the caller, which then uses custom js client code to refresh the token on this response. This is a huge theory and, even if it is plausible, still introduces state and kind of invalidates the point of JWTs while requiring a large amount of custom code.
So, I apologize for the long post but this is really irking me. I do not NEED to use IdentityServer or JWTs, but I would like to at least have a React front-end. What options do I have for up-to-date tenancy selection and roles? Right when I was willing to give in and implement an authorization endpoint that returns fresh data, I realized I'd be calling it both at the API and client every request. Even with cached data, that's a lot of overhead just in pure http calls. Is there some alternative solution that would work here? Could I honestly just use a cookie with authorization information that is secure and updated only when necessary?
It becomes confusing when you want to use IdentityServer as-is for user authorization. Keep concerns seperated.
As commented by Dominick Baier:
Yes – we recommend to use IdentityServer for end-user authentication,
federation and API access control.
PolicyServer is our recommendation for user authorization.
Option 1 seems the recommended option. So if you decide to go for option 1:
The OSS version of the PolicyServer will suffice for handling the requests. But instead of using a json config file:
// this sets up the PolicyServer client library and policy provider
// - configuration is loaded from appsettings.json
services.AddPolicyServerClient(Configuration.GetSection("Policy"))
.AddAuthorizationPermissionPolicies();
get the information from an endpoint. Add caching to improve performance.
In order to allow centralized access, you can either create a seperate policy server or extend IdentityServer with user authorization endpoints. Use extension grants to access the user authorization endpoints, because you may want to distinguish between client and api.
The json configuration is local. The new endpoint will need it's own data store where it can read the user claims. In order to allow centralized information, add information about where the permissions can be used. Personally I use the scope to model the permissions, because both client and api know the scope.
Final step is to add admin UI or endpoints to maintain the user authorization.
I ended up using remote gRPC calls for the authorization. You can see more at https://github.com/Perustaja/PermissionServerDemo
I don't like to accept my own answer here but I think my solution and thoughts on it in the repository will be good for anyone thinking about possible solutions to handing stale JWT authorization information.

IdentityServer4 personal access token (github-like) or API key for third party clients

Our current setup is
IdentityServer4
Angular + ASP.NET Core application
Authentication for the app via implicit flow/oidc.
We want to provide APIs for customers, i.e. third party clients, with restricted access (separate set/subset of claims). These clients are mostly non-interactive scripts that download data.
This means that we cannot use any flow which (occasionally) requires user interaction. Personal access tokens, like in github, or some other generate once, reuse for a long time API key or token would be needed.
The long token lifetime would not be a security issue, because the token should only allow access to a few read-only APIs and only for that customer's data - so the responsibility to handle the token(s) falls onto the customer.
The customer should be able to create and revoke such API-access tokens based on their claims. Some users might only claims to access certain APIs.
It would be good if we could later prevent that the user re-uses the same token for multiple clients because of licensing requirements but that is perhaps an entirely new question
How could I achieve this?
I thought about doing this via a custom grant, similar to a delegation grant: user uses app, which calls the asp.net core API, which performs auth with that custom grant, persists that token somewhere (just a plain table in the database full of customer-api-only tokens? I'm not sure about that) and shows it to the user - which can also retrieve it later from storage.
I'm thinking about doing the "delegate"-authentication via our API so that we don't leak the secrets into the Angular application.
I think that we then should be able to have either long-lived access tokens or at least refresh tokens via that custom grant.
2017-12-12 how I think I could solve it
We want a process where the user generates something in our application (i.e. via our client) and this something can later be used by the user's third party client to access the API - or request an access token and then access the API.
We want this access to be tied to the user. This includes
- Disabled user
- Lockout
- Specific claims (e.g. tenant)
This does not lend itself well to a solution that issues access tokens directly, because the token would remain valid even if the user was disabled or locked out. Which means that we cannot use a custom grant or IdentityServerTools to issue tokens directly.
Therefore we should use the client credentials grant, or something similar to it, as this could yield new, short-lived access tokens.
User actually generates a new client, which is pre-filled with claims from the user (such as the tenant - which is immutable) and has a claim that corresponds with the user. This happens transparently. Password should be user-supplied with the option to change it. We only store the relation between user and issued client-ids, no passwords.
We have to create a custom grant, which works similar to client credentials, but also checks if the corresponding user is active etc. (which I think should be possible by injecting UserManager)
Resulting access token lifetime is short, interaction with our APIs is expected to be short-lived.
Assuming it is safe and easy enough to write such a grant, we should be able to cover everything we need.
Of course, I might have completely overlooked something :)

Manually expire JWT token from server - WEB API 2

I am working on a api server which revives requests from a mobile app. I am using JWT with ASP.Net MVC Web API 2. In this Admin gives access of various departments to mobile app users. I set these DeptIds in Claims at the time of Login. On every authorised request from app, in a custom action filter attribute I read claims to match deptId in request URL with claims. This all scenario works fine.
Now my problem is, when Admin revokes access of any particular dept from app user, how should I expire the access_token of that user so that, on Login request call, I can set new Claims. Otherwise, as Admin removes access from server but the deptId still exists in user's Claims so user still have access to that department.
One way is on every request, check in database for access but that increases overhead of server also increases response time. So I don't want to go this way.
I didn't find anything on web how to expire token in JWT. Can any one help on this?
A JWT token happens to be a kind of token that allows it to be self-contained i.e. one can validate it without consulting an external entity.
That also means that there's no external entity that will tell you that the token was revoked or expired. Expiration can only happen by some property in the JWT itself; the exp claim was standardized for that purpose: it will tell the recipient the time after which the information in it must no longer consider to be valid
Authentication and Authorization are different things.
Use JWT for Authentication but not for Authorization. I mean that using JWT you can know who the user are but don't put information about what user can do into the JWT. Check permissions for the user on the server side basing on just user's identity that you got from JWT. You may also put into JWT some information that additionally limits access rights (i.e. blacklisting; for example, social network site creates an access token for a game to access my identity and friends list but not my posts) but don't put there information that directly provides access to some features (i.e. whitelisting). In that way you can easily remove access to some features on your sever-side despite that fact that the user is already logged in with JWT.
I understand you are interested in revoking or invalidating tokens instead of expiring them.
Revoking or invalidating tokens
Unfortunately​ it's not possible to achieve it
without keeping the track of the tokens somewhere:
Issue a token and add it to a whitelist to keep the track of it.
When validating a token, check the whitelist and refuse the request if it is not whitelisted.
To revoke or invalidate a token, remove it from the whitelist.
This security schema require some trade-offs. Deal with it.
Performance considerations
Regarding your performance concerns: Bear in mind that premature optimization is the root of all evil. You shouldn't optimize until you have a performance problem and you have proven that the performance problem comes from the way you store your tokens.
You could start storing the tokens in the database and then consider a cache in memory, for example. But always be careful when fixing a problem that you currently don't have.
Token identifier
The jti claim should be used to store the token identifier on the token. When validating the token, ensure that it's valid by checking the value of the jti claim against the token identifiers you have on server side.
For the token identifier you could use a UUID.

ASP .NET WebAPI default OWIN authentication - help clear things up

I have some general/how-does-it-work-inside questions about WebAPI and OWIN (specifically, the default configuration which is set up when you create new WebAPI project in VS2013 and select Individual user account authentication). I did that, then I registered (using jQuery post) and even logged in (received token which I included in Authorization header, receiving access to protected resource. I just have some more questions about it:
Are my data stored inside authentication token? I know my password isn't, but is token containing encrypted data, or is just a random string? These are the only 2 options that I can think of: either token contains encrypted data (userId, expiration date, etc.) and server app deciphers it and grants me access to resources, or token is a random string and all user data are stored on server (token is used as a key to obtain correct user data entry). If the second theory is right, the token <-> userData lookup must be stored somewhere - is it session, cache or database maybe?
If i wanted to make a RESTful API, what about Roles, etc. (in general - data beyond simple who-are-you identification that I need for every request)? Again: first thing that comes to mind is to store them inside token. But if the data grows large isn't that too much overhead to send with each request (plus headers themselves probably are limited in size)? Second thing is using external OAuth service (like Facebook or Twitter) - if the user authenticates using external token, I can't control what information does it contain. Alternative is to get the data I need from the database each time, but isn't it bad practice? Every single request would need an extra database call to collect user's role and check if he even has access to this particular part of application. I could store it in session, but RESTful API is supposed to be stateless.
Thanks for any help as I'm just starting to dig into OAuth and WebAPI authentication. I know that I can customize everything to work as I want (so use session to store user data, etc.), but I wanted to know what the good practices are and which of them are provided out of the box with default WebAPI project in VS2013 and which need to be implemented manually.
(1) the latter is correct. The server verify token by machine key and can decipher and validate its contents.
(2) You got that correct. Its best to keep the token size min. tbh I am looking to see what others are doing about this. (+1 for the question.)