0

I am building a MVC app in asp.net core 6. The app is done but I want it to be used only by selected few users. I want these users to be stored in a file so that they can be added later by a SYSadmin. Right now I am using the following code:

{
    var policy = new AuthorizationPolicyBuilder()
                   .RequireAssertion(x =>
                         x.User.Identity!.Name == "DOMAIN\\NAME" ||
                         x.User.Identity!.Name == "DOMAIN2\\NAME2"
                         )
                   .Build();
    config.Filters.Add(new AuthorizeFilter(policy));
});

I would like this to be replaced with a code which reads the allowed users from a file. Thank you.

2 Answers2

1

Based on the question and it's comment, I'm assuming a simple text file containing users separated by line-breaks is good enough - something like this:

DOMAIN1\UserA
DOMAIN2\UserB
DOMAIN3\UserC

If that is the case, you can use File.ReadAllLines() to load the content of the file into a string array, and then simply use linq's Any():

// Note: filePath should come from app.settings
var users = File.ReadAllLines(filePath);

// validation on the content of users omitted for brevity

{
    var policy = new AuthorizationPolicyBuilder()
                   .RequireAssertion(x =>
                         users.Any(
                             u => u.Equals(
                                 x.User.Identity!.Name, StringComparison.OrdinalIgnoreCase
                             )
                         )
                    )
                   .Build();
    config.Filters.Add(new AuthorizeFilter(policy));
});

Notes:

  1. You should wrap your call to File.ReadAllLines() with a try...catch to handle exceptions that might be thrown from it in case the path is wrong or the user running the application don't have permissions to the file.
    If you can't get the information from the file, you should exit gracefully or consider using a default user (hard coded or app.settings based).

  2. As a rule, prefer using .Equals over == when comparing strings, especially if you want a case-insensitive comparosin. More info on string comparison can be found here: Recommendations for string usage.

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • Thank you! However this code gives me three different errors. I have added the vaidation above the brackets. .Build(); says as follows "Severity Code Description Project File Line Suppression State Error CS1061 'bool' does not contain a definition for 'Build' and no accessible extension method 'Build' accepting a first argument of type 'bool' could be found (are you missing a using directive or an assembly reference?) AktualniSchemaHfEditor D:\Users\992960t\source\repos\AktualniSchemaHfEditor\Program.cs 40 Active " – Matěj Němec Jul 25 '23 at 13:27
  • And second policy say as follows: Severity Code Description Project File Line Suppression State Error CS1503 Argument 1: cannot convert from 'Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder' to 'Microsoft.AspNetCore.Authorization.AuthorizationPolicy' AktualniSchemaHfEditor D:\Users\992960t\source\repos\AktualniSchemaHfEditor\Program.cs 41 Active Thank you for any help – Matěj Němec Jul 25 '23 at 13:28
  • 1
    I've missed a `)`... Edited that in (and spaced out the lines a bit to help readability) – Zohar Peled Jul 25 '23 at 13:36
  • Thank you! This does the trick. I will now proceed to read the code to try understand it as best as possible. Once again thank you for your time and help. Have a wonderful day. – Matěj Němec Jul 25 '23 at 13:54
  • 1
    Glad to help :-) – Zohar Peled Jul 25 '23 at 14:10
1

Here’s a version that reads the file every time, but only until a match is found. I. e. it doesn’t read the file only once at startup, so you can add and remove users at runtime:

    var policy = new AuthorizationPolicyBuilder()
        .RequireAssertion(async context => {
                using var reader = new StreamReader(@"C:\temp\validusers.txt");
                while (await reader.ReadLineAsync() is string validName)
                {
                    if (string.Equals(context.User.Identity!.Name, validName, StringComparison.InvariantCultureIgnoreCase))
                        return true;
                }
                return false;                
            })
        .Build();
BenderBoy
  • 346
  • 2
  • 8
  • Hello! Thank you, I like this code but after I have commented all the previous solutions and left this one with an empty file (to test whether it truly works) it still allowed me into the app. Any Idea please? – Matěj Němec Jul 25 '23 at 13:39
  • Not sure what’s wrong on your end, it seems to work for me, sorry (I get a 403 when the file is empty). Did you add it to `config.Filters`? You could also make it the DefaultPolicy to make it apply to all requests. – BenderBoy Jul 25 '23 at 14:24
  • I have successfully implemented the above solution. But thank you for yours. I have probably made some msitake along the way with your code. – Matěj Němec Jul 26 '23 at 07:19