Paul Meems
Paul Meems

Reputation: 3284

How to combine Google Authentication and API key Authentication using Blazor?

I have a Blazor application using .NET Core 3.1. I use Google authentication to log in as explained in this article, written by @MichaelWashington https://blazorhelpwebsite.com/ViewBlogPost/19
I add [Authorize] to my Controller and only logged in user can access my controller.

I also need to give access to my controller using an API key. I followed this article, written by @JosefOttosson: https://josef.codes/asp-net-core-protect-your-api-with-api-keys/ this is working fine as well when I replace [Authorize] with [Authorize(AuthenticationSchemes = AuthenticationConstants.ApiKeyDefaultScheme)]

But now I don't have access to my controller via my Blazer site. So I added [Authorize(AuthenticationSchemes = AuthenticationConstants.GoogleAuthenticationScheme)] but now I get CORS errors:

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=[...] 
(redirected from 'https://localhost:44380/api/client/2/upload/foo') 
from origin 'https://localhost:44380' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I've tried numerous options but I still keep getting this error. Replacing the two [Authorize(AuthenticationSchemes ... with [Authorize] makes my front-end work again but my Postman call (mimicking a 3rd party call) fails.

How can I combine these two authentication methods?

In public void Configure(IApplicationBuilder app) I have

app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);

app.UseHttpsRedirection();
app.UseStaticFiles();

In public void ConfigureServices(IServiceCollection services) I have at the top:

services.AddCors(options =>
{
    options.AddPolicy(MyAllowSpecificOrigins, builder => builder
         .WithOrigins("http://localhost:44380/")
         .SetIsOriginAllowed((host) => true)
         .AllowAnyMethod()
         .AllowAnyHeader());
});

Upvotes: 1

Views: 493

Answers (1)

Paul Meems
Paul Meems

Reputation: 3284

I finally figured it out. I was banging my head because sometimes it did work and sometimes it didn't. When I logged out and then in again on the frontend using Google Authentication it never worked.
In the Login code

await HttpContext.SignInAsync(
         CookieAuthenticationDefaults.AuthenticationScheme,
         new ClaimsPrincipal(GoogleUser),
         authProperties);

is used. Watch the CookieAuthenticationDefaults.AuthenticationScheme. It is using/setting a different scheme.

So after adding [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] my controller works all the time.

My controller now looks like this:

    [Authorize(AuthenticationSchemes = AuthenticationConstants.GoogleAuthenticationScheme)]
    [Authorize(AuthenticationSchemes = AuthenticationConstants.ApiKeyDefaultScheme)]
    [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
    public class MetaController : BaseApiController

I hope it helps somebody else. It took me two days ;-)

Upvotes: 2

Related Questions