I have been using cookie authentication in my MVC application. But now that I want to introduce Rest APIs in it, I want the cookie authentication to be only on my MVC part of the application. Is there any configuration to not use these return paths when the URL starts from /API
services.ConfigureApplicationCookie(options => {
// Set authentication request paths.
options.LoginPath = "/Identity/Account/Login";
options.LogoutPath = "/Identity/Account/Logout";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
// Set cookies to expire after 2 days.
options.ExpireTimeSpan = TimeSpan.FromDays(2);
// Do not update cookie expiration between logins.
options.SlidingExpiration = false;
// TODO set HttpOnly? set SecurePolicy to Always?
});
I did read the documentation but didn't find any such thing. it is possible with OAuth, but cant find anything in cookie auth.
You shouldn't have to change the URL paths in your setup.
I would use attributes on the controllers you want to protect - and not change your startup options.
Put an [Authorize] tag on the controllers you want to force people to sign in on and leave it off for your API controllers with public access.
Related
I have a .NET 5 MVC5 Application.
It use MVC Areas to run 3 applications.
Each one has a main cookie and depending on wheter user is enabled or not it check for additional auth cookies/claims.
On Chrome I receive this error:
A cookie was not sent to an insecure origin from a secure context. Because this cookie would have been sent across schemes on the same site, it was not sent. This behavior enhances the SameSite attribute’s protection of user data from request forgery by network attackers.
Resolve this issue by migrating your site (as defined by the eTLD+1) entirely to HTTPS. It is also recommended to mark the cookie with the Secure attribute if that is not already the case.
On MSDN I read that you need to work with SameSite:
Working with SameSite
In this article I also read:
SameSite and Identity
ASP.NET Core Identity is largely unaffected by SameSite cookies except for advanced scenarios like IFrames or OpenIdConnect integration.
When using Identity, do not add any cookie providers or call
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme),
Identity takes care of that.
I think this is my case so I'm quite safe I guess.
Nonetheless I wanted to do it because... Knowledge.
I use a login + cookie+claim auth:
services.AddMvc(config =>
{
// Requiring authenticated users on the site globally
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
})
// Authentication
var cookiesConfig = this.Configuration.GetSection("CookiesOptions")
.Get<CookiesOptions>();
services.AddAuthentication(
CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
//Various options
});
services.AddAuthorization(options =>
{
options.AddPolicy("Require.SomePolicy1.User", policy =>
policy.RequireClaim("AAAAA_ENABLED_USER", "true")
.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme)
);
options.AddPolicy("Require.SomePolicy2", policy =>
policy.RequireClaim("AAAAA_CAPA_ENABLED_USER", "true")
.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme)
);
And I wanted to try the SameSite thing with what I've found Here in this article
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.HttpOnly = true;
}
);
Now as you can see down there only the aspnet cookie is set to strict and the others aren't.
How can I set every cookie to strict and remove those chrome warnings?
Microsoft suggestion is to add the request manually to every reponse like this:
// Add the cookie to the response cookie collection
Response.Cookies.Append("MyCookie", "cookieValue", cookieOptions);
but it's quite horrible, even if I do it using an ActionFilter.
Isn't there a way to set it up for every cookie?
I see that
options.Cookie..
Has also a CookieBuilder property. Maybe that's the one to try?
Thanks
In my current project I am using cookie authentication to secure my controllers.
However, for one particular controller (which will simply be used as API controller) I want the endpoints to be secured using Azure AD.
My use case is that the application serves as a website where users log in and the authentication is stored as a cookie. This already works. Now I want to extend a new controller that will be called via a Logic App.
But I only want the Logic App to be able to call this endpoint. So I created a system managed identity for the Logic App and now I want to secure this new API controller/endpoint.
I have read many articles explaining how to implement multiple schemes. But I don't understand how to implement cookie auth + this particular authentication method.
Perhaps a different method is required, thus I am asking it here. Preferably I don't want to edit the existing working code but rather have a [Authorize(Policy = "ManagedApp")] policy at the top of the new controller.
Any help is appreciated, I am pretty of stuck.
Current ConfigureServices method (irrelevant code removed)
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/signin";
options.LogoutPath = "/signout";
// Stuff to store the auth cookie
})
services.AddMvc();
}
From the information you provided, it seems to me that, in order to use policies such as [Authorize(Policy = "ManagedApp")], besides the AddAuthentication(... definition, you will still need to either include:
AddAuthorization
or AddPolicySchemes, depending on your preferences.
I would recommend following this tutorial, which explains both implementations: https://code-maze.com/dotnet-multiple-authentication-schemes/
Please mind that, in order to use exactly [Authorize(Policy = "ManagedApp")], you will need to register a policy named as "ManagedApp".
Concerning the development of front-end and API controllers alongside each other, I wrote this answer some time ago, which may be of interest for your scenario.
In order to authorize all your endpoints by default, you can, for example:
Have different (base) controllers for the front-end and API, and employ a specified Authorize attribute in each of them, then inheriting from those (Microsoft ref);
Or use RequireAuthorization on the endpoints definition, as Andrew Lock suggests here.
Hope this helps!
Whenever I implement authentication and authorization with Azure AD in an ASP.NET Core application, in development environments I require a valid and configured account to sign in and get to the protected pages.
If the environment is development, I'd like to be able to run the app as if a user was signed in by default. For example, any User.Identity.IsAuthenticated value would be true, [Authorize] attributes would be ignored, any usages of IAuthorizationService would react as if the user was fully authorized. How could this be done? Or it would be equally good if when I press to sign in with Microsoft it just automatically "authenticates" on any computer.
I looked through some SO solutions, but they all seem to disable authentication. I can't disable it because if [Authorize] attribute is bypassed but User.Identity.IsAuthenticated returns false, code in my controllers and razor views would break. I want this so that when Selenium runs automatic tests for the UI it does not have to deal with signing into Microsoft, and that anyone who wants to run the app locally isn't required to have an account.
When signing in, I use the action from MicrosoftIdentity at /MicrosoftIdentity/Account/SignIn.
If it helps, here's my ConfigureServices method in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.ExpireTimeSpan = TimeSpan.FromMinutes(Configuration.GetValue<double>("AzureAd:TimeoutInMinutes"));
options.SlidingExpiration = true;
});
RegisterAuthorizationPolicies(services);
services.Configure(OpenIdConnectDefaults.AuthenticationScheme, (Action<OpenIdConnectOptions>)(options =>
{
options.Events.OnTicketReceived = async context =>
{
// I run some code here that determines whether or not to allow the user to sign in.
return;
};
}));
services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
...
}
I'm trying to use a second cookie so that other applications in a subdomain can validate, if a user is logged in in my application. However i don't trust the other applications thats why I'm planning to use two Authentication Cookies. One for my own Application (IdentityCookie) and one so that the other Apps can access the login status (SubCookie).
I'm using ASP.NET Identity for cookie creation and account management.
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>().AddSignInManager<AuthSignInManager<ApplicationUser>>();
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
options.CookieManager = new CookieManager();
});
The custom CookieManager is responsible for creating and deleting both Cookies at the same time.
My issue now is that I can't find a way to validate the cookies. I attempted to use a custom Authenticationhandler for the validation of the subCookie, but if I add the following code the IdentityCookie validation stops working:
services.AddAuthentication("CookieBearer").AddScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>("CookieBearer", o => {});
It seemes like after adding this line only the Custom Handler is used and the one provided by Identity is ignored. Is there any way to add multiple AuthenticationHandlers with ASP.NET Identity? I want to use the custom AuthenticationHandler just as a fallback option. So that if authentication by Identity fails the custom AuthenticationHandler is used.
I know I can chain Authentication Schemes/Methods like this, but I'm not sure how to do it in combination with Identity.
services
.AddAuthentication()
.AddJwtBearer("Custom1", options =>
{
//Configure here
})
.AddJwtBearer("Custom2", options =>
{
// Configure here
});
I am trying to authenticate CORS origin requests and set Claims principle with the user of internal company single sign on utility. I have the current setting so far, the cookie will never get created on the domain set at the authentication setup.
I have an Angular client application and .Net Core 3.0 Webapi, the requirement is for the client to be able to set authentication for future api calls.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Cookie.Name = "access_token";
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.Domain = "localhost:xxxx";
});
//CORS
services.AddCors(options =>
{
options.AddPolicy(
"AllowOrigin",
builder => builder.WithOrigins("localhost:xxxx")
.AllowCredentials()
.AllowAnyHeader()
.AllowAnyMethod());
});
//Sign In
HttpContext.SignInAsync(
scheme: CookieAuthenticationDefaults.AuthenticationScheme,
principal: new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme)),
properties: new AuthenticationProperties { ExpiresUtc = DateTime.Now.Add(120) });
I am testing this all on local so both URLS are localhost with different ports
Angular is hosted: http://localhost:xxxx
WebAPi is hosted :http://localhost:xxx2
http request from Angular to webapi is http://localhost:xxx2/api/auth which has the SignInAsync call, the company single sign does a username but the cookie never gets created. If I remove the options.Cookie.Domain = "localhost:xxxx"; the cookie does get created on the webapi domain http://localhost:xxx2. I must be missing something here.
After reading up some other posts on stackoverflow , it tuned out that AllowAllOrigins will only fix this problem but poses a threat.
So I ended up fixing this issue with JWT - setting authorization token for every request sent from client interface. This issue was caused due to fact that the client and WebApi are hosted on different domains.