Thomas Kendall
Thomas Kendall

Reputation: 23

.NET Core Authorization fails while Authentication succeeds

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();
            });
        }

Upvotes: 1

Views: 474

Answers (1)

Thomas Kendall
Thomas Kendall

Reputation: 23

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

Upvotes: 1

Related Questions