1

I have a .NET Core Web API that accepts a JWT bearer token from a Google sign-in button for authentication. It appears that authentication is succeeding as I am able to get the ClaimsPrincipal from the HttpContext.User in my controller methods. However, when I add the [Authorize] attribute to my controller, I get back a 403 for failed authorization. I believe I am using the default authorization which should allow any authenticated user. What am I missing?

Here is the SecurityTokenValidator that I am using:

        public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
        {
            var payload = GoogleJsonWebSignature.ValidateAsync(securityToken, _validationSettings).Result;
            validatedToken = _jwtHandler.ReadJwtToken(securityToken);

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, payload.Name),
                new Claim(ClaimTypes.Name, payload.Name),
                new Claim(JwtRegisteredClaimNames.FamilyName, payload.FamilyName),
                new Claim(JwtRegisteredClaimNames.GivenName, payload.GivenName),
                new Claim(JwtRegisteredClaimNames.Email, payload.Email),
                new Claim(JwtRegisteredClaimNames.Sub, payload.Subject),
                new Claim(JwtRegisteredClaimNames.Iss, payload.Issuer),
            };

            var principal = new ClaimsPrincipal();
            principal.AddIdentity(new ClaimsIdentity(claims));
            return principal;
        }

Here is where I wire that up in Startup.cs:

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(o =>
            {
                var googleClientId = Configuration[ConfigurationKeys.GoogleClientId];
                if(googleClientId == null)
                {
                    throw new Exception($"Configuration property not found: {ConfigurationKeys.GoogleClientId}");
                }
                var validationSettings = new ValidationSettings();
                validationSettings.Audience = new List<string> { googleClientId };

                o.SecurityTokenValidators.Clear();
                o.SecurityTokenValidators.Add(new GoogleSecurityTokenValidator(validationSettings));
            });

Here is where I configure the app:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseCors(x => x
                .AllowAnyMethod()
                .AllowAnyHeader()
                .SetIsOriginAllowed(origin => true)
                .AllowCredentials()
            );

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
  • Try to use F12 developer tools or Fiddler to check the request header, whether it contains the JWT token or not? Besides, you can also try to decode the JWT token, whether it contains the claims or not? – Zhi Lv Aug 22 '22 at 08:52
  • The JWT has claims. I am able to read the user's name, email, etc. which gets turned into a ClaimsPrincipal and ClaimsIdentity which becomes accessible in the Controller via the HttpContext.User property. Does this imply that I have an authenticated user? – Thomas Kendall Aug 22 '22 at 12:16
  • I just noticed that, even though I have a ClaimsIdentity, the IsAuthenticated property of it is false. How can I tell why it is false? Did I miss an authentication step somewhere? – Thomas Kendall Aug 22 '22 at 12:23

1 Answers1

1

I have finally found the problem. When creating a ClaimsIdentity object, the AuthenticationType needs to be specified. For my solution, I changed set it to JwtBearerDefaults.AuthenticationScheme although I'm not sure that is correct.

principal.AddIdentity(new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme));

I found the answer here: https://stackoverflow.com/a/20254797/3984834