Sign in with Google
Coming from Google’s documentation after expecting this to be easy? Yah, me too.
Here’s how to add Sign-in with Google to your website
{
"id": "1be02c41-4d4e-80d4-9633-c2e533849af5",
"type": "image",
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/a0e28483-01ab-4009-81c1-3139fd1424a5/500f628c-a9b2-4a0e-b0db-258a0f5183b8/CleanShot_2025-03-22_at_15.29.10.png?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Content-Sha256=UNSIGNED-PAYLOAD\u0026X-Amz-Credential=ASIAZI2LB4667IZQTHBL%2F20260601%2Fus-west-2%2Fs3%2Faws4_request\u0026X-Amz-Date=20260601T053648Z\u0026X-Amz-Expires=3600\u0026X-Amz-Security-Token=IQoJb3JpZ2luX2VjEDkaCXVzLXdlc3QtMiJIMEYCIQCABXE1zz9hNvApqvVJjPA2anSfl9G3UevicmmQXdmVRwIhAKojjmeQ3%2FtfoY1aNTu9kElfEW3OWsDTg%2BDKTLk7Rpx3Kv8DCAIQABoMNjM3NDIzMTgzODA1IgyIsk8TAZWOVX2c7zUq3AM8FJPcZamd2IXRJhB6KMWy46APh%2FCdzVp98XI2PIReEaqBTKfuq709GwqJVk83Hd9IIuXCtIe9hOOwcFt%2BcrjOhQ%2BNWs3ta4Fxl2ezgnBmcZiVf4aM5NIW1BZs7Qx746ZAbIFA39POyOMEWGpQ%2FPG%2B1QIGSytKLLbDVfavGzQS1X1By%2FINffp4OsEqbvaCDhwHsa564ovZa79LZstbfmGoZVhwxRx17bJobQI4W9stUunavR3tijFyN5aUfAZJmUamlSus3wNPG3648W1pviZJMs5sYs0gYYB6Q0CnFyGaOCfgRjzKVOGdKo50lXD8q1HUsDxGlJZSHVP%2F3mALVY44xx4CsEGWVtc1A2YTcUMwzcCuc5A0Qw%2FDawbCQfoh3X8R9HwqjdtQPNSDCY3dLdqma%2F70Gfc%2BCZHVwzdeuXjqUa6slXhV4XwY1MhRWNgwu760isbODnz9BT%2Fr6w4vXR3tpAi%2BQUksj%2FxDOXdnKD7Y%2FyGUty6iL94vZiDHVFZx3EeOAkXa5MuseBpLC1RHsnWjbEiFRAsuKV00LEg4D27UOfVGQ78mw1diYbWdfiF2AoT4tAeiVMycr9atlw%2Fr7KX6kyrGhLCXHZc8yGdGiGLbJ1qbobvGurv7zTgQNTDHp%2FPQBjqkAZVWofItBN0B8f6FBQp65tVAVhUt%2BmpcEJhD8dH8jyyMNOqB0ozxAnXWy%2B6Pz%2FujFjHb7q0FCBAIcwH%2BblaeSBRH3DVfpa6reIlaICzuzzLuNXoFchQQ68P%2FW2U6QDBV6oIhhj2o8kmZdI2t3LHEUq71npFob2AP9LrK%2Fl7oUugTEb6RZgwl8%2FzAgnOhPr6xkfZ3gDvaB5oGxtgp3TfoIIQGGcRj\u0026X-Amz-Signature=dc900de5c7287eaf5fb5a7a0b2996d69735e20c39464028f69ada983962a103b\u0026X-Amz-SignedHeaders=host\u0026x-amz-checksum-mode=ENABLED\u0026x-id=GetObject"
}<script src="https://accounts.google.com/gsi/client" async defer></script>
{
"id": "1be02c41-4d4e-800a-abea-e0774ac4fc40",
"type": "code",
"content": [
{
"type": "text",
"content": "\t\t\u003cdiv\n\t\t\tid=\"g_id_onload\"\n\t\t\tdata-client_id={ env.GOOGLE_CLIENT_ID }\n\t\t\tdata-login_uri={ env.GOOGLE_REDIRECT_URL }\n\t\t\tdata-auto_prompt=\"true\"\n\t\t\tdata-cancel_on_tap_outside=\"false\"\n\t\t\u003e\u003c/div\u003e"
}
],
"language": "javascript"
}Creates a POST request to login_uri
https://developers.google.com/identity/gsi/web/guides/verify-google-id-token#node.js
{
"id": "1be02c41-4d4e-802e-9fdc-d43474cb97e0",
"type": "code",
"content": [
{
"type": "text",
"content": "\ttoken, err := r.Cookie(\"g_csrf_token\")\n\tif err != nil {\n\t\thttp.Error(w, \"token not found\", http.StatusBadRequest)\n\t\treturn\n\t}\n\tbodyToken := r.FormValue(\"g_csrf_token\")\n\tif token.Value != bodyToken {\n\t\thttp.Error(w, \"token mismatch\", http.StatusBadRequest)\n\t}\n\n\tcredential := r.FormValue(\"credential\")\n\tpayload, err := idtoken.Validate(r.Context(), credential, c.env.GOOGLE_CLIENT_ID)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t}\n\n\tfor k, v := range payload.Claims {\n\t\tfmt.Printf(\"%v: %v\\n\", k, v)\n\t}\n\tfmt.Println(\"got request\", payload.Subject)\n"
}
],
"language": "javascript"
}sub is the unique ID you should be storing in your database
Don’t use email as an identifier because a Google account can have multiple emails at different points in time