0

I am setting up an authentication and authorization for my minimal API (.Net 7) using this tutorial: https://www.telerik.com/blogs/authorization-authentication-minimal-apis

I have never done this before and I am curious if my idea is correct or not. I need to check if the data that should have been received from the database are connected with the authenticated user (basically I want to prevent other users to view data of other users - only "Admin" role can do that). Would this be the right way how to do that or am I missing something (is there some more elegant way than written below)?

In this example: lets say that only when user is logged in (user with nickname "test123) he can receive only his information (data from database about the user "test123") but not about any others (only the logged in user with role "Admin" can do that):

app.MapGet("/users/{nickname}", (string nickname, ClaimsPrincipal user, IUserData userData) =>
{
    if (user?.Identity?.Name == nickname ||
        user?.IsInRole("Admin") ?? false)
    {
        try
        {
            return Results.Ok(await userData.GetUserByNickname());
        }
        catch(Exception ex)
        {
            return Results.Problem(ex.Message);
        }
    }
    
    return Results.Unauthorized();
});
Guru Stron
  • 102,774
  • 10
  • 95
  • 132

1 Answers1

1

For scenario where the data can be received only by owner of this data (so e.g. user Monster can get information only about Monster), you don't event need to get nickname parameter.

While your user is authenticated to get information, you can extract the user identifier from ClaimsPrincipal, and it by design prevents getting data about someone other. The endpoint would look just like /user

For second scenario, where admin can get information about everyone, you just need to check e.g. basing on ClaimsPrincipal whether user is in role admin. If yes, then just query database for user by his nickname and return it. The endpoint would look like this /user/{nickname}.

And additional thing, don't use exceptions to handle the logic. Exceptions are exceptional. You should rather call the IUserData.GetUserByNickname() and check if result is equal to null. If yes, then e.g.

return Results.NotFound("User not found")

Szyszka947
  • 473
  • 2
  • 5
  • 21
  • Thank you for you answer, I think that is exactly what I needed to clarify. Anyway about the exception: it is there because it is an async method that can be cancelled or any other exception can happen during the async operation and on awaited then it will throw the exception, therefore I want to set the result as "problem". It is not same as "not found" (I have the logic for "not found" in my original code where there is the null check as you suggest, but this on the stackoverflow is only the example code). – Michal Lyga Aug 28 '23 at 13:20