I have a webpage which uses multiple URLS for the same application:
for example: *.MyWebPage.com.au *.YourWebPage.com.au
So it will use subdomains on
Addition to @michael's answer: How to "handle the deletecookie event, adding options.Domain = RemoveSubdomain(context.Request.Host.Host)": just add
options.Domain= RemoveSubdomain(context.Request.Host.Host);
before
ConcreteManager.DeleteCookie(context, key, options);
in
CookieManager.DeleteCoockie(..){..};
And don't forget to call CookieManager.DeleteCoockie on logout!
PS Also, if you need to be able to login both on subdomain.example.com and on example.com - you need to modify AppendResponseCookie(..){..}, or you will get only TLD (.com/.ru etc) here
How many main domains are there? If there are not too many, you can add several CookieAuthenticationOptions. Like this:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "mywebpage.com.au",
CookieDomain = "mywebpage.com.au",
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "yourwebpage.com.au",
CookieDomain = "yourwebpage.com.au",
});
If there are too many main domains, you will need to write your own cookie provider.
What I didnt realise when I started was the difference between Identity and CookieAuthentication. Since I was using Identity
app.UseIdentity();
app.UseCookieAuthentication was not the solution.
I finally found my solution by implementing ICookieManager.
Here is my solution:
in Startup.cs:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequiredLength = 5;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Cookies.ApplicationCookie.CookieManager = new CookieManager(); //Magic happens here
}).AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
now in a class I have called CookieManager.cs:
public class CookieManager : ICookieManager
{
#region Private Members
private readonly ICookieManager ConcreteManager;
#endregion
#region Prvate Methods
private string RemoveSubdomain(string host)
{
var splitHostname = host.Split('.');
//if not localhost
if (splitHostname.Length > 1)
{
return string.Join(".", splitHostname.Skip(1));
}
else
{
return host;
}
}
#endregion
#region Public Methods
public CookieManager()
{
ConcreteManager = new ChunkingCookieManager();
}
public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
{
options.Domain = RemoveSubdomain(context.Request.Host.Host); //Set the Cookie Domain using the request from host
ConcreteManager.AppendResponseCookie(context, key, value, options);
}
public void DeleteCookie(HttpContext context, string key, CookieOptions options)
{
ConcreteManager.DeleteCookie(context, key, options);
}
public string GetRequestCookie(HttpContext context, string key)
{
return ConcreteManager.GetRequestCookie(context, key);
}
#endregion
In addition to @michael's solution:
ICookie
: ICookie Interface
is an abstraction layer on top of http cookie object
, which secures the data
.ICookieManager
: Cookie Manager
is an abstraction layer on top of ICookie Interface
. This extends the Cookie behavior in terms of <TSource>
generic support, Func<TResult>
.This is implemented by DefaultCookieManager
class. ICookie Interface
is a depedenacy of this class.Usage of CookieManager
:
CookieManager
in startup Configure Service.git
by Nemi Chand.