简体   繁体   中英

How to configure .net core to send authentication cookies to different domain

I am trying to use cookies with frontend which domain is different than backend's domain. Backend is implemented with .net core and frontend is Angular. I have researched that I need to set withCredentials: true when making http calls. But when I set it to true I get this error:

Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. I have been trying to set CORS and Cookie settings to work with this situation. Here is my relevant code from StartUp.cs. Cors settings:

services.AddCors(options =>
        {
            options.AddPolicy("AllowDomainOrigin",
                builder =>
                {
                    builder
                        .WithOrigins("http://some.domain.net")
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
            options.AddPolicy("AllowForLocalhost",
                builder =>
                {
                    builder
                        .WithOrigins("http://localhost:4200")
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
        });
services.AddSession(options =>
        {
            options.Cookie.SameSite = SameSiteMode.None;
        });
...
        app.UseCors("AllowDomainOrigin");
        app.UseCors("AllowForLocalhost");

Cookie settings:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => 
            {
                options.Cookie.Domain = "some.domain.net";
                options.Cookie.Name = "access_token";
                options.Cookie.SameSite = SameSiteMode.None;
                options.LoginPath = "/login";
                options.LogoutPath = "/login";
            })
            .AddCookie("localhost", options => 
            {
                options.Cookie.Domain = "localhost";
                options.Cookie.Name = "localhost_access_token";
                options.Cookie.SameSite = SameSiteMode.None;
                options.LoginPath = "/login";
                options.LogoutPath = "/login";
            })
            .AddCookie("othercloud", options => 
            {
                options.Cookie.Domain = "domain.com";
                options.Cookie.Name = "musiple_access_token";
                options.Cookie.SameSite = SameSiteMode.None;
                options.LoginPath = "/login";
                options.LogoutPath = "/login";
            })
            .AddJwtBearer(options => 
            {
                options.TokenValidationParameters = tokenValidationParameters;
            });

Here is how I login to HttpContext in login controller:

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync("localhost");
await HttpContext.SignOutAsync("othercloud");
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(identity),
            authProperties);
await HttpContext.SignInAsync("localhost",
            new ClaimsPrincipal(identity),
            authProperties);
await HttpContext.SignInAsync("othercloud",
            new ClaimsPrincipal(identity),
            authProperties);

And here is my endpoint for audio files:

[HttpGet("{id}")]
[Authorize(AuthenticationSchemes= CookieAuthenticationDefaults.AuthenticationScheme +", localhost, othercloud")]
public async Task<FileStreamResult> Get(int id)

So as you see I also use JWT token with authentication. I need cookies because I download mp3 file from my REST API using audio element and I'm setting audio elements src directly to my REST API address. So I can't set JWT to header when using audio element. Cookies was working well in this situation when my frontend was at same domain as backend but now I'm trying to move frontend to other server and domain as well.

How do I need to configure backend to get cookies from different domain?

My backend is on Azure. There is also some CORS settings where I remove * and replaced it with spesific address. Does this have something to do with this?

EDIT:

After I found Azure CORS settings, Exception changed to this:

Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'

EDIT 2:

You need to remove all CORS settings from Azure to get your .net core cors settings to get cors control. Still no success but maybe little closer the solution.

Finally I got it working. As I say in my edit comment, main reason was azures CORS settings. After I remove them I get my .net core settings to hit in. Here is my final solution: Cookie settings:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => 
            {
                options.Cookie.Name = "access_token";
                options.Cookie.SameSite = SameSiteMode.None;
            })
            .AddJwtBearer(options => 
            {
                options.TokenValidationParameters = tokenValidationParameters;
            });

CORS settings:

services.AddCors(options =>
        {
            options.AddPolicy("AllowAllOrigins",
                builder =>
                {
                    builder
                        .AllowAnyOrigin()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
        });
...

app.UseCors("AllowAllOrigins");

Here is related code from login in backend:

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

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

And this was enough in my audio controller endpoint

[HttpGet("{id}")]
[Authorize()]
public async Task<FileStreamResult> Get(int id)

And in frontend I set withCredentials: true when I make login call.

I now this is quite unsecure when I have AllowAnyOrigin instead of WithOrigin, but for some reason I didn't get it working with WithOrigin.

For those who are reading this and are using .net Core in azure and want use CORS remove your CORS settings from Azure and handle them in .net core because in .net core there is much more configurations than in CORS in azure. Here is some what I found from internet:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM