I have a .NET Core 3.1 API for the backend and an Angular frontend. The auth between the two is fine, done using JWT token.
Now, because I need to integrate with another app, I'm adding cookie authentication to the API using this instruction blog. Something like this in Startup.cs
:
services.AddAuthentication()
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, opt =>
{
opt.Cookie.Name = ".SharedCookie";
opt.Cookie.Path = "/";
opt.Cookie.Domain = ".localhost";
opt.SlidingExpiration = true;
opt.ExpireTimeSpan = new TimeSpan(24 * 7, 0, 0);
})
So far so good. The API has an endpoint to register, log in, and sign out. However, I want my API to use the cookie to authorize only. The cookie will be created by another app, not the API or my frontend app.
It means that I have another application (in a different tech stack, e.g., Python, NodeJS) that will take care of the authentication. When the user successfully signs in there, a cookie will supposedly be created and stored in the browser. Then, when the user visits my Angular app and from there, makes requests to my .NET Core API (with the cookie attached), my API can authenticate and authorize based on that cookie.
I have looked around and am not sure what to do on the NET Core side.
For example, from this tutorial, I see that an app can create a cookie like this
res.cookie(
'token',
jwt.sign(
{ username: row.username, email: row.email },
config.secret
),
{
domain: `.my-domain.com`
}
);
How can my NET Core API consume this? I'm asking so because it seems the cookie created by NET API is in a different format. I can either change the NET API or change the cookie format created by 3rd-party apps.
Many thanks in advance.
CodePudding user response:
As requirement are completely out of any standard. Our best chance might be building our own Authentication scheme. Something like
public class CustomCookieAuthenticationOptions : AuthenticationSchemeOptions
{
}
public class CustomCookieAuthenticationHandler : AuthenticationHandler<CustomCookieAuthenticationOptions>
{
public CustomCookieAuthenticationHandler(IOptionsMonitor<CustomCookieAuthenticationOptions> options, ILoggerFactory logger,
UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (Request.Cookies.TryGetValue("myCookie", out var customCookie))
{
// Some process to extract data was needed from the cookie and build ticket like below
var cookieClaims = new[]
{
new Claim(ClaimTypes.NameIdentifier, "PreviousProcessValueOne"),
new Claim(ClaimTypes.Email, "PreviousProcessValueTwo"),
new Claim(ClaimTypes.Name, "PreviousProcessValueThree")
};
var cookieClaimsIdentity = new ClaimsIdentity(cookieClaims, nameof(CustomCookieAuthenticationHandler));
var customTicket = new AuthenticationTicket(new ClaimsPrincipal(cookieClaimsIdentity), Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(customTicket));
}
return Task.FromResult(AuthenticateResult.Fail("Cookie not presented!"));
}
}
Then register it with authentication process
services.AddAuthentication(opts => opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer()
.AddScheme<CustomCookieAuthenticationOptions, CustomCookieAuthenticationHandler>("MyCustomCookieScheme", null);
When using it to guard our endpoints like
[Authorize(AuthenticationSchemes = "MyCustomCookieScheme")]
public IActionResult TestAuthentication()
{
return Ok("Authenticated!");
}