Implementing A Custom Authorization Handler In ASP.NET Core | Permission Authorization - Part 3

Поделиться
HTML-код
  • Опубликовано: 23 янв 2025

Комментарии • 178

  • @MilanJovanovicTech
    @MilanJovanovicTech  2 года назад +12

    If you had a dollar for every time I say _permission_ in this video, how rich would you be?
    Get the source code for this video for FREE → the-dotnet-weekly.ck.page/permissions3
    Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
    Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt

    • @Dustyy01
      @Dustyy01 2 года назад +1

      I think authorization would be more lucrative haha

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      @@Dustyy01 You sure? Did you count? 😂

    • @sineme
      @sineme 2 года назад +1

      @@MilanJovanovicTech I counted
      permission/permissions: 98
      authorization(not authorize): 43
      You should reupload the video and say 2x permission at the end😂

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      @@sineme Those are rookie numbers 🤣

  • @sushilb7994
    @sushilb7994 2 года назад +9

    Milan, you are one of the best content creator that I'm following from hundreds of others.... Loved this one.... Keep them coming....✌️

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      Thank you, this means so much to me, more than you can imagine 😊

  • @kirillhorn3186
    @kirillhorn3186 2 года назад +3

    Thanks you, Milan! Every new video I learn new and new and new!!! I really appreciate what you are doing!

  • @davittonoyan6537
    @davittonoyan6537 Год назад +2

    Great video, Milan I looked for video like this in past 6 months... Thank you

  • @AbuBakrSadiqi-b7t
    @AbuBakrSadiqi-b7t Год назад +3

    Every time I come to watch your video for a specific topic, I learn tons of other topics too.
    Can you please make some videos about unit test and integration tests which are on a real project. Because I watched lots of videos about it, but still, I am stuck.
    Thanks for that and stay awesome. 😊😊

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      I already have a few videos on those topics:
      - ruclips.net/video/tj5ZCtvgXKY/видео.html
      - ruclips.net/video/a6Qab5l-VLo/видео.html
      - ruclips.net/video/Pk2d-qm5KwE/видео.html

  • @dicusardenis922
    @dicusardenis922 Год назад +2

    I just wanted to thank you for everything that you are doing, your content is awesome and it helped me a lot. I think you deserve way more subscribers than you have :)
    p.s. good luck, loocking forward to video course series

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      Thank you so much! I'm glad this series has been so helpful for many people. The subscribers will come, but the quality is what's important.

  • @talkathiriify
    @talkathiriify 2 года назад +2

    Excellent topic.
    Thank you very much Milan.

  • @adisilagy
    @adisilagy 2 года назад +3

    This is so helpful!!!
    Thank you Milan

  • @nove1398
    @nove1398 2 года назад +1

    Way to gooo! Keep them coming. Part 4? :)

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +2

      Part 4 on Tuesday, and that's a wrap for now 😁

    • @nove1398
      @nove1398 2 года назад

      @@MilanJovanovicTech suppose we request it to have more on this series! And vote in numbers

  • @alirezanet
    @alirezanet 2 года назад +3

    The thing I was talking about before in other videos in this series was a third way to solve the problem you mentioned here 4:30 . (for authorization without calling the database and dealing with caches or storing all claims in jwt token) which is using enum flags. this is a much faster and more flexible way to deal with this problem. and we can use a single value in the database or jwt tokens, instead of list of permissions.

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +2

      Agreed, but you are limited to 32/64 values with flags.
      On a project I'm working on, we have ~300 unique permissions 😅

    • @alirezanet
      @alirezanet 2 года назад +1

      @@MilanJovanovicTech I had the same problem with jason taylor suggestion before that's why I've created that library (infiniteEnumflags)
      also I added an example of how it works to the repo. you can check it out.

    • @alirezanet
      @alirezanet 2 года назад +1

      @@MilanJovanovicTech by example, I mean a flexible authorization implementation example by the library.

    • @jwcodendaal
      @jwcodendaal Год назад +1

      ​@@alirezanet I'll check it out. I was also preferring the approach using enum flags but ran into the limitations mentioned.

    • @alirezanet
      @alirezanet Год назад

      @@jwcodendaal 👍 let me know if you faced any problem

  • @novaploca2080
    @novaploca2080 2 года назад +2

    Yes yes yes yes yes.
    Thank you Milan

  • @megaporky
    @megaporky Год назад +2

    Great post Milan. In the past when I first time implemented permissions based RBAC I spent so much time to get content that gathered here in several videos.
    One thing I noticed that might be improved in your example. In AuthorizationPolicyProvider you getting policy and if it's not null you creating it. To avoid creation of the policies all the time I'd suggest to take IOptions options from constructor to local variable and then slightly modify GetPolicyAsync to:
    if (policy == null)
    {
    if (Enum.TryParse(policyName, out var permissionId))
    {
    policy = new AuthorizationPolicyBuilder()
    .AddRequirements(new PermissionRequirement(permissionId))
    .Build();
    // Add policy to the AuthorizationOptions, so we don't have to re-create it each time
    options.Value.AddPolicy(policyName, policy);
    }

  • @gavincampbell1061
    @gavincampbell1061 2 года назад +1

    @9:17 when filtering for the Member, would you not use "FirstOrDefault()" instead of "Where"? "Where" will return an IEnumerable containing one element but it will have had to check the whole table; whereas "FirstOrDefault" will exit out once it finds the Member you're looking for. However, you'd also need to deal with a potential null value if no Member with that ID exists. Maybe I'm missing something as to why "Where" was used here so thought I should ask/point it out.

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      It's going to be an index seek at the database level regardless. And I'm only returning that Member's roles in the end. The main point is there won't be any table scans involved.

  • @MaxSupercars
    @MaxSupercars 2 года назад +1

    Finally! Great, thank you! 😊

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      Did it meet expectations?

    • @MaxSupercars
      @MaxSupercars 2 года назад

      @@MilanJovanovicTech Of course. Now I will try to play with it in a test solution. I normally rather like to work with Permissions than only with roles. I like that solution with "HasPermisson" attribute. It's so elegant. .NET has evolved in a very powerfull platform.

  • @tidianediallo6199
    @tidianediallo6199 11 месяцев назад +1

    awesome Milan , thank you off lot, may God blessyou

  • @CaioVitorOliveira
    @CaioVitorOliveira 3 месяца назад +1

    I'm sorry, I asked the question wrong. By following your videos I was able to implement the HasPermission method and initialize the permissions and related entities using IEntityTypeConfiguration and builder.HasData.
    The problem is in the API tests using xUnit, I use the CustomWebApplicationFactory class that inherits from WebApplicationFactory to initialize my databases but I'm not able to insert the related entities. Could you explain how to seed the Permissions, Roles and RolePermissions in the CustomWebApplicationFactory?

  • @Gamedocable
    @Gamedocable 2 года назад +2

    Thanks for the great video Milan! I've got my version working, the only thing is that on the line 'AuthorizationPolicy? policy = await base.GetPolicyAsync(policyName);' the policy is always null, do you know why this is?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      It should be null the first time, but not afterwards

    • @Gamedocable
      @Gamedocable 2 года назад

      @@MilanJovanovicTech I have it null every time I try it

    • @DaveRoman-mc4nn
      @DaveRoman-mc4nn Год назад

      @@Gamedocable Could you solve it?

  • @manofqwerty
    @manofqwerty Год назад +1

    I don't know if it is the way I have set it up, but I was getting an error when implementing the `GetPermissionAsync` method as defined here. What worked for me was to change the `.Select(x => x.Roles)` on the member context to `.SelectMany(x => x.Roles)` and then on the roles variable, remove the first `.SelectMany(x => x)`.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Maybe you had a slightly different entity configuration? EF Core version? Could be a number of things

    • @manofqwerty
      @manofqwerty Год назад

      @@MilanJovanovicTech yeah, I think this is likely the case, but thought I'd comment it here just incase someone else has the same issue 👍

    • @soonhongng7037
      @soonhongng7037 Год назад

      i face the error in GetPermissionsAsync too, while accessing GetMemberById endpoint. The error is from _dbContext.Set().Include(x->x.Roles).ThenInclude(x->x.Permissions)..... Error was 'Invalid column names RolesId)

  • @acvinu
    @acvinu 8 месяцев назад

    Great video Milan, thank you very much for this

  • @joshuakosamu7765
    @joshuakosamu7765 9 месяцев назад +1

    Thanks for the assist. Much needed help.

  • @algernonloos6743
    @algernonloos6743 Год назад +1

    Hi, Milan! Thanks for the video series, they help me to progress on my pet project
    I've got a question: Why are AuthorizationHandlers defined in the Infrastructure project, and not in the Application project for instance? What's the logic behind that?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Because I see Auth as an Infrastructure concern, and not an Application (business) level concern

  • @pablocom
    @pablocom 9 месяцев назад +1

    Thanks for sharing this video!

  • @HasithaWikramasinghe
    @HasithaWikramasinghe Год назад +1

    Hi Milan,
    I implemented permission based authorization in .NET 5 with the support of your video. But I got stuck at some point. Here is my problem.
    - When I'm trying to access logged in user's userId (by context.User.Claims) from the context in PermissionAuthorizationHandler class it's always null. I almost wasted 5-6 days to figure this out. But I couldn't able to find where is the issue. Do you have any idea about this type of issue?

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Check the pinned comment perhaps. Maybe it's not wired up correctly.

  • @MikeRM2
    @MikeRM2 11 месяцев назад +1

    Great series so far. I did run into a issue, if entering a userId that not valid, I kept getting a 404 error, even though I was thinking I would get a 401 error. Is there a way to trigger a 401 if the parsedId is not valid?

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      We'd need to alter the code that's return a not found when the user doesn't exist - on the other hand, maybe this is the correct behavior

  • @mylesdavies9476
    @mylesdavies9476 2 года назад +1

    Does one of your videos cover the creation of the individual database entity configuration classes shown in this video?

  • @jodainemoore8300
    @jodainemoore8300 3 месяца назад

    What tool do you use for should the values of variable when you are stepping through the code

  • @anantjaiswal3283
    @anantjaiswal3283 Год назад +1

    Can you please send document/blog link where we can check code.
    Thanks!

  • @Dustyy01
    @Dustyy01 2 года назад +3

    In the next video u will show how to put the permissions into the claimsidentity. The thing with JWTs is that once they're created u cannot update them.
    How would u handle permission updates in this case?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      That's the tradeoff you're making to gain performance. There isn't a clear way how to revoke a JWT once it's issues. One thing you can do is give it a short TTL.

    • @Dustyy01
      @Dustyy01 2 года назад +1

      @@MilanJovanovicTech so would rather go for reference tokens or just use permission validation on each call?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +4

      ​@@Dustyy01 I'd ask myself two things:
      - How often do user's permissions actually change?
      - Can I suffer the performance hit of checking permissions in DB?
      If permissions don't change frequently, just put them in JWT and be done with it. Give the token a 60min lifetime, and just refresh it from the client when it expires.
      If I want to always fetch from DB to have the latest state, but I don't want to take a performance hit, I can introduce caching. And I just need to deal with cache invalidation when permissions change.
      Both solutions are viable, and simple to implement. I use fetching permissions from DB + caching with IMemoryCache on a current project, and it works like a charm.

    • @Dustyy01
      @Dustyy01 2 года назад

      @@MilanJovanovicTech that's actually a pretty smart solution, thank you so much for this idea!

  • @georgeritchie4497
    @georgeritchie4497 6 месяцев назад

    Very cool video, the only question why do you add IPermissionService as singleton? why don't you add as scoped? is it compile time error, logic error or something else?

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 месяцев назад

      Isn't it scoped? 🤔

    • @georgeritchie4497
      @georgeritchie4497 6 месяцев назад

      @@MilanJovanovicTech Sorry, I mean IAuthorizationHandler where you use IPermissionService. Just got mixed up with names.

    • @MilanJovanovicTech
      @MilanJovanovicTech  6 месяцев назад

      @@georgeritchie4497 Ah, in that case it can be any lifetime. I just prefer singleton for stateless classes.

  • @manofqwerty
    @manofqwerty 2 года назад +1

    In my PermissionAuthorizationHandler, the `context.User.Claims` is always empty. I know I have missed something obvious, but I have been though the video several times and I cannot figure it out. Any idea what my issue may be?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      When creating the JWT does it end up having the claims?
      You can inspect it on jwt.io

    • @manofqwerty
      @manofqwerty 2 года назад

      @@MilanJovanovicTech yeah, the JWT has the subscriber and email claims associated with it.

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      @@manofqwerty Then it could be something around configuring Auth with the framework

    • @manofqwerty
      @manofqwerty 2 года назад

      @@MilanJovanovicTech yeah, that is what I was thinking. I will have another look tomorrow. Thank you.

    • @anilkarasahh
      @anilkarasahh Год назад +1

      @@manofqwerty Hey, have you been able to figure that out? I have run into the same issue. I suppose it is because of a problem of decoding JWT. Because of it, even the Authorize attribute does not work as well.

  • @paulbarton2280
    @paulbarton2280 Год назад +1

    What about restrictions on owned content? Meaning, you can only successfully fetch your own member data. I am assuming ReadMember will allow me to fetch any members data. Using a guid and the only security measure is not sufficient.

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Right. That's resource-based authorization and I didn't tackle that

  • @MirrorBoySkr
    @MirrorBoySkr 10 месяцев назад

    Thank you for the helpful video!
    But the HandleRequirementAsync() is not compiled in my case
    I had to put
    return Task.CompletedTask;
    How did it work in your implementation?

    • @MilanJovanovicTech
      @MilanJovanovicTech  10 месяцев назад +1

      Make it async, await something inside

    • @MirrorBoySkr
      @MirrorBoySkr 10 месяцев назад

      @@MilanJovanovicTech Ah. Now I see differences. Thanks a lot!
      Thank you for your videos. Good luck!

  • @matthewrossee
    @matthewrossee Год назад +1

    Hi Milan, why did you decide to register the authorization handler as singleton? I was browsing through the aspnetcore source code and as far as I can tell, they register it as transient. By the way, thank you for your videos!

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      Really? My understanding was that it should be a Singleton. Either one is fine.

  • @nathanf6526
    @nathanf6526 2 года назад +1

    Hi Milan. Thank you for the video - very informative.
    I have a question regarding returning a custom error message from the AuthorizationHandler. I would like to inform the user of which particular permission is missing. It seems you can write a custom error message via httpContext.Response.Body.WriteAsync( bytes, 0, bytes.Length );
    However, this seems a bit low level (writing a string to a byte[]), which makes be think that this may not be the conventional way of doing things. Do you have any opinons or alternative approaches for doing this?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      I wouldn't advise exposing permission information to consumers of your API. A 403 response is good enough.
      Why would they even need to know?

    • @nathanf6526
      @nathanf6526 2 года назад

      ​@@MilanJovanovicTech The scenario is users can upload an Excel file. This can potentially contain anything as the content. On the Api side we parse the file to see what 'kind' it is based on the column names. Once we know what kind of Excel file it is we want to check to see if the user has permission to upload this kind of Excel file. Ideally, we want to return 403 and also a error message to the client similar to "You do not have permission to upload {excel file kind}"

  • @ali.techub
    @ali.techub 8 месяцев назад

    Great video, could you help me I'm stuck with
    Unable to resolve service for type 'System.String' while attempting to activate 'Examination.Infrastructure.Authentication.PermissionRequirement'.

    • @MilanJovanovicTech
      @MilanJovanovicTech  8 месяцев назад

      You probably missed a step?

    • @ali.techub
      @ali.techub 8 месяцев назад

      @@MilanJovanovicTech it's was extra step i made it which inject PermissionRequirment, now im in another problem which is Unable to create a 'DbContext' of type ''. The exception 'The skip navigation 'User.Roles' doesn't have a foreign key associated with it. Every skip navigation must have a configured foreign key.' i think because the joining table not configured in correct way which is (userRole) entity if you configured in another video or some think help me please give me the link, thanks again

  • @اسيرالعلم-ك9ظ
    @اسيرالعلم-ك9ظ 29 дней назад

    what about users of same role has deffernt permissions, because know u get the permission of the role insted of permission of spicific user

    • @MilanJovanovicTech
      @MilanJovanovicTech  28 дней назад

      The relation is between role and permissions, not users and permissions.
      We'd need a different data model for what you're describing.

  • @juanmiguel431
    @juanmiguel431 2 года назад +1

    Great video.

  • @ashleyrodrigues1468
    @ashleyrodrigues1468 2 года назад

    Hi Milan, Why do we need IServiceScopeFactory? Why can't we directly inject IPermissionService through constructor injection??

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      It's a Singleton service, and IPermissionService is scoped

    • @ashleyrodrigues1468
      @ashleyrodrigues1468 2 года назад

      @@MilanJovanovicTech , Even though IServiceScopeFactory is a Singleton Service it will still behave like a Scoped service, Since you have registered IPermissionService as Scoped in your DI container..Please let me know if I am missing anything here...

  • @soonhongng7037
    @soonhongng7037 Год назад +1

    Hi Milan, thanks for this awesome series! However i face the error in GetPermissionsAsync too, while accessing GetMemberById endpoint. The error is from _dbContext.Set().Include(x->x.Roles).ThenInclude(x->x.Permissions)..... Error was 'Invalid column names RolesId)

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Did you run the DB migration? 🤔

    • @soonhongng7037
      @soonhongng7037 Год назад

      yes I did, switch to Persistence project and ran "Update-Database" and from Management Studio I can see all the migrations history

    • @soonhongng7037
      @soonhongng7037 Год назад

      I can register member and login but it seems like the MemberRole table didn't get populated with the userdata who has registered. Might this be the problem?

    • @soonhongng7037
      @soonhongng7037 Год назад

      @@MilanJovanovicTech what could be the problem here?

  • @andresjimenez3140
    @andresjimenez3140 Год назад +1

    Hey Milan Thks for this awesome content !!
    I've my web api project with 41 controllers and several api methods (haven't count em all yet), and I'm defining permissions for each endpoint using a smart enum 'Permission', but it's begining to look quite long class, any suggestion?

  • @mumk
    @mumk Год назад +1

    Finally

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      What do you mean finally? 😅 This video is out for a year...

  • @martinkrastev6353
    @martinkrastev6353 2 года назад +1

    Hi Milan, thank you for the amazing tutorial! Very well explained, easy to digest and understand. I have a small suggestion though. If you want to avoid creating the policy every single time, perhaps you should add it to the AuthorizationOptions. You can do this by creating a new property:
    private readonly AuthorizationOptions options;
    Assign value to this.options in the constructor:
    this.options = options.Value;
    And modify the return a bit in that way:
    policy = new AuthorizationPolicyBuilder(Auth0BearerTokenConstants.AuthenticationScheme)
    .AddRequirements(new PermissionRequirement(policyName))
    .Build();
    // Add policy to the AuthorizationOptions, so we don't have to re-create it each time.
    this.options.AddPolicy(policyName, policy);
    return policy;
    Let me know what is your opinion about it :)
    Thanks again for the astonishing tutorial!
    Kinds regards/Martin

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      But the policy changes dynamically per Permission, and it's only created once and then reused. I don't think it's a significant cost.

  • @matsandersson9306
    @matsandersson9306 9 месяцев назад

    Hi Milan, Great channel you have! One thing i miss in this authorization serie, HasPermission, where does that come from? I saw the HasPermissionAttribute, in the controller you write [HasPermission(...)] and i don´t see where that is?

    • @MilanJovanovicTech
      @MilanJovanovicTech  9 месяцев назад +1

      In C#, you can omit the "Attribute" from HasPermissionAttribute and just write HasPermission and it will behave the same

  • @andyhb1970
    @andyhb1970 Год назад +1

    Hi Milan, just followed your video series through and your explanation of the various classes required to implement a full featured custom authorization are superb and have saved me endless hours I'm sure! I wanted my permission model to be split into two elements e.g. Users with Author, Contributer and Viewer levels. To achieve this I have just concatenated the Permission and Level enums to create my policy name within the HasPermissionAttribute and then I deconstruct them in the policy provider to allow the correct creation of my permission requirement, do you think this sensible?

  • @SajidAliSoftwareEngineer
    @SajidAliSoftwareEngineer 2 года назад +1

    great Milan

  • @juke-duke
    @juke-duke 2 года назад +2

    do you think you can make a series on GraphQL APIs using hotchocolate where we still apply CA and DDD

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +2

      I want to explore GraphQL for sure, but it'll have to wait a bit, I need to do my research 😁

  • @jodainemoore8300
    @jodainemoore8300 3 месяца назад

    I am getting this error when trying the GetMemberByID, not sure what I am doing wrong
    401
    Undocumented
    Error: response status is 401

  • @nekonovi5038
    @nekonovi5038 4 месяца назад

    Hey Milan, great series of videos. Do you have any links that would be helpfull for unit testing the auth handler?

  • @bilalmehrban
    @bilalmehrban 2 года назад +1

    Thank you, explained it beautifully. Have you combined this with Identity?

  • @RamiNassarPlus
    @RamiNassarPlus 2 года назад +2

    Thanks Milan for sharing this... is there a link for github repo of this code?

    • @Dustyy01
      @Dustyy01 2 года назад

      U could check his GitHub for expensely server, I think he did the same there

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      Most likely, good idea

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад +1

      I share the code on my Patreon, but I also have examples on GitHub

    • @jamesevans6438
      @jamesevans6438 2 года назад +1

      Wow, what an awesome series Milan and I really like your presentation style too, I am a fan of permission based auth and this is something I will definitely use in my future projects

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      @@jamesevans6438 Thanks James :)
      I've used this on a couple projects now and it worked out great.

  •  Год назад +1

    you don't need to worry about the cached permission values if you invalidate the cache with the permissions key when you save changes in the permissions repo.

  • @techpc5453
    @techpc5453 Год назад +2

  • @RoshdiAlMajzoub
    @RoshdiAlMajzoub 11 месяцев назад

    Hi bro
    I have followed every step. but I am getting these 2 errors.
    Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Authorization.IAuthorizeData Lifetime: Scoped ImplementationType: Gatherly.Infrastructure.Authentication.HasPermissionAttribute': Unable to resolve service for type 'Gatherly.Domain.Enums.Permission' while attempting to activate 'Gatherly.Infrastructure.Authentication.HasPermissionAttribute'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Authorization.IAuthorizationRequirement Lifetime: Scoped ImplementationType: Gatherly.Infrastructure.Authentication.PermissionRequirement': Unable to resolve service for type 'System.String' while attempting to activate 'Gatherly.Infrastructure.Authentication.PermissionRequirement'.)

    • @MilanJovanovicTech
      @MilanJovanovicTech  11 месяцев назад

      There is no way you're getting that error if you followed Part 1-3 exactly. Looks like it's something related to registering the custom auth handler.

    • @ali.techub
      @ali.techub 8 месяцев назад

      Same Issue 100% if you solved Tell me , thanks

  • @justhobbes4682
    @justhobbes4682 2 года назад +1

    Good job! Will you look into resource-based authorisation?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      Yes, that's still an outstanding topic

    • @dmitryye4756
      @dmitryye4756 5 месяцев назад

      ​@@MilanJovanovicTech Milan, Thank you for your videos and samples; I learned a lot from them. I also thought about resource-based authorization. In the retail network, for example, a salesperson can only access their own sales, a shop manager can view their shop's sales data, and a regional headmaster can get sales within their region, among other restrictions. Given its domain-specific nature and potential for advanced logic, I am considering implementing it using MediatR pipeline behaviors. Do you have any other suggestions for enhancing this?

  • @androidsavior
    @androidsavior 5 месяцев назад

    The source code you shared here does not contain your full implementation of permission based

    • @MilanJovanovicTech
      @MilanJovanovicTech  5 месяцев назад +1

      It should be the implementation for this video only. The one in Part 4 should be the complete version.

    • @androidsavior
      @androidsavior 5 месяцев назад

      @@MilanJovanovicTech got the code. Thank you so much

  • @microtech2448
    @microtech2448 2 года назад +1

    I am still trying to understand all of it.
    How it would be possible to check different conditions on different roles/permissions?
    Let's say, there are 3 types of users.
    1. Super Admin
    2. Manager
    3. Staff
    Super Admin - this user should ve able to add/edit/delete users of rest 2 types but can not perform action on other super admins.
    Manager has some staff users under them.
    So manager kind of user should be able to add/edit/delete staff users who are associated to the logged in manager but can not add/edit/delete other managers staff users.
    And manager even can not alter any super admin user.
    Staff user can just login and do some other crud operations.
    How such requirements/Authorization can be implemented. Can you please explain in your next videos?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      You're mixing apples and oranges. Permissions are simply about "which action can I _perform_ in the system".
      There's nothing here that controls *what data you are allowed to see*. It's a separate requirement, and it needs a custom implementation of its own.

    • @microtech2448
      @microtech2448 2 года назад

      @@MilanJovanovicTech hmm, so do you have separate videos on this as well which shows how to implement it in manageable way or in your style?

    • @MilanJovanovicTech
      @MilanJovanovicTech  2 года назад

      @@microtech2448 Didn't get that far yet, unfortunately. But it's coming at some point

    • @microtech2448
      @microtech2448 2 года назад

      @@MilanJovanovicTech would love to see that series. Thank you

  • @mathieutrindade456
    @mathieutrindade456 3 месяца назад

    Hello,
    First of all, I love your content!
    However, there is something I don't understand in the Presentation layer. There is a reference to the Infrastructure layer, whereas I thought we were only supposed to point to the Application layer

    • @MilanJovanovicTech
      @MilanJovanovicTech  3 месяца назад

      Layers on the same level such as Presentation/Infra can reference each other. How else would you set up DI?

  • @mcdaddy1334
    @mcdaddy1334 Год назад +1

    "You know the drill"

  • @josepardo1026
    @josepardo1026 Год назад

    Hi Milan, very nice video series, thank you so much for your content.
    I´ve implemented your feature with string parameter for permission, my permission are like Entity.Read, Entity.Update, etc...
    My solution it´s working perfect with defined entity controller like this:
    [HasPermission($"{nameof(Boxer)}.Read")]
    public async Task GetBoxers()
    But I´m having error calling "HasPermission" with a generic entity controller like this:
    [HasPermission($"{typeof(TBaseEntity).Name}.Read")]
    public virtual async Task GetBaseGenerics()
    Compiler Error CS0182
    An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
    can you think of any solution to solve this?
    thanks in advance

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад +1

      It wont work. typeof is evaluted at compile time. And you specify your generic at runtime.

    • @josepardo1026
      @josepardo1026 Год назад

      I understand, many thanks@@MilanJovanovicTech

  • @am7-p
    @am7-p Год назад +1

    I wish the source code was provided.

  • @javidibra6786
    @javidibra6786 11 месяцев назад

    😍😍😍😍

  • @ramakris2323
    @ramakris2323 Год назад +3

    Milan everything is good but you are speaking in a very flat tone means you need to highlight and pause at main points otherwise its hard to figure out whats the critical portion or real logic to remember, skip saying very common things like i am giving it as argument blah blah.. very much we can see it anyway, I request you first elaborate on drawing board whats the overall design and flow, I could not sync with your talk and video at the same time..

    • @MilanJovanovicTech
      @MilanJovanovicTech  Год назад

      Things like that take time, don't think creating content is easy