Home > other >  Google Sign-in with existing ASP.NET MVC Application
Google Sign-in with existing ASP.NET MVC Application

Time:12-31

I'm trying to handle google-signin to my existing ASP.NET MVC application. It has a forms authentication developped customely and it works fine for username and password.

I want to add Google-sign-in to this project. I currently added the button, created the app in google developper console got my id and secret and set up the urls.

I can see the button in login page, click, i see my account and picture, select account. At this point google posts me some data. I received in an Action method an string array object called "credential" which has a string in first position. But I don't know what to do from here on...

Can somebody help me with this? Which document I should use?

I'm reading this: https://developers.google.com/identity/gsi/web till now but i'm stuck.

What I dont want is this: https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on

I want to handle the requests needed myself (with cookies, database checks and keeping track of tokens) and get the user information google provides by myself in my controller's action methods.

Here is a part of the razor view code

<div id="g_id_onload"
         data-client_id="my id is here"
         data-login_uri="@Url.Action("LoginWithGoogle","Login")"
         data-auto_prompt="false">
    </div>
    <div 
         data-type="standard"
         data-size="large"
         data-theme="outline"
         data-text="sign_in_with"
         data-shape="rectangular"
         data-logo_alignment="left"
         data-auto_prompt="true"
         >
    </div>

I added this script:

<script src="https://accounts.google.com/gsi/client" async defer></script>

This Action method can catch the string:

[HttpPost]
public ActionResult LoginWithGoogle(string[] credential)
{
    ViewBag.Data = credential;
    ///I will do necessary stuff here.
    return View();
}

Notes:

-Identity is not installed and will not be used (if unless impossible without using it).

-My .Net Framework version: 4.7.2

Thanks for the help.

CodePudding user response:

I don't use "full" default auth code too, here is how I handle Google/Yandex/Discord/OAuth response:

[HttpPost]
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string? returnUrl = null)
{
    var redirectUrl = Url.Action(nameof(ExternalLoginCallback), null, new { returnUrl });
    var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
    return new ChallengeResult(provider, properties);
}

[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string? returnUrl = null)
{
    var info = await signInManager.GetExternalLoginInfoAsync();
    if (info == null)
    {
        return this.Redirect(LoginPath);
    }

    var email = info.Principal.FindFirstValue(ClaimTypes.Email);
    var name = info.Principal.FindFirstValue(ClaimTypes.Name) ?? info.Principal.Identity.Name;

    // your own actions & checks with email, name etc

This still required some "default" preparations in Startup:

services.AddIdentity<User, UserStoreService.UserRole>()
    .AddUserStore<UserStoreService>()
    .AddRoleStore<UserStoreService>()
    .AddDefaultTokenProviders();
services.AddAuthentication().AddGoogle(...)

But here User is my own class, UserRole is own (end empty) class, and UserStoreService is my own implementation of IDisposable, IUserStore<User>, IUserEmailStore<User>, IUserClaimStore<User>, IUserSecurityStampStore<User>, IRoleStore<UserStoreService.UserRole> (you may modify this list according to your needs)

CodePudding user response:

This is example how to process external authentication using owin. First of all, you have to setup your startup.cs and update configuration with something like this. Of course you have to import required packages into your project.

    public void Configuration(IAppBuilder app)
    {
        ....

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
        {
            ClientId = "YourGoogleClientId",
            ClientSecret = "YourGoogleClientSecret",
        });
    }

Then in your account controller (example name) create method that will handle your login with google button. For example:

    public ActionResult ExternalLogin(string provider)
    {
        var returnUrl = Request.Url.GetLeftPart(UriPartial.Authority)   "/Account/ExternalLoginCallback";

        return new ChallengeResult(provider, returnUrl);
    }

Create your ChallengeResult method:

internal class ChallengeResult : HttpUnauthorizedResult
{
    public ChallengeResult(string provider, string redirectUrl)
    {
        LoginProvider = provider;
        RedirectUri = redirectUrl;
    }

    public string LoginProvider { get; set; }
    public string RedirectUri { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        var properties = new AuthenticationProperties { RedirectUri = RedirectUri };

        var owin = context.HttpContext.GetOwinContext();

        owin.Authentication.Challenge(properties, LoginProvider);
    }
}

Add your new authentication method in your account controller. For example:

    public async Task<ActionResult> ExternalLoginCallback()
    {

        try
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

            if (loginInfo == null || string.IsNullOrEmpty(loginInfo.Email))
            {
                return RedirectToAction("ExternalLoginFailed", "WebAccount");
            }
            else
            {
            // handle external login, means process user login in your system
            }
        }
        catch (Exception ex)
        {
           // handle possible exceptions
        }

        return RedirectToAction("ExternalLoginFailed", "WebAccount");
    }

    private IAuthenticationManager AuthenticationManager
    {
        get { return HttpContext.GetOwinContext().Authentication; }
    }
  • Related