Get the source code for this video for FREE → the-dotnet-weekly.ck.page/permissions4 Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Thank you, Milan for doing a series on the implementation of JWT. I know that codingtutorial series isn't that great for many views on here, but I just want to say I learnt a lot from this series. Lots of new ideas 💪
Glad you've mentioned the two problems at the end. Otherwise I would've done it 😁 A customer insisted to have all his permissions in the jwt and ended up with 200+ permissions and 10 minute token lifetime 😂
@@MilanJovanovicTech It worked surprisingly well, but not in regards of performance. A request was between 300ms to 1.1s. Depending on connection speed. Mobile devices had the worst performance. The infrastructure was scaled well tho.
Hi Milan, thanks for the awesome video series on permissions. Learned heaps. One question. For the claims, if we insert the role instead of the permissions into the claims would that not be better since the roles would change a lot less frequent than permissions and since roles are tied to permissions, it would be easy to get the permissions for that role.
Hy Milan. I am thinking about what would be the best approach to achieve performance and not depend on issues such as the lifetime of the jwt or the weight of many custom claims. At some point you talk about cached database access, but I haven't found a video that addresses that point. I would like to avoid that additional load to the jwt with the custom claims, but also hit the database every time I use a web api event. Kind Regards Diego
Hey DIego, you can use any caching mechanism to fetch from the DB once and then return the cached value for subsequent requests. Here are a few videos: - ruclips.net/video/Tt5zIKVMMbs/видео.html - ruclips.net/video/i_3I6XLAOt0/видео.html
@@MilanJovanovicTech Sorry, I misstyped there. I meant to say refresh tokens to request new access tokens when the access token expires or if the page is refreshed.
Hey Milan, noobie question here, you're using custom roles right? Or is it somehow a build up on the identity roles. I want to implement this permission authorization, but I'm not sure it will work with the roles already in the system?
Hey Milan, I'm wondering why the IJwtProvider is on the application layer, since it's not used by it. Shouldn't we put it on the Infrastructure project, just similar to the IPermissionService? Thanks for the series! It really helped me.
Is there a way to intercept the error on AuthorizationHandler to specify on http response what permission the user havent? I tried with AuthorizacionFilter, but i cannot approach that filter intercepts my response
Another great video. I would like to have one question. Is it safe to pass just strings everywhere? Shouldn't I make some strong type? Thanks Milan, keep up the amazing content.
I have a question that you probably have the answer to. If we are going to be controlling the roles and permissions data present in the database from a code-first perspective, ie hard coding the database values in the code itself; why would we not just hard code the roles and permissions in the code? In my head, this would negate the issue of hitting the database with every request as well as the issue of JWT bloat when a user has lots of permissions. There is probably a simple answer to this, but I can't think what. I guess if you were to have multiple systems that were interested in the roles and permissions, it makes sense to have this data in the database, rather than just in code.
I think you came to the proper conclusion on your own. That approach works in a single system, but when it's multiple systems it starts to become a problem.
@@MilanJovanovicTech There are several strategies to invalidate json token but only when using non cache approach where use calls DB during the authentication process: Revocation via Blacklist Blacklist tokens: Store invalidated tokens in a persistent store (e.g., database or cache). When a user logs out or when you want to revoke access for a particular token, you add the token's jti (JWT ID claim) to the blacklist. Check on each request: When validating the JWT in subsequent requests, check if the jti is in the blacklist. If it is, reject the token as invalid. Revocation via Token Versioning Version tokens: When generating a JWT, include a token_version claim in the payload. Store the current version for each user in a database. When the user logs out or the token needs to be invalidated, increment the token version in the database. For future requests, check that the token's token_version matches the user's version in the database. Force Token Invalidation via Issued-At (iat) Claim Include the iat (issued-at) claim in the token and store a timestamp in the database for the last token issuance. If the user logs out or needs the token invalidated, update the stored timestamp, and any token issued before that time is considered invalid. This technique is often combined with short-lived tokens and refresh tokens
Interesting Idwa, but I would not store the permissions in JWT. Also I would not read the list of all permissions from DB. I would read them once and update them from DB by any change. But once are they in memory I can use for ex. DI to use them.
Sounds like an monolithic approach and not suitable for distributed systems. I would recommend Redis or another distributed caching that can be easily invalidated on permission changes.
Hi Milan, to solve issue with performance I would suggest to introduce Memory cache rather than put this data to Claims. There are multiple reasons for it. First you can drop cache whenever needed, for example user got role un assigned or assigned new one Second. You keep authentication and authorization part separate. More over if you use distributed cache like Redis you will not have issues if you have multiple instances too Third. JWT size and lifetime that you mentioned will be not tied to permissions
Get the source code for this video for FREE → the-dotnet-weekly.ck.page/permissions4
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Wild to see that there were 5.7k on your newsletter only 5 months above. Now you are above 20k 💪
@@mcdaddy1334 Well it's been a solid 6 months since this video. But taking a look back, it's nice to see how far I got 😁
Thank you, Milan for doing a series on the implementation of JWT. I know that codingtutorial series isn't that great for many views on here, but I just want to say I learnt a lot from this series. Lots of new ideas 💪
It actually did pretty okay in the long term as far as views are concerned
Wow wow wow, thank you Milan, you are a life saver. I have been looking for this implementation for a while now.
Thank you Milan
Most welcome! :)
You made my life easier man. Thank you very much. One more subscriber.
Thank you, glad you enjoyed this series 😁
Glad you've mentioned the two problems at the end. Otherwise I would've done it 😁
A customer insisted to have all his permissions in the jwt and ended up with 200+ permissions and 10 minute token lifetime 😂
How did that work out for them? 😅
@@MilanJovanovicTech It worked surprisingly well, but not in regards of performance. A request was between 300ms to 1.1s. Depending on connection speed. Mobile devices had the worst performance.
The infrastructure was scaled well tho.
I searched your channel for an explanation of refresh token but I didn't find it. Please give me the video link if it exists.
Video coming soon, promise!
@MilanJovanovicTech explain it on clean architecture please 🙏
Awesome content my friend!
Thanks a lot, Saddam! 😊
Hi Milan, what do you think about Jason Taylor Flexible Authorization approach?
I modeled my approach using it + another similar approach I've seen
Milan you awesome
Thanks a lot! 😊
Hi Milan, thanks for the awesome video series on permissions. Learned heaps. One question. For the claims, if we insert the role instead of the permissions into the claims would that not be better since the roles would change a lot less frequent than permissions and since roles are tied to permissions, it would be easy to get the permissions for that role.
Yeah that could work ✅
Hy Milan. I am thinking about what would be the best approach to achieve performance and not depend on issues such as the lifetime of the jwt or the weight of many custom claims. At some point you talk about cached database access, but I haven't found a video that addresses that point. I would like to avoid that additional load to the jwt with the custom claims, but also hit the database every time I use a web api event. Kind Regards Diego
Hey DIego, you can use any caching mechanism to fetch from the DB once and then return the cached value for subsequent requests. Here are a few videos:
- ruclips.net/video/Tt5zIKVMMbs/видео.html
- ruclips.net/video/i_3I6XLAOt0/видео.html
It would be awesome to complement this authentication series by implementing access tokens.
That only makes sense for a public facing API, right?
@@MilanJovanovicTech Sorry, I misstyped there. I meant to say refresh tokens to request new access tokens when the access token expires or if the page is refreshed.
Hey Milan, noobie question here, you're using custom roles right? Or is it somehow a build up on the identity roles. I want to implement this permission authorization, but I'm not sure it will work with the roles already in the system?
Identity has a concept of custom claims, which you could use for permissions
Hey Milan, I'm wondering why the IJwtProvider is on the application layer, since it's not used by it. Shouldn't we put it on the Infrastructure project, just similar to the IPermissionService?
Thanks for the series! It really helped me.
Check out the first video in the series, it is used in the Application layer 🤔
ruclips.net/video/4cFhYUK8wnc/видео.html
Could you please show the same approach using reference tokens instead of JWTs? Asked that alrdy just not sure if you're planning too
I'm still unsure about that, perhaps yes. But not so soon
Yes that would be very interesting because unfortunately there is not really much good documentation to reference tokens..
Awesome! Are there any of your videos that go over ASP .NET Core Identitiy, user registration, etc.
Not yet, but I'm releasing a few very soon
Hello Milan , GetPolicyAsync is not getting the cached policy
Oh no?
Hi ! Milan. How can we Implement the Custom Error Page when the user ha no permission associated. Please let me know on this.
I don't know, to be honest. Haven't worked with MVC in a long time
@@MilanJovanovicTech can you give a shot to catch the response of the Failure to a middleware .
What would you say is the max amount of permissions a jwt can hold before it starts to become an issue?
I'd check what the JWT limit is, that should about do it. But you can encode the permissions with numbers maybe, to save on space.
Is there a way to intercept the error on AuthorizationHandler to specify on http response what permission the user havent? I tried with AuthorizacionFilter, but i cannot approach that filter intercepts my response
I found a solution using IAuthorizationMiddlewareResultHandler wich catch result from AuthorizationHandler
Isn't that a security concern?
@MilanJovanovicTech i use it just like aws iam
Another great video. I would like to have one question. Is it safe to pass just strings everywhere? Shouldn't I make some strong type? Thanks Milan, keep up the amazing content.
Constants are fine, IMO
thank you very match,it's great
I'm glad you like it
👋
Where can I find the complete solution? with JWT?
Check the first or last video in the series, should be a pinned comment
where can i get a code?
www.patreon.com/milanjovanovic
i am not able to pay 6 $ but i really want it (
@@ShaxbozbekQodiov Igualmente deseo conseguirlo
I have a question that you probably have the answer to. If we are going to be controlling the roles and permissions data present in the database from a code-first perspective, ie hard coding the database values in the code itself; why would we not just hard code the roles and permissions in the code? In my head, this would negate the issue of hitting the database with every request as well as the issue of JWT bloat when a user has lots of permissions. There is probably a simple answer to this, but I can't think what. I guess if you were to have multiple systems that were interested in the roles and permissions, it makes sense to have this data in the database, rather than just in code.
I think you came to the proper conclusion on your own. That approach works in a single system, but when it's multiple systems it starts to become a problem.
@@MilanJovanovicTech Hi Milan. What would be the correct approach for this type of problem with multiple systems?
The pain point can be resolve by invalidating all tokens issues to a user perfoming any chnage in users permission.
How do we invalidate the tokens?
@@MilanJovanovicTech There are several strategies to invalidate json token but only when using non cache approach where use calls DB during the authentication process:
Revocation via Blacklist
Blacklist tokens: Store invalidated tokens in a persistent store (e.g., database or cache). When a user logs out or when you want to revoke access for a particular token, you add the token's jti (JWT ID claim) to the blacklist.
Check on each request: When validating the JWT in subsequent requests, check if the jti is in the blacklist. If it is, reject the token as invalid.
Revocation via Token Versioning
Version tokens: When generating a JWT, include a token_version claim in the payload. Store the current version for each user in a database. When the user logs out or the token needs to be invalidated, increment the token version in the database. For future requests, check that the token's token_version matches the user's version in the database.
Force Token Invalidation via Issued-At (iat) Claim
Include the iat (issued-at) claim in the token and store a timestamp in the database for the last token issuance. If the user logs out or needs the token invalidated, update the stored timestamp, and any token issued before that time is considered invalid.
This technique is often combined with short-lived tokens and refresh tokens
Interesting Idwa, but I would not store the permissions in JWT. Also I would not read the list of all permissions from DB. I would read them once and update them from DB by any change. But once are they in memory I can use for ex. DI to use them.
So your idea is to save all logged-in users claims in memory? Any real scenario example?
How would you scale that? 😅
Sounds like an monolithic approach and not suitable for distributed systems. I would recommend Redis or another distributed caching that can be easily invalidated on permission changes.
Hi Milan, to solve issue with performance I would suggest to introduce Memory cache rather than put this data to Claims. There are multiple reasons for it.
First you can drop cache whenever needed, for example user got role un assigned or assigned new one
Second. You keep authentication and authorization part separate. More over if you use distributed cache like Redis you will not have issues if you have multiple instances too
Third. JWT size and lifetime that you mentioned will be not tied to permissions
Good suggestion there. This also applies if you're working with an external IDP, which solves authentication
please, upload this project on github
It's on Patreon only at the moment
@@MilanJovanovicTech kek. i already find code on github
🪙🪙🪙
🤔