Google Sign-In is added to a website or app with OAuth 2.0 and its identity layer, OpenID Connect (OIDC). Short answer: the user is redirected to Google, Google authenticates them and sends your site a signed ID token; your server verifies the token’s signature and audience, matches the user to your own records and opens your own session. Your site never sees or stores the Google password. The technical setup is quick; what stretches the project is account linking, session management and the single sign-on (SSO) requirements of enterprise customers. This article describes the flow we implement in corporate web projects; it is the authentication side of our web development service.
OAuth, OpenID Connect and SSO: which is which?
These three terms are used interchangeably in everyday speech, but they answer three different questions. OAuth 2.0 is a delegation protocol: it says “this app may read my calendar on my behalf”, not who you are. OpenID Connect is the identity layer on top of OAuth: a signed ID token carries “this user is this identity, and the email is verified”. Google Sign-In is, in practice, OpenID Connect. SSO (single sign-on) is an architectural goal: the user signs in once and reaches several applications without typing another password. There are two distinct needs:
- Social login (B2C): your customers register and sign in with a Google, Apple or Microsoft account. The goal is less friction and not owning password management.
- Enterprise SSO (B2B / internal apps): employees sign in through the company’s identity provider (Google Workspace, Microsoft Entra ID, Keycloak). The goal is central access management: when someone leaves, access is cut in one place.
Both use the same protocol, but the product decisions differ. In social login the user picks the provider; in enterprise SSO the customer company dictates the provider and usually wants to connect its own tenant via SAML or OIDC.
The Google Sign-In flow step by step
The recommended flow is “authorization code with PKCE”. The old implicit flow that produced tokens in the browser is no longer recommended; tokens are always obtained on the server, and the browser only receives your own session cookie.
- Create an OAuth client in Google Cloud Console; the allowed redirect URIs are registered as exact matches, no wildcards.
- When the user clicks “Sign in with Google”, the server generates a random state and a PKCE code_verifier, stores them in a short-lived cookie and redirects the user to Google’s authorization endpoint.
- Google authenticates the user, shows what will be shared and asks for consent; the browser returns to your callback URL with a code.
- The server compares state with the cookie and exchanges the code for an ID token at Google’s token endpoint (with client_secret and code_verifier).
- The ID token’s signature is verified against Google’s published keys, along with the iss and aud claims and the expiry; the email must be marked as verified.
- The user is found or created in your database and your session cookie completes the login. The Google token is never sent to the browser.
Example: the callback as a Next.js route handler
// app/api/auth/google/callback/route.ts
import { createRemoteJWKSet, jwtVerify } from 'jose';
const GOOGLE_JWKS = createRemoteJWKSet(
new URL('https://www.googleapis.com/oauth2/v3/certs'),
);
export async function GET(req: Request) {
const url = new URL(req.url);
const code = url.searchParams.get('code');
const state = url.searchParams.get('state');
// state was written to a cookie when the login started: CSRF check
if (!code || !state || state !== await readStateCookie()) {
return new Response('Invalid request', { status: 400 });
}
// the code -> token exchange always happens on the server
const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
code,
grant_type: 'authorization_code',
client_id: process.env.GOOGLE_CLIENT_ID!,
client_secret: process.env.GOOGLE_CLIENT_SECRET!,
redirect_uri: process.env.GOOGLE_REDIRECT_URI!,
code_verifier: await readVerifierCookie(),
}),
});
const { id_token } = (await tokenRes.json()) as { id_token: string };
// signature, issuer, audience and expiry verification
const { payload } = await jwtVerify(id_token, GOOGLE_JWKS, {
issuer: ['https://accounts.google.com', 'accounts.google.com'],
audience: process.env.GOOGLE_CLIENT_ID,
});
if (payload.email_verified !== true) {
return new Response('Email not verified', { status: 403 });
}
// the identity is Google's permanent "sub", not the email address
const user = await findOrLinkUser({
provider: 'google',
subject: payload.sub!,
email: String(payload.email),
});
return createSessionAndRedirect(user.id, '/dashboard');
}Account linking: where projects get stuck
Most sites that add Google Sign-In already have users registered with email and password. If what happens when the same person signs in with Google is not decided up front, you either end up with two separate accounts or merge the wrong ones. Three rules solve this. First, the user’s identity is not the email address but the permanent sub value Google sends; emails change, sub does not. Second, automatic merging with an existing account happens only when the email is verified by Google; otherwise an account claiming someone else’s email could sign in. Third, a user must be able to link more than one provider, so provider data lives in a separate “identities” table (user, provider, sub) rather than as columns on the user table.
The user’s key is not the email but the permanent identifier issued by the provider. A system keyed on email mixes up accounts the moment an address changes or another provider sends the same address without verifying it.
Enterprise SSO: Google Workspace and Microsoft Entra
When SSO is requested for a B2B product or an internal panel, the job grows by a few steps. Which domains may sign in must be restricted: the hd claim in a Google ID token carries the user’s Workspace domain, but it is only a check, not a substitute for authorization. If users are created automatically on first login (just-in-time provisioning), the role they start with must be defined; we covered role design in user roles and authorization. If Microsoft Entra or another tenant is to be connected, the customer usually registers your application on their side via SAML or OIDC, and you keep a separate issuer and key set per customer. The most forgotten item is sign-out: when an employee leaves, their account at the identity provider is closed, but your open session lives until its own expiry. Keep sessions short or listen for the provider’s logout notification.
Security checklist
- state and PKCE are mandatory on every request; state is single-use and compared with the cookie on callback.
- Redirect URIs are registered as exact matches; separate clients are used for test and production, and client_secret never goes into the browser or a mobile bundle.
- The ID token is used only for identity; your own session or your own issued token authorizes API calls. Sending the ID token to other services as if it were an access key is a common mistake.
- Scopes stay minimal: openid, email and profile are enough for most sites. Calendar or Drive access, if needed, is requested separately and later.
- The recovery path for a user who loses their Google account is designed up front: a one-time email link or a second provider. Accounts tied to a single provider are the most frequent source of support tickets.
- Login endpoints are rate limited and failed attempts are logged; for the other attack surfaces see our website security article.
For high-risk actions (payment approval, permission changes) Google login alone should not be enough; ask for a second verification at the moment of the action. We covered that side in SMS OTP verification.
Managed identity service or your own setup?
Hosted services such as Auth0, Firebase Authentication and Clerk, and self-hosted products such as Keycloak, deliver this whole flow, password reset and multi-factor authentication out of the box. For a single provider and a simple user model, your own setup with a library like Auth.js is enough and user data stays in your own database. If multi-tenant SSO, SAML support, multi-factor authentication and audit logs are all required together, a managed service or Keycloak shortens the project by weeks. Two questions decide it: where will user data live, and if you leave the service, can users be exported together with their password hashes? If the user table is in your own database, the second question answers itself; this approach also fits the multi-tenant model in our SaaS product development article.
Privacy notice
With Google Sign-In your side receives the name, email and profile picture; this is personal data, and your privacy notice should state its source (the identity provider) and the purpose. Request only what login needs and do not store the profile picture unless it is used. For the Turkish framework see our KVKK compliant website article; this text is not legal advice.
Conclusion
Done right, Google Sign-In gives users a frictionless registration and spares your site from storing passwords. The technical flow is standard; what shapes the project is the account linking rules, session lifetime and the SSO expectations of enterprise customers. If you want to add social login or enterprise SSO to an existing site, send us your requirements through the quote form and we will plan the flow together with your current user table.