0

At the top of my controller or even for each method I can add [ AuthorizeForScopes(Scopes = new string[] { "Sites.ReadWrite.All" })] or [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] which includes all the scopes for Azure AD laid out as similar to "file.read file.write" and I can access my controller. However, i could even change it to [AuthorizeForScopes(ScopeKeySection = "fakescope typo giberish")] and I still have access to my controller. It is almost as if this tag is doing nothing. Is there a reason for this or is there something i might need to add to program.cs to enable this to work?

My program.cs includes the following:

    //authentication pipline
builder.Services.AddHttpContextAccessor();
var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(options =>
                {
                    builder.Configuration.Bind("AzureAd", options);
                    options.Events = new OpenIdConnectEvents
                    {
                        //Tap into this event to add a UserID Claim to a new HttpContext identity
                        OnTokenValidated = context =>
                        {
                            //This query returns the UserID from the DB by sending the email address in the claim from Azure AD
                            string query = "select dbo.A2F_0013_ReturnUserIDForEmail(@Email) as UserID";
                            string connectionString = builder.Configuration.GetValue<string>("ConnectionStrings:DBContext");
                            string signInEmailAddress = context.Principal.FindFirstValue("preferred_username");

                            using (var connection = new SqlConnection(connectionString))
                            {
                                var queryResult = connection.QueryFirst(query, new { Email = signInEmailAddress });

                                var claims = new List<Claim>
                                {
                                    new Claim("UserID", queryResult.UserID.ToString())
                                };

                                var appIdentity = new ClaimsIdentity(claims);

                                context.Principal.AddIdentity(appIdentity);
                            }

                            return Task.CompletedTask;
                        },
                    };

                })
                    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                        .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
                        .AddInMemoryTokenCaches();

//Add Transient Services
builder.Services.AddTransient<IOneDrive, OneDrive>();

builder.Services.AddControllers(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();

builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
    options.Conventions.AllowAnonymousToFolder("/Login");
    options.Conventions.AuthorizeFolder("/");
    options.Conventions.AuthorizeFolder("/files");
}).AddMicrosoftIdentityUI();
Irish Redneck
  • 983
  • 7
  • 32
  • It may be you didnt configure something in `startup.cs` pre .net 6 or `program.cs` in .net 6+, without more code it's just a guessing game – Ryan Wilson Dec 18 '22 at 03:29
  • Please do not spam the tags, this question has nothing to do with `c` – Pablo Dec 18 '22 at 03:29
  • @Ryan Wilson I included the relevant program.cs services which I think relate. I have added AddMicrosoftIdentityUI() as shown so I figured that would be what would do it but still no. – Irish Redneck Dec 18 '22 at 03:54

1 Answers1

1

This is what I said about the AAD authorization. In your SPA, you need to integrate msal.js so that you can let your users sign in and you also need to generate access token so that you can use it to call your api application when your api application is under the protection by AAD as well.

When your api application is protected by AAD, you need to expose an api in Azure AD, then authorize this api permission(validate scope or role). I had another answer here which provide the solution and the tutorial inside it. And summarize here, in the api application, you only need to integrate AAD, like the sample code showed :

 services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
                    .EnableTokenAcquisitionToCallDownstreamApi()
                        .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                        .AddInMemoryTokenCaches();

No need to set cookie options, your api only need to authorize the request and return 401/403 error when the token is not correct. And in your controller, since I mentioned you need to expose api in AAD, you only need to set validation with attribute like [RequiredScope("your_custom_api_scope")].

I have a code snippet in this answer which is based on react, you can also take a look at it. The api part should be the same.

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
  • Upon further investigation my code does currently use the access token process similar to the code you provided. However, when i look in the browser at the cookies after login there is .AspNetCore.Cookies by default from logging in. Is the access token stored in this cookie? – Irish Redneck Dec 23 '22 at 15:15
  • no. `.AspNetCore.Cookies` is the cookie generated by cookie authentication which used for authentication but not authorization. access token doesn't contained in it. – Tiny Wang Dec 25 '22 at 09:17
  • Hey so after digging around. My setup is considered a hybrid approach. I have a asp.net core mvc with a SPA front end. Therefore, I have to use the webapp authentication. My code above has been updated to remove those cookie options. However, my issue still remains. [AuthorizeForScopes] could be any value that doesn't match my downstream API scopes and it still does not do anything. Eg, [AuthorizeForScopes(Scopes = new[] { "Sites.ReadWrite.All" })] does not keep me out of the controller even though in Azure portal I do not have that permission nor is it in my Downstream api in appsettings.json – Irish Redneck Dec 26 '22 at 16:03
  • could you pls create a new question with the detailed issue and what you had done, it will help to continue troubleshoot sir? – Tiny Wang Dec 27 '22 at 02:02
  • I decided to add my new question to here: https://stackoverflow.com/questions/74929457/how-to-configure-azure-ad-authentication-in-hybrid-asp-net-core-mvc-backend-an – Irish Redneck Dec 27 '22 at 15:31