I wanted to know the same thing and couldn't find any answers on the web, so I cloned the Microsoft.AspNetCore.Security (v2.1) repo to see if I could figure out how it worked. I believe this is what you are looking for. Add this to your ConfigureServices method in the Startup.cs file.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o => o.LoginPath = new PathString("/login"))
// You must first create an app with Google and add its ID and Secret to your user-secrets.
// https://console.developers.google.com/project
.AddGoogle(o =>
{
o.ClientId = "YOUR_GOOGLE_CLIENT_ID";
o.ClientSecret = "YOUR_GOOGLE_CLIENT_SECRET";
o.AuthorizationEndpoint += "?prompt=consent"; // Hack so we always get a refresh token, it only comes on the first authorization response
o.AccessType = "offline";
o.SaveTokens = true;
o.Events = new OAuthEvents()
{
// There are a number of (optional) events you may want to connect into and add your own claims to the user, or handle a remote failure, etc.
OnRemoteFailure = HandleOnRemoteFailure,
OnCreatingTicket = HandleOnCreatingTicket
};
o.ClaimActions.MapJsonSubKey("urn:google:image", "image", "url");
});
If you want to intercept some of the events to add additional claims to a user, or store them off in a database to apply app level authorization, you can connect in to various OAuthEvents. I placed the following methods at the bottom of the Startup.cs file, inside the Startup Class.
private async Task HandleOnCreatingTicket(OAuthCreatingTicketContext context)
{
var user = context.Identity;
// please use better logic than GivenName. Demonstration purposes only.
if(user.Claims.FirstOrDefault(m=>m.Type==ClaimTypes.GivenName).Value == "MY_FAVORITE_USER")
{
user.AddClaim(new Claim(ClaimTypes.Role, "Administrator"));
}
await Task.CompletedTask;
}
private async Task HandleOnRemoteFailure(RemoteFailureContext context)
{
// add your logic here.
await Task.CompletedTask;
}
Finally, you will need to add a couple of controller actions. I put mine in an AccountController.cs file like this:
public class AccountController : Controller
{
[AllowAnonymous]
[Route("/login")]
public async Task<IActionResult> Login()
{
if (User == null || !User.Identities.Any(identity => identity.IsAuthenticated))
{
// By default the client will be redirect back to the URL that issued the challenge (/login?authtype=foo),
// send them to the home page instead (/).
string returnUrl = HttpContext.Request.Query["ReturnUrl"];
returnUrl = string.IsNullOrEmpty(returnUrl) ? "/" : returnUrl;
await HttpContext.ChallengeAsync("Google", new AuthenticationProperties() { RedirectUri = returnUrl });
}
return View();
}
[Authorize]
[Route("/logout")]
public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme, new AuthenticationProperties() { RedirectUri="/" });
return View();
}
}
I also put a couple of simple views so that once logged-out, a user could click a link to return to home, or to login again or as another user, etc.
This seemed to work for me.