Short answer: you should use a custom AuthorizationHandler
to authenticate & retrieve claims.
Long answer: With ASP.NET CORE you should walk away from authentication middleware. Instead you should use an AuthenticationHandler microsoft
To create a custom Authentication handler, you will need to create a new class inheriting from AuthenticationHandler<TOption>
. TOption
is a simple class used to pass parameters to your handler.
public class TecMobileOptions : AuthenticationSchemeOptions
{
// Add your options here
}
public class MyNewHandler : AuthenticationHandler<MyOptions>
{
private readonly ILogger _logger;
public TecMobileHandler(
IOptionsMonitor<MyOptions> options,
ILoggerFactory loggerFactory,
UrlEncoder encoder,
ISystemClock clock) : base(options, loggerFactory, encoder, clock)
{
// Inject here your DbContext
_logger = loggerFactory.CreateLogger("name...");
}
}
Then you will need to implement the HandleAuthenticateAsync method. It will be called by the Auth middleware when necessary:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var authorization = Request.Headers["UserId"].ToString();
(...)
return AuthenticateResult.Success(
new AuthenticationTicket(**your claims**, Scheme.Name));
}
Claims returned by this method will be available through the HttpContext.User object.
Once that done, you will need to add your scheme to the authentication builder.
services.AddAuthentication()
.AddCookie("MyAuthenticationCookie");
.AddScheme<MyOptions, MyHandler>("MyHandlerName");
Don't forget to add in Startup.cs / Configure methods the following code line
app.UseAuthentication();
Finally, you will need to add the Authorize attribute on all classes/methods you want to secure
[Authorize(AuthenticationSchemes = "MyHandlerName")]
public class MyControllerController : BaseController
{ }
OR
[Authorize(AuthenticationSchemes = "MyHandlerName")]
public IActionResult MyMethod()
{ }
EDIT: Here the solution covering the full login process.
Let's consider you define two authentication schemes
- Cookie based is called CookieScheme
- AutoSignInScheme: create the corresponding handler following the steps above
[Authorize(AuthenticationSchemes = "CookieScheme")]
public class SecuredController : Controller
{
(...)
}
Then you will need to add the AccountController
public class AccountController : Controller
{
[HttpGet]
[Authorize(AuthenticationSchemes = "AutoSignInScheme")]
public async Task<IActionResult> AutoSignIn(string returnUrl)
{
await HttpContext.SignInAsync(
"CookieScheme",
new ClaimsPrincipal(new ClaimsIdentity(User.Claims, "CookieScheme")));
return Redirect(returnUrl);
}
}
In your Startup.cs, add the following lines:
services.AddAuthentication()
.AddCookie("CookieScheme", opts =>
{
opts.LoginPath = new PathString("/account/AutoSignIn");
opts.LogoutPath = ** TODO IF REQUIRED **
opts.Cookie.Expiration = TimeSpan.FromHours(8);
})
.AddScheme<MyOptions, MyHandler>("AutoSignInScheme");
When the users tries to access your site, he is redirected to the autosignin controller. Claims are then retrieved from your DB, stored in a cookie and the user is finally redirected to his initial destination!.
Seb