EasyReasy.Auth.Google 1.3.0

dotnet add package EasyReasy.Auth.Google --version 1.3.0
                    
NuGet\Install-Package EasyReasy.Auth.Google -Version 1.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EasyReasy.Auth.Google" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EasyReasy.Auth.Google" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="EasyReasy.Auth.Google" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EasyReasy.Auth.Google --version 1.3.0
                    
#r "nuget: EasyReasy.Auth.Google, 1.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EasyReasy.Auth.Google@1.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EasyReasy.Auth.Google&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=EasyReasy.Auth.Google&version=1.3.0
                    
Install as a Cake Tool

EasyReasy.Auth.Google

Google Sign-In integration for the EasyReasy.Auth JWT authentication pipeline. Validates Google ID tokens and lets your application issue the same JWTs (and optional refresh tokens) as any other auth method.

Quick Start

1. Install

dotnet add package EasyReasy.Auth.Google

2. Implement IGoogleAuthHandler

This is where you decide what happens after a Google user is verified - look them up, create them, assign claims and roles, and build the JWT:

public class MyGoogleAuthHandler : IGoogleAuthHandler
{
    private readonly IUserRepository _users;

    public MyGoogleAuthHandler(IUserRepository users)
    {
        _users = users;
    }

    public async Task<AuthResponse?> HandleGoogleUserAsync(
        GoogleUserInfo userInfo,
        IJwtTokenService jwtTokenService,
        IRefreshTokenService? refreshTokenService,
        HttpContext? httpContext)
    {
        User user = await _users.FindOrCreateByGoogleSubjectAsync(
            userInfo.Subject, userInfo.Email, userInfo.Name);

        DateTime expiresAt = DateTime.UtcNow.AddHours(1);
        string token = jwtTokenService.CreateToken(
            subject: user.Id.ToString(),
            authType: "user",
            additionalClaims: [],
            roles: user.Roles,
            expiresAt: expiresAt);

        string? refreshToken = null;
        if (refreshTokenService != null)
        {
            refreshToken = await refreshTokenService.CreateRefreshTokenAsync(
                user.Id.ToString(), "user", null, null);
        }

        return new AuthResponse(token, expiresAt.ToString("o"), refreshToken);
    }
}

3. Register Services

// In Program.cs
builder.Services.AddEasyReasyAuth(jwtSecret);
builder.Services.AddEasyReasyGoogleAuth(googleClientId: "your-client-id.apps.googleusercontent.com");
builder.Services.AddScoped<IGoogleAuthHandler, MyGoogleAuthHandler>();

WebApplication app = builder.Build();

app.UseEasyReasyAuth();
app.AddGoogleAuthEndpoint();   // POST /api/auth/google

The built-in EasyReasy.Auth endpoints are added separately with app.AddAuthEndpoints(...), which needs an IAuthRequestValidationService for API key and username/password sign-in and an IRefreshTokenService for refresh and logout; see the EasyReasy.Auth README.

Flow

  1. Frontend uses Google's JavaScript SDK - user consents - frontend gets a Google ID token
  2. Frontend sends POST /api/auth/google with { "idToken": "..." }
  3. Library validates the ID token against Google's public keys
  4. Library enforces the hosted-domain allowlist and email-verification policy, then extracts GoogleUserInfo (subject, email, email-verified, name, picture URL)
  5. Library calls your IGoogleAuthHandler.HandleGoogleUserAsync
  6. You look up or create the user, issue a JWT via IJwtTokenService, optionally create a refresh token
  7. AuthResponse (token, expiration, optional refresh token) is returned to the frontend

Configuration

Restrict to Google Workspace Domains

builder.Services.AddEasyReasyGoogleAuth(
    googleClientId: "your-client-id.apps.googleusercontent.com",
    allowedHostedDomains: new[] { "yourcompany.com" });

When allowedHostedDomains is set, only users whose Google account belongs to one of those domains will be accepted. All other tokens are rejected. Domain matching is case-insensitive.

Email Verification

By default, accounts whose email address is not verified by Google (the token's email_verified claim is false) are rejected, matching Google's guidance that an unverified email must not be trusted as an identifier. If your application does not rely on the email address for identity, opt out:

builder.Services.AddEasyReasyGoogleAuth(
    googleClientId: "your-client-id.apps.googleusercontent.com",
    requireVerifiedEmail: false);

Either way, the verification state is exposed on GoogleUserInfo.EmailVerified so your IGoogleAuthHandler can make its own decision.

Endpoint Behavior

AddGoogleAuthEndpoint maps POST /api/auth/google, sharing two properties with the built-in EasyReasy.Auth endpoints:

  • It is anonymous, so it stays reachable even when the application applies a global authorization policy.
  • It sets Cache-Control: no-store, so the issued token is never cached by browsers or proxies.

Beyond those two, read each endpoint's own contract rather than assuming parity: this endpoint passes the supplied idToken to the validator as it stands, and the EasyReasy.Auth credential endpoints document their own request handling in that package's README.

When EasyReasyAuthOptions.CookieTokenPaths is non-empty, a successful sign-in also sets the __Secure-access_token cookie through the same call the built-in login endpoint makes, so a user who signs in with Google can open a protected file in a new tab without waiting for the first refresh. A rejected sign-in sets no cookie, the JSON response is unchanged, and with the option empty nothing changes. A token too large for the cookie does not fail the sign-in: the cookie is expired instead and EasyReasy.Auth logs an error naming the size and the limit. Clearing the cookie on a failed refresh or on logout is the job of the EasyReasy.Auth refresh and logout endpoints. See "Opening Files in a New Tab" in the EasyReasy.Auth README for the rules and what stays with your application.

Audit Logging

Google sign-in flows into the same audit pipeline as every other EasyReasy.Auth event. If you register an IAuthAuditLogger (see the EasyReasy.Auth README, "Security Audit Logging"), the endpoint invokes OnExternalAuthAsync after every attempt — success or failure — before the response is written:

public class MyAuditLogger : IAuthAuditLogger
{
    private readonly ILogger<MyAuditLogger> _logger;

    public MyAuditLogger(ILogger<MyAuditLogger> logger) { _logger = logger; }

    public Task OnExternalAuthAsync(HttpContext ctx, ExternalAuthResult result)
    {
        _logger.LogInformation(
            "auth.external {Provider} {Outcome} subject={Subject} reason={Reason} ip={Ip}",
            result.Provider,                                  // "google"
            result.Success ? "success" : "failure",
            result.AttemptedSubject,
            result.FailureReason,
            ctx.Connection.RemoteIpAddress);
        return Task.CompletedTask;
    }
}

The ExternalAuthResult.FailureReason is InvalidToken when the Google ID token fails validation (bad signature, expiry, audience mismatch, a disallowed hosted domain, or an unverified email) and Rejected when your IGoogleAuthHandler returns null to decline an otherwise-valid identity. As with the other result types, log the metadata shown above — never the whole result, because on success it embeds the issued bearer token.

Models

GoogleUserInfo

Property Type Description
Subject string (required) Google's stable unique user ID (the sub claim)
Email string (required) The user's email address
EmailVerified bool (required) Whether Google has verified the user owns this email (the email_verified claim)
Name string? Display name, or null
PictureUrl string? Profile picture URL, or null

GoogleAuthRequest

Property Type Description
IdToken string The Google ID token from the frontend

Follows the standard EasyReasy serialization pattern: ToJson(), FromJson(string), ToString().

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.0 47 11/7/2026
1.2.0 101 11/2/2026
1.1.1 119 10/3/2026
1.1.0 164 9/10/2026
1.0.0 287 6/16/2026

The Google sign-in endpoint now runs on EasyReasy.Auth's shared ExternalSignInEndpoint, so the no-store header, the audit record, the access-token cookie, the progressive-delay reset and the 200 or 401 happen exactly as for every other provider package. The sign-in itself is unchanged. One behaviour change: when several services the endpoint needs are missing at startup, AddGoogleAuthEndpoint now names all of them in one InvalidOperationException instead of throwing on the first. Requires EasyReasy.Auth 5.14.0. See https://github.com/AdamTovatt/easy-reasy/blob/auth-google-v1.3.0/EasyReasy.Auth.Google/README.md#endpoint-behavior