8.7 KiB
Google Sign-In Without Identity
This guide will show you how to implement Google Sign-In without using the Identity framework. While Identity is a great framework, it can be overkill for some applications. Often we just want to use a third-party provider to authenticate a user and use default cookie or JWT authentication for the rest of the application.
Prerequisites
- A Google account
- .NET 8
- Visual Studio 2022
Note: This article assumes you are using a Windows development environment. If you are using a Mac or Linux, you will need to use the appropriate tools for your environment.
Implementation
Create a new .NET Core MVC Application
Open Visual Studio and create a new .NET Core MVC application. You can use the default template. I have called my project GoogleAuthentication
.
::: warning
Ensure that when you create the project the 'None' option is selected for authentication. (Otherwise, you will need to remove the Identity framework later.)
:::
Create a new Account Controller
Create a new blank MVC controller called AccountController.cs
. This controller will be used to handle the Google Sign-In process.
Inject the configuration service into the controller so that we can access the Google Client ID from the appsettings.json
file later.
After creating the controller and injecting the service the code should look like this:
using Microsoft.AspNetCore.Mvc;
namespace GoogleAuthentication.Controllers
{
public class AccountController(IConfiguration configuration) : Controller
{
private readonly IConfiguration _configuration = configuration;
public IActionResult Index()
{
return View();
}
}
}
Create a Login View
We will now add a Login
method to the AccountController
. This method will be used to redirect the user to the Google Sign-In page.
Start by creating a LoginViewModel
in the Models
folder. This view model will be used to pass the Google Client ID to the view.
public class LoginViewModel
{
public string GoogleClientId { get; set; } = null!;
}
Then the following code to the AccountController
class:
public IActionResult Login()
{
LoginViewModel model = new()
{
GoogleClientId = _configuration["GoogleClientId"]!
};
return View(model);
}
This code will create a new LoginViewModel
and pass the Google Client ID from the configuration to the view. At this state we can also remove the default Index
method from the controller as we will not be using it.
Add a new view called Login.cshtml
to the Views/Account
folder. This view will be used to display the Google Sign-In button.
@model LoginViewModel
@{
ViewData["Title"] = "Login";
}
<div class="row">
<div class="column text-center">
<h3>Please sign in with your Google Account</h3>
<hr />
<div id="buttonDiv" class="has-text-centered"></div>
</div>
</div>
<form id="login-form" asp-asp-controller="Account" asp-action="Callback" method="post">
<input type="hidden" name="jwt" />
</form>
@section Scripts {
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
function handleCredentialResponse(response) {
if (response.credential) {
let form = document.getElementById('login-form');
let jwt = document.getElementsByName('jwt')[0];
jwt.value = response.credential;
form.submit();
}
}
window.onload = function () {
google.accounts.id.initialize({
client_id: "@Model.GoogleClientId",
callback: handleCredentialResponse
});
google.accounts.id.renderButton(
document.getElementById("buttonDiv"),
{ theme: "outline", size: "large" } // customization attributes
);
google.accounts.id.prompt(); // also display the One Tap dialog
}
</script>
}
The above code will render the Google Sign-In button and handle the response from Google. When the user signs into google, the handleCredentialResponse
function will be called and the authentication response from Google will be submitted as the data. This function will then submit the form with the JWT token (called credential in the response) as a hidden field.
Create a Callback Method
Start by creating a model to represent the submitted form data.
public class LoginRequestViewModel
{
public string Jwt { get; set; } = string.Empty;
}
We will now create a Callback
method in the AccountController
. This method will be used to handle the response from Google and then perform the authentication step that our appliation requires.
Add the following code to the AccountController
class:
[HttpPost]
public async Task<IActionResult> Callback(LoginRequestViewModel login)
{
// If the jwt token is empty then user is not authorized
if (string.IsNullOrEmpty(login.Jwt))
{
throw new Exception("The jwt token is empty.");
}
// Otherwise we can verify the token with google and get the user's email address
Payload payload = await GoogleJsonWebSignature.ValidateAsync(login.Jwt);
// If the payload is not null and is valid then get the user by email address
if (payload != null)
{
string userEmail = payload.Email!;
// Perform necessary logic to sign in the user here
// e.g. create a cookie, or a JWT token, etc.
// Return the user to the home page
return RedirectToAction("Index", "Home");
}
else
{
// If the payload is null then the user is not authorized
throw new Exception("The payload is null.");
}
}
The above code will retrive the JWT token and then validate it with Google, using the GoogleJsonWebSignature class. This class is provided as part of the nuget package Google.Apis.Auth
. If the token is valid, we can then perform any necessary logic to sign the user in. In this example we will just redirect the user to the home page, however in your own applications should could create a sign-in cookie, create a JWT or start a session.
In this above example if the sign in fails, an exception will be thrown. This will cause the user to be redirected to the error page. In a production application you would want to handle this error more gracefully.
Add the Google Client ID to the Configuration
We will now add the Google Client ID to the configuration. This will allow us to access the value from the appsettings.json
file.
Add the following code to the appsettings.json
file:
{
"GoogleClientId": "YOUR_GOOGLE_CLIENT_ID"
}
To generate a Google Client ID, follow the steps below:
- Go to the Google Cloud Console
- Create a new project
- Go to the Credentials Page
- Click the
Create Credentials
button and selectOAuth client ID
- Select
Web application
as the application type - Enter a name for the application
- Add the following URL to the
Authorized JavaScript origins
section:https://localhost:5001
(replace with your own URL) - Add the following URL to the
Authorized redirect URIs
section:https://localhost:5001/account/callback
(replace with your own URL) - Click the
Create
button - Copy the Client ID and paste it into the
appsettings.json
file
You will also need to setup the consent screen for your application. To do this, follow the steps below:
- Go to the OAuth consent screen
- Select
External
as the user type - Click the
Create
button - Enter a name for the application
- Add the following URL to the
Authorized domains
section:localhost
- Click the
Save and continue
button - Click the
Add or remove scopes
button - Select the
email
andprofile
scopes - Click the
Update
button - Click the
Save and continue
button
Test the Authentication
We will now test the authentication using the Google Sign-In button.
Start the application and then manually update the url to go to the /Account/Login
route. This will redirect you to the Google Sign-In page. Either click the Google Sign-In button or use the one tap feature to sign in with your Google account. You should then be redirected to the home page.
Conclusion
We have now learnt how to implement Google Sign-In without using the Identity framework. This is a great way to add authentication to your application without the overhead of the Identity framework.
This method works well when combined with cookie or JWT authentication. You can use the Google Sign-In to authenticate the user and then use the cookie or JWT to authenticate the user for future requests.