LeadSoft.Adapter.Google.Workspace
10.1.0
dotnet add package LeadSoft.Adapter.Google.Workspace --version 10.1.0
NuGet\Install-Package LeadSoft.Adapter.Google.Workspace -Version 10.1.0
<PackageReference Include="LeadSoft.Adapter.Google.Workspace" Version="10.1.0" />
<PackageVersion Include="LeadSoft.Adapter.Google.Workspace" Version="10.1.0" />
<PackageReference Include="LeadSoft.Adapter.Google.Workspace" />
paket add LeadSoft.Adapter.Google.Workspace --version 10.1.0
#r "nuget: LeadSoft.Adapter.Google.Workspace, 10.1.0"
#:package LeadSoft.Adapter.Google.Workspace@10.1.0
#addin nuget:?package=LeadSoft.Adapter.Google.Workspace&version=10.1.0
#tool nuget:?package=LeadSoft.Adapter.Google.Workspace&version=10.1.0
LeadSoft® Google Workspace Integration Adapter
LeadSoft.Adapter.Google.Workspace
Adapter .NET para integrar com os serviços de autenticação do Google Workspace — Single Sign-On via OAuth2 e consulta ao perfil expandido do usuário via People API.
Fornece uma camada leve, testável e orientada a interfaces para validação de ID Tokens e recuperação de dados de perfil, encapsulando o SDK do Google, validação de JWT e tratamento de erros de forma consistente para aplicações .NET 10.
Este pacote é um tributo independente e não é afiliado oficialmente ao Google.
Somos gratos pela disponibilização das APIs públicas do Google Identity e do Google People API. Ao utilizar este pacote, você concorda automaticamente com os Termos de Serviço do Google.
NuGet.Org: LeadSoft.Adapter.Google.Workspace
GitHub Repo: leadsoft-adapter-google
Principais características
- Compatível com .NET 10.0.
- Autenticação SSO via Google OAuth2 com validação de ID Token JWT.
- Suporte a lista de domínios permitidos (Workspace e/ou contas pessoais
@gmail.com). - Consulta ao perfil expandido do usuário via Google People API (nome, foto, telefone, aniversário).
- Autorização opcional por grupo de e-mail via Google Admin Directory API.
- Renovação de Access Token via Refresh Token, sem exigir novo login pelo usuário.
- Chamadas assíncronas com
async/await. - Fácil integração com injeção de dependência (
IServiceCollection). - Interface
IGoogleSSOpara facilitar testes e mocking. - Suporte a registro como
ScopedouSingleton. - Tratamento centralizado de erros com
AppExceptione derivações — mensagens amigáveis para o chamador. - Logging integrado via
ILogger<T>com suporte opcional por DI — sem logs quando não configurado. - Stack traces nos logs apenas em ambientes não-produtivos (
ASPNETCORE_ENVIRONMENT != Production). - Open Source (MIT License).
Variáveis de ambiente
| Variável | Obrigatória | Descrição |
|---|---|---|
GOOGLE_SSO_CLIENT_ID |
Sim | Client ID do projeto OAuth2 no Google Cloud Console. |
GOOGLE_SSO_CLIENT_SECRET |
Sim | Client Secret do projeto OAuth2 no Google Cloud Console. Usado na renovação de Access Token via RefreshAccessTokenAsync. |
GOOGLE_SSO_HOSTED_DOMAIN |
Não | Lista de domínios permitidos separados por vírgula. Quando definido, bloqueia contas fora da lista. Ver detalhes abaixo. |
Detalhes de GOOGLE_SSO_HOSTED_DOMAIN
Aceita um ou mais domínios separados por vírgula. Inclua gmail.com para aceitar contas pessoais do Google.
| Valor | Comportamento |
|---|---|
| (não definido) | Aceita qualquer conta Google. |
empresa.com |
Aceita apenas contas do domínio Workspace empresa.com. |
empresa.com,parceiro.com |
Aceita contas dos domínios Workspace empresa.com e parceiro.com. |
empresa.com,gmail.com |
Aceita contas Workspace de empresa.com e contas pessoais @gmail.com. |
Nota técnica: contas
@gmail.comnão possuem o campoHostedDomainno token JWT do Google. O adapter identifica essas contas pelo campo
Métodos disponíveis
IGoogleSSO
Task<DTOGoogleUserResponse?> GetOAuthSSOAsync(string idToken, CancellationToken cancellationToken = default)- Valida o ID Token JWT emitido pelo Google após o login do usuário.
- Verifica assinatura, expiração e Client ID automaticamente via SDK do Google.
- Opcionalmente restringe login a uma lista de domínios (Workspace e/ou
@gmail.com). - Lança
UnauthorizedAppExceptionquando o token é inválido ou expirou. - Lança
ForbiddenAppExceptionquando o domínio do usuário não é permitido. - Lança
BadRequestAppExceptionpara erros de entrada inesperados.
Task<DTOGoogleUserResponse?> GetOAuthSSOAsync(string idToken, IList<string> requiredEmailGroups, string accessToken, CancellationToken cancellationToken = default)- Executa o mesmo fluxo do overload acima, exigindo adicionalmente que o usuário pertença a pelo menos um dos grupos de e-mail em
requiredEmailGroups. - A checagem de grupo consulta a Google Admin Directory API através de
IsUserInGroupAsync— exige umaccessTokendo usuário com o escopoadmin.directory.group.readonlyconcedido no consentimento (escopo sensível/restrito do Google, nem sempre disponível para consentimento de usuário comum — ver nota abaixo). - Lança
ForbiddenAppExceptionquando o usuário não pertence a nenhum dos grupos requeridos (além dos casos do overload simples). - Lança
BadRequestAppExceptionquandoaccessTokennão é informado.
- Executa o mesmo fluxo do overload acima, exigindo adicionalmente que o usuário pertença a pelo menos um dos grupos de e-mail em
Task<bool> IsUserInGroupAsync(string userEmail, IList<string> requiredEmailGroups, string accessToken, CancellationToken cancellationToken = default)- Verifica isoladamente se um usuário pertence a pelo menos um dos grupos de e-mail informados, sem passar pelo fluxo completo de login.
- Útil para revalidar associação a grupo a qualquer momento (ex.: em cada requisição sensível), sem reemitir o ID Token.
- Nunca lança exceção — falhas de comunicação com a Directory API (rede, escopo ausente, etc.) são registradas em log e tratadas como "usuário não pertence ao grupo", retornando
false.
Task<DTOGoogleRefreshTokenResponse> RefreshAccessTokenAsync(string refreshToken, CancellationToken cancellationToken = default)- Troca um Refresh Token por um novo Access Token junto ao Google, sem exigir que o usuário passe novamente pela tela de login.
- O Refresh Token precisa ter sido obtido previamente pelo seu fluxo de autorização com
access_type=offline(eprompt=consentna primeira vez) — este método não gera um Refresh Token novo, apenas troca um já existente. - Lança
UnauthorizedAppExceptionquando o Refresh Token é inválido, expirado ou foi revogado pelo Google (nesses casos é necessário um novo login completo). - Lança
BadRequestAppExceptionpara erros de entrada inesperados.
Nota sobre
admin.directory.group.readonly: é um escopo restrito do Google Workspace. Em muitos casos, o Access Token de um usuário comum obtido via consentimento OAuth simples não terá esse escopo — pode ser necessário que o app OAuth passe por verificação do Google, ou que o usuário autenticado seja administrador do Workspace. Teste esse fluxo no seu ambiente antes de depender dele em produção.
Instalação
Pelo CLI do .NET:
dotnet add package LeadSoft.Adapter.Google.Workspace
Ou via NuGet Package Manager no Visual Studio (pesquise por LeadSoft.Adapter.Google.Workspace).
Uso básico (exemplo)
Abaixo um exemplo genérico de como registrar e usar o adapter em uma aplicação ASP.NET Core / Console com DI.
// Program.cs (exemplo)
using LeadSoft.Adapter.Google.Workspace;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
// Google SSO
builder.Services.AddGoogleSSO(); // scoped (padrão)
// builder.Services.AddGoogleSSO(true); // singleton
WebApplication app = builder.Build();
app.Run();
Exemplo de uso via injeção de dependência — validação de ID Token (SSO):
// Em um Controller, Service ou Minimal API endpoint:
public class AuthService(IGoogleSSO googleSSO)
{
public async Task<DTOGoogleUserResponse?> LoginAsync(string idToken)
{
// Valida o token e retorna os dados básicos do usuário
return await googleSSO.GetOAuthSSOAsync(idToken);
}
}
Exemplo de uso — perfil expandido (após autenticação OAuth2 completa):
public class PerfilService(IGoogleSSO googleSSO)
{
public async Task<DTOGoogleUserExpandedResponse?> ObterPerfilAsync(string accessToken)
{
// Retorna dados detalhados do usuário via People API
return await googleSSO.GetUserProfileAsync(accessToken);
}
}
Exemplo de uso — login restrito a grupos de e-mail:
public class AuthService(IGoogleSSO googleSSO)
{
private static readonly string[] GruposPermitidos = ["equipe-interna@empresa.com"];
public async Task<DTOGoogleUserResponse?> LoginRestritoAsync(string idToken, string accessToken)
{
// Lança ForbiddenAppException se o usuário não pertencer a nenhum dos grupos
return await googleSSO.GetOAuthSSOAsync(idToken, GruposPermitidos, accessToken);
}
}
Exemplo de uso — renovação de Access Token via Refresh Token:
public class SessaoService(IGoogleSSO googleSSO)
{
public async Task<DTOGoogleRefreshTokenResponse> RenovarSessaoAsync(string refreshToken)
{
// Troca o Refresh Token por um novo Access Token, sem novo login
return await googleSSO.RefreshAccessTokenAsync(refreshToken);
}
}
DTOs de retorno
DTOGoogleUserResponse — GetOAuthSSOAsync
| Propriedade | Tipo | Descrição |
|---|---|---|
Id |
string |
Identificador único do usuário no Google (campo sub do JWT) |
Email |
string |
Endereço de e-mail do usuário |
Name |
string |
Nome completo do usuário |
Picture |
string |
URL da foto de perfil |
Domain |
string |
Domínio Workspace do usuário (vazio para contas @gmail.com) |
DTOGoogleUserExpandedResponse — GetUserProfileAsync
| Propriedade | Tipo | Descrição |
|---|---|---|
Id |
string |
Identificador único do usuário (ResourceName sem prefixo people/) |
Email |
string |
Endereço de e-mail principal |
Name |
string |
Nome de exibição completo |
Picture |
string |
URL da foto de perfil |
PhoneNumber |
string? |
Número de telefone (quando disponível) |
Birthday |
DateTime? |
Data de nascimento (quando disponível) |
DTOGoogleRefreshTokenResponse — RefreshAccessTokenAsync
| Propriedade | Tipo | Descrição |
|---|---|---|
AccessToken |
string |
Novo Access Token OAuth2 |
ExpiresInSeconds |
long? |
Tempo de vida do novo Access Token, em segundos |
IdToken |
string? |
Novo ID Token JWT, quando o escopo openid foi concedido originalmente |
Scope |
string? |
Escopos concedidos ao Access Token renovado, separados por espaço |
TokenType |
string |
Tipo do token (tipicamente Bearer) |
Logging
O adapter emite logs via ILogger<GoogleSSO> quando disponível. Ao registrar via DI (AddGoogleSSO()), o ILogger é resolvido automaticamente. Sem DI configurado, new GoogleSSO() funciona normalmente sem nenhum log.
O comportamento dos logs varia conforme ASPNETCORE_ENVIRONMENT:
| Ambiente | Stack trace no log | Mensagem de exceção |
|---|---|---|
Production |
Não — apenas a mensagem | Sim |
Staging / Development |
Sim — stack trace completo | Sim |
Tratamento de erros
| Exceção | Quando ocorre |
|---|---|
BadRequestAppException |
Token vazio, accessToken/refreshToken ausente quando exigido, erros de entrada inesperados |
UnauthorizedAppException |
ID Token inválido/expirado, ou Refresh Token inválido/expirado/revogado |
ForbiddenAppException |
Domínio do usuário não está na lista autorizada, ou usuário não pertence a nenhum dos grupos requeridos |
GetUserProfileAsync e IsUserInGroupAsync nunca lançam exceção — erros são registrados no log e retornam, respectivamente, null e false.
Configuração recomendada
- Configure
GOOGLE_SSO_CLIENT_IDvia variáveis de ambiente ou cofre seguro (Azure Key Vault, AWS Secrets Manager) — nunca em código-fonte. - Defina
GOOGLE_SSO_HOSTED_DOMAINpara restringir o login. Use vírgula para múltiplos domínios; incluagmail.compara aceitar também contas pessoais do Google. - Configure o logging padrão do ASP.NET Core (
builder.Logging) para capturar os logs do adapter. - Propague
CancellationTokenem todas as chamadas assíncronas.
Boas práticas de integração
- Valide o ID Token no servidor imediatamente após recebê-lo do frontend — nunca confie apenas na validação client-side.
- Não exponha diretamente os DTOs HTTP ao seu domínio — mapeie para modelos de domínio quando necessário.
- Use
GetUserProfileAsyncapenas quando precisar de dados adicionais (telefone, aniversário) além dos fornecidos pelo ID Token. - Prefira o overload simples de
GetOAuthSSOAsyncpara fluxos de login sem restrição por grupo — é mais rápido e não requer um Access Token separado. - Trate a expiração/revogação do Refresh Token (
UnauthorizedAppExceptionemRefreshAccessTokenAsync) como sinal para forçar um novo login completo — não há como "reviver" um Refresh Token inválido.
Versionamento e Compatibilidade
- Destinado a .NET 10.0. Verifique a compatibilidade do pacote com seu projeto.
- Siga versionamento semântico: breaking changes → major, novas features → minor, correções → patch.
Documentação de referência
| Recurso | Link |
|---|---|
| Google Identity — Sign In with Google | developers.google.com/identity/gsi/web |
| Google OAuth2 — ID Token | developers.google.com/identity/openid-connect/openid-connect |
| Google People API | developers.google.com/people |
| Google Cloud Console | console.cloud.google.com |
Licença
Consulte o arquivo de licença no repositório para detalhes sobre uso e redistribuição.
LeadSoft.Adapter.Google.Workspace — adapter simples e testável para autenticação via Google SSO e acesso ao perfil do usuário em aplicações .NET 10.
Development
Desenvolvido pelo time da LeadSoft® Soluções Web.
Nossa empresa
LeadSoft Soluções Web Ltda
CNPJ 38.043.762/0001-48
Como nos encontrar:
INFORMAÇÕES DE CONTATO — Se você tiver alguma dúvida sobre estes Termos ou Serviços, entre em contato conosco em
| Product | Versions 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. |
-
net10.0
- Google.Apis.Admin.Directory.directory_v1 (>= 1.75.0.4227)
- Google.Apis.Auth (>= 1.76.0)
- Google.Apis.PeopleService.v1 (>= 1.74.0.3973)
- LeadSoft.Common.GlobalDomain (>= 10.0.16)
- LeadSoft.Common.Library (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.