Confused by API Test tab C# Code

I am attempting to modify and use the downloaded sample ASP.NET Core MVC app that has been configured with my tenant and - seemingly - my API information to access my ASP.NET Core Web API. I can successfully login on the MVC app and I can verify that I have both an id_token and an access_token. When the authenticated user clicks a link I added to the Home Controller, control passes to the Values method in my controller. Within that method I am retrieving the access_token like this:

[Authorize]
    public async Task<IActionResult> Values()
    {
        string accessToken = await HttpContext.GetTokenAsync("access_token");

        var client = new RestClient("http://localhost:3010/api/private");
        var request = new RestRequest(Method.GET);
        request.AddHeader("authorization", $"Bearer {accessToken}");
        IRestResponse response = client.Execute(request);

        return View();
    }

I know that the user is authenticated because I have the Authorize attribute on the Values method. Within the method you can see that I am obtaining the access_token and attempting to pass it as a bearer token to my API. However, no matter what I try, I am getting a 401 Unauthorized response.

I have verified the body of the access_token. Here’s what that looks like:

{
  "iss": "https://centurysoftwaretech.auth0.com/",
  "sub": "auth0|5d375597fd9aa60eff16fe3d",
  "aud": [
    "http://localhost/auth0testapi",
    "https://centurysoftwaretech.auth0.com/userinfo"
  ],
  "iat": 1563918460,
  "exp": 1564004860,
  "azp": "THE_CLIENTID_OF_MY_APPLICATION_ NOT_MY_API",
  "scope": "openid read:messages"
}

I have replaced the azp claim value above with an observation. As far as I can tell, the only bit of information that has anything to do with my API is the “http://localhost/auth0testapi” aud claim… What can I be missing?

The title of my topic states that I am confused by the API Test tab C# code. I am because on that tab it shows that I should make the following call and then retrieve the access_ token from that. But my user is already authenticated! Do I need to do this again?

var client = new RestClient("https://centurysoftwaretech.auth0.com/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"client_id\":\"THE_CLIENTID_OF_MY_API\",\"client_secret\":\"MY_CLIENT_SECRET\",\"audience\":\"http://localhost/auth0testapi\",\"grant_type\":\"client_credentials\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

So in my Values method do I have to call the code above, then extract the access_token, and then call my API? I am confused.

Hi @jlavallet,

Welcome to the Auth0 Community Forum!

I am wondering if you have authorized the app to access the api in the Auth0 dashboard, like mentioned here:

Let me know if this was the issue otherwise we can move forward with other troubleshooting.

Thanks,
Dan

Hi @dan.woda, thank you for your reply.

Yes, I double checked by following those instructions you gave me. After working with the situation a couple of days, I am convinced that my problem has something to do with either my understanding of what the access_token conveys or my implementation of the JWT token handling in my API.

In the last code example I gave above I am requesting a client_credentials grant type. Should I expect the authenticated user’s identity to be a part of the access_token? I would think that the identity of that user comes in through the sub claim. When I get into my API, I am unable to execute any ASP.NET Core Web API controller method (endpoint) that has the [Authorize] attribute. I get back an Unauthorized response. It would seem that ASP.NET Core and the Authorization middleware have not coordinated to associate the User principal object with the identity of the calling user. A step beyond that, if my access_token includes the read:messages scope, which I can verify that it does, a call to an endpoint with the [Authorize(“read:messages”)] attribute also does not work. I have very carefully followed the example provided by Auth0 in this quick start: Auth0 ASP.NET Core Web API SDK Quickstarts: Authorization and, according to that quick start, what I am trying to do should just work.

Please advise.

Thanks,
Jack

@jlavallet,

Thanks for providing that extra context. It’s good to know what you are starting with. Can you send me a private DM with your tenant name, and the first few digits of the client id of the application you are trying to access the API with?

Thanks,
Dan

1 Like

Hi @dan.woda, I clicked on your username and then clicked the Message button. Hopefully that is what you were referring to by a private DM.

I thought I might include the contents of my Startup.cs file. Do I need to add anything to this to make authorization work? Do I need to add a call to AddOpenIdConnect or anything else like that? Nothing like that was shown in the quick start.

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddCors(options =>
            {
                options.AddPolicy("AllowSpecificOrigin",
                    builder =>
                    {
                        builder
                        .WithOrigins("*") //http://localhost:3000
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
                    });
            });

            var domain = $"https://{Configuration["Auth0:Domain"]}/";
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            }).AddJwtBearer(options =>
            {
                options.Authority = domain;
                options.Audience = Configuration["Auth0:ApiIdentifier"];
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("read:values", policy => policy.Requirements.Add(new HasScopeRequirement("read:values", domain)));
                options.AddPolicy("write:values", policy => policy.Requirements.Add(new HasScopeRequirement("write:values", domain)));
                options.AddPolicy("read:messages", policy => policy.Requirements.Add(new HasScopeRequirement("read:messages", domain)));
            });

            // Register the scope authorization handler
            services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();

            app.UseCors("AllowSpecificOrigin");
            app.UseMvc();

            app.UseAuthentication();
        }
    }

I totally figured it out! It was a stupid oversight!

Look at the order of the app.UseAuthentication() call in relation to the app.UseMvc() call.

It’s kind of important to do authentication before routing.

Once I moved the app.UseAuthentication() call ahead of the app.UseMvc() call everything worked as advertised.

Thanks for your help @dan.woda. I’m on to my next challenge.

Ahhh! Nice, glad that you figured it out!

Good luck with your next one :+1:

Thanks,
Dan

Hi @dan.woda,

Thought I would let you know that this morning I was reviewing the process I had gone through to get authorization working. I realized that the problem with the middleware configuration that I reported was not my own doing. The ASP.NET Core Web API v2.0: Authorization quick start provides a downloadable sample. I verified that the code provided in that download contains the middleware misconfiguration. This cost me several days of work. I thought I should let someone know about this at Auth0. Please see my solution.

Thanks,
Jack

Hi @jlavallet,

I apologize for the issues, and thank you for your patience and taking the time to report your findings. I am going to try and reproduce the issues then I will report it to the appropriate team. I’ll update here when I get through it.

Thanks again,
Dan

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.

Hi @jlavallet,

Sorry for the delay. I wanted to report back and say this has be fixed. Thanks for the input!

Warm Regards,
Dan

1 Like