How to get identity values from google external provider in ASP.NET Core Web API

Viewed 522
    [ApiController]
    [Route("[controller]")]
    public class AuthController : ControllerBase
    {
        private readonly SignInManager<IdentityUser> _signInManager;

        public AuthController(SignInManager<IdentityUser> signInManager)
        {
            _signInManager = signInManager ?? throw new ArgumentNullException(nameof(signInManager));
        }

        [HttpGet("token")]
        public ChallengeResult Token()
        {
            var properties = new GoogleChallengeProperties
            {
                RedirectUri = "/auth/retrieve",
                AllowRefresh = true,
            };

            return Challenge(properties, "Google");
        }

        [HttpGet("[action]")]
        public async Task Retrieve()
        {
            var token = await HttpContext.GetTokenAsync("access_token");
            var externalLoginInfoAsync = await _signInManager.GetExternalLoginInfoAsync();
            var identityName = User?.Identity?.Name;
            var authenticateResult = await HttpContext.AuthenticateAsync();
        }
    }

I direct the user to /auth/token, where he is redirected to the Google Oauth Page, if successful, he is redirected to /auth/retrieve, where I expect the user data, but token, externalLoginInfoAsync, identityName, authenticateResult is null

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseNpgsql(Configuration.GetConnectionString("Default")));
            services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddAuthentication()
                .AddCookie()
                .AddGoogle(options =>
                {
                    options.Scope.Add("https://www.googleapis.com/auth/gmail.settings.basic");
                    options.AccessType = "offline";
                    options.SaveTokens = true;
                    options.SignInScheme = IdentityConstants.ExternalScheme;
                    options.Events.OnCreatingTicket = ctx =>
                    {
                        var identityName = ctx.Identity.Name;
                        return Task.CompletedTask;
                    };

                    options.ClientId = "SMTH_VALUE";
                    options.ClientSecret = "SMTH_VALUE";
                });

            services.AddControllers();
        }

I debug the google provider and found the user values in the Events - identityName is not null. How i can get this value in the controller?

1 Answers

You could refer the following code to configure Google authentication in Startup.ConfigureServices method:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddAuthentication()
            .AddGoogle(opt =>
            {
                opt.ClientId = "620831551062-rcvu44q4rhr5d8ossu3m0163jqbjdji0.apps.googleusercontent.com";
                opt.ClientSecret = "GXFN0cHBbUlZ6nYLD7a7-cT8";
                opt.SignInScheme = IdentityConstants.ExternalScheme;
            });
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

Then, use the following sample to login using Google and get user information:

[Authorize]
public class AccountController : Controller
{
    private UserManager<ApplicationUser> userManager;
    private SignInManager<ApplicationUser> signInManager;

    public AccountController(UserManager<ApplicationUser> userMgr, SignInManager<ApplicationUser> signinMgr)
    {
        userManager = userMgr;
        signInManager = signinMgr;
    }

    // other methods

    public IActionResult AccessDenied()
    {
        return View();
    }

    [AllowAnonymous]
    public IActionResult GoogleLogin()
    {
        string redirectUrl = Url.Action("GoogleResponse", "Account");
        var properties = signInManager.ConfigureExternalAuthenticationProperties("Google", redirectUrl);
        return new ChallengeResult("Google", properties);
    }

    public IActionResult Login()
    {
        return View();
    }

    [AllowAnonymous]
    public async Task<IActionResult> GoogleResponse()
    {
        ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync();
        if (info == null)
            return RedirectToAction(nameof(Login));

        var result = await signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);
        string[] userInfo = { info.Principal.FindFirst(ClaimTypes.Name).Value, info.Principal.FindFirst(ClaimTypes.Email).Value };
        if (result.Succeeded)
            return View(userInfo);
        else
        {
            ApplicationUser  user = new ApplicationUser
            {
                Email = info.Principal.FindFirst(ClaimTypes.Email).Value,
                UserName = info.Principal.FindFirst(ClaimTypes.Email).Value
            };

            IdentityResult identResult = await userManager.CreateAsync(user);
            if (identResult.Succeeded)
            {
                identResult = await userManager.AddLoginAsync(user, info);
                if (identResult.Succeeded)
                {
                    await signInManager.SignInAsync(user, false);
                    return View(userInfo);
                }
            }
            return AccessDenied();
        }
    }
}

The result like this:

enter image description here

More detail information, see How to integrate Google login feature in ASP.NET Core Identity and Google external login setup in ASP.NET Core

Related