Signing in to Directus with a Google account is one of those tasks that takes ten minutes when you know the five things that matter, and an entire afternoon when you do not. This guide is the ten-minute version, written out in full — every screen, every value, and every step people skip that quietly breaks the whole thing.

Throughout, the Directus install is at https://cms.contensu.com. Substitute your own address wherever you see it.

First, the thing that confuses everyone

Directus has no Google driver. It ships five authentication drivers — local, oauth2, openid, ldap and saml — and Google is a configuration of the openid one. That is why searching for “Directus Google login” turns up documentation about OpenID Connect and it feels like the wrong page. It is the right page.

The good news: because Google publishes an OpenID discovery document, you give Directus one URL and it finds the authorisation endpoint, the token endpoint and the signing keys by itself. No copying four URLs from a reference table.

What you need before you start

  • A Directus instance you can restart and whose environment variables you can edit.
  • A Google account. A personal one is fine for testing; Google Workspace matters only if you want group-based role mapping later.
  • Your Directus public address — the one people type into a browser. Ours is https://cms.contensu.com.

Step 1 — Create a Google Cloud project

Open the project creation screen and give it a name. The name is internal — it never appears to the people signing in. If you already have a project you are happy to reuse, skip this.

Go to the OAuth consent screen. This is the panel your users see when Google asks whether they want to share their name and email with your Directus.

  • Choose Internal if you have Google Workspace and only your own staff will sign in. This is the easy path — no verification, no test-user list.
  • Choose External for anyone else. Fill in the app name, a support email and a developer contact email. Those three are required and the form will not let you continue without them.

Here is the step people forget. An External consent screen starts in Testing mode, and in Testing mode only accounts you have explicitly added as test users can sign in. Everyone else gets a Google error before Directus is ever involved — which sends people off debugging Directus for an hour. Either add your testers under the Test users heading, or publish the app.

Step 3 — Create the OAuth client

Go to CredentialsCreate credentialsOAuth client ID.

For Application type choose Web application. Not Desktop, not TV and Limited Input. The wrong type does not fail here — it fails much later with a message that does not mention the application type at all.

Step 4 — The one string that has to match exactly

Still on that screen, under Authorised redirect URIs, add this and nothing else:

https://cms.contensu.com/auth/login/google/callback

The shape is always the same:

[PUBLIC_URL]/auth/login/[provider name]/callback

Three things about that string are worth understanding, because between them they cause most failed setups.

  • Directus builds it from PUBLIC_URL, not from the address in your browser. If PUBLIC_URL is still http://localhost:8055 on a live server, Directus will send Google a callback of http://localhost:8055/... no matter what domain you visited, and Google answers redirect_uri_mismatch.
  • The provider name is part of the path. We named ours google, so the path says google. Rename it to workspace later and this URI must change too, or a working login breaks for no visible reason.
  • Trailing slashes matter. https://cms.contensu.com/ as your PUBLIC_URL can produce a double slash in the callback, and Google compares these strings literally.

Save, and Google shows you two values. Copy both now — the secret is easy to retrieve later, but easier to copy while it is on screen.

  • The Client ID ends in .apps.googleusercontent.com
  • The Client secret starts with GOCSPX-

If what you copied does not look like that, you have grabbed the wrong field.

Step 5 — Tell Directus about it

Add these to your Directus environment and restart. Every variable after the AUTH_GOOGLE_ prefix maps to a setting inside the driver, which is why the naming looks verbose.

AUTH_PROVIDERS="google"

AUTH_GOOGLE_DRIVER="openid" AUTH_GOOGLE_ISSUER_URL="https://accounts.google.com/.well-known/openid-configuration" AUTH_GOOGLE_CLIENT_ID="your-id.apps.googleusercontent.com" AUTH_GOOGLE_CLIENT_SECRET="GOCSPX-your-secret" AUTH_GOOGLE_IDENTIFIER_KEY="sub" AUTH_GOOGLE_ALLOW_PUBLIC_REGISTRATION="true" AUTH_GOOGLE_DEFAULT_ROLE_ID="paste-a-role-uuid-here" AUTH_GOOGLE_LABEL="Google" AUTH_GOOGLE_ICON="google"

A few notes on the ones that are easy to get wrong:

  • AUTH_PROVIDERS is a comma-separated list of names you choose. The name becomes the URL path and the variable prefix. You cannot call it local — Directus refuses to start.
  • AUTH_GOOGLE_DEFAULT_ROLE_ID takes the UUID of a role, not its name. Open the role in Settings and copy the id from the address bar.
  • AUTH_GOOGLE_IDENTIFIER_KEY defaults to sub, Google's permanent account id. Leave it there. Emails change when people are renamed in Workspace; sub does not.
  • You do not need to set a scope. Directus defaults to openid profile email, which is what Google offers and all you need.

Step 6 — Check it worked

Restart Directus and open /admin/login. A Google button appears under the normal email and password form. Sign in, and you should land in the Directus app.

Then open Settings → Users and find the account you just used. Two fields prove the connection is real rather than coincidental: Provider reads google, and External Identifier holds a long number — that is the sub claim, and it is the value Directus will match on every future login.

Trying it on localhost first

You do not have to prove this on a live domain, and you should not. Google is one of the few providers that accepts a plain-HTTP redirect URI, on the single condition that it points at loopback — so the whole flow runs against a Directus on your own laptop. Three things have to line up.

Register the localhost URI alongside the real one

An OAuth client holds a list of authorised redirect URIs, so you do not need a second client. Add http://localhost:8055/auth/login/google/callback next to the production one and both keep working. Two traps: the port is part of the string, and 127.0.0.1 is a different string to Google than localhost — register whichever one you will actually type into the address bar.

Make Directus send that URI

Directus ignores the address you are browsing. It builds the callback from PUBLIC_URL, so a local instance still carrying the production PUBLIC_URL hands Google the production callback and you get redirect_uri_mismatch while the browser bar quite clearly says localhost. Either set PUBLIC_URL=http://localhost:8055 in your local environment, or — on Directus 11.14.1 and later — leave it alone and add AUTH_ALLOWED_PUBLIC_URLS=http://localhost:8055. Directus compares the protocol and host of the incoming request against that list, uses the entry that matches, and falls back to PUBLIC_URL when none does. The comparison is exact: the port counts, and an entry written as localhost will not match a request to 127.0.0.1.

A fresh install already works over plain HTTP — SESSION_COOKIE_SECURE and REFRESH_TOKEN_COOKIE_SECURE both default to false, and the same-site policy defaults to lax. The failure appears the moment you copy a production .env across. With SESSION_COOKIE_SECURE=true or AUTH_GOOGLE_COOKIE_SECURE="true" on HTTP, the browser accepts the redirect and silently discards the cookie: Google signs you in, Directus issues a session you never receive, and you arrive back at the login screen with no error of any kind. It reads exactly like a wrong client secret, and it is not.

One more if you run Directus in Docker. PUBLIC_URL has to be the address your browser uses, not the service name on the Compose network. Google redirects the browser, and the browser has never heard of http://directus:8055.

The steps people forget

In rough order of how often each one is the culprit.

The Google account has no Directus user, and registration is off

This is the big one. Google signs you in perfectly, then Directus refuses with an invalid credentials error, and everything looks correct. By default allowPublicRegistration is off, so an unrecognised Google account is rejected rather than created. Either switch AUTH_GOOGLE_ALLOW_PUBLIC_REGISTRATION to true, or create the user in Directus by hand and paste the Google sub into the External Identifier field.

Public registration is on, but no default role is set

The user gets created and can sign in, and then sees almost nothing, because they have no role and therefore no permissions. Set AUTH_GOOGLE_DEFAULT_ROLE_ID to a real role UUID.

PUBLIC_URL does not match reality

Covered above, and it is the most common cause of redirect_uri_mismatch. Check it before you check anything in the Google console. If you serve Directus on more than one domain, AUTH_ALLOWED_PUBLIC_URLS lets you list the alternatives — Directus matches the request's protocol and host against that list and falls back to PUBLIC_URL.

Only listed test users can sign in. Everyone else is stopped by Google before Directus sees the request, so no amount of Directus debugging will help.

Waiting for group mapping that will never arrive

Plain Google sign-in does not send a groups claim — its discovery document advertises sub, email, email_verified, name, given_name and family_name, and that is all. AUTH_GOOGLE_ROLE_MAPPING cannot work without a claim to read, and Directus logs a debug line saying the configured group claim is missing or empty. Group mapping needs Google Workspace with a custom claim.

The licence tier, but only on Directus 12

This one depends on your version, and it is worth getting right. Directus 11 has no licence module at all — SSO is ungated, and everything in this guide works on a stock 11.17.4. Licensing arrived in 12.0.0, and there the SSO routes sit behind an sso_enabled entitlement: without it the login and callback routes return 404 rather than failing loudly, and Directus logs a warning at startup — you have SSO providers configured these will be unavailable under the current license tier. So if you are on 12 and the provider is simply absent, check the entitlement before you start doubting your configuration.

Cookies over plain HTTP

The login flow stores a short-lived signed cookie between the redirect out and the callback back. On a real domain set AUTH_GOOGLE_COOKIE_SECURE="true". On plain HTTP leave it off, or the browser drops the cookie and the callback fails with a message about not being able to verify it.

What actually happens when someone clicks the button

Useful to know, because it explains most error messages.

  1. The login screen asks Directus which providers exist and renders a button for each one that has both a name and a driver.
  2. Clicking it hits /auth/login/google. Directus generates a PKCE code verifier, signs it into a short-lived cookie along with where you should end up afterwards, and redirects you to Google.
  3. You approve at Google. Google redirects back to the callback URL with a code.
  4. Directus reads its own cookie back, exchanges the code for tokens, and asks Google's userinfo endpoint who you are.
  5. It looks for a user whose external identifier matches your sub. Found — you are signed in and your refresh token is stored. Not found — it creates the user if registration is allowed, and refuses if not.

That cookie in step two is why the flow breaks if it is dropped, and why the login has a timeout: by default you have five minutes between clicking the button and finishing at Google.

Directus is what we build on every day, and we publish the extensions we needed along the way — they are all free and MIT-licensed, and you can find them on our tools page.

Common questions

Does Directus have a Google login option built in?

Not as a Google-specific driver. Directus ships five auth drivers — local, oauth2, openid, ldap and saml — and Google is configured through the openid driver by pointing it at Google's discovery document. That is why the setup guides you find talk about OpenID Connect rather than Google.

What redirect URI should I give Google?

Exactly your PUBLIC_URL followed by /auth/login/<provider>/callback. If PUBLIC_URL is https://cms.contensu.com and your provider is named google, the URI is https://cms.contensu.com/auth/login/google/callback. Directus builds this from PUBLIC_URL, not from the address you happen to be visiting, so a wrong PUBLIC_URL produces redirect_uri_mismatch even though the browser URL looks right.

Why does Google sign in successfully but Directus says invalid credentials?

Almost always because the Google account has no matching Directus user and public registration is switched off. Set AUTH_GOOGLE_ALLOW_PUBLIC_REGISTRATION to true and give AUTH_GOOGLE_DEFAULT_ROLE_ID a role, or create the user in Directus first with the External Identifier field set to the Google sub.

Do I have to use the email address as the identifier?

No, and you should not. Directus defaults to the sub claim, which is Google's permanent account identifier. Emails change when someone is renamed in Google Workspace; sub does not. Setting AUTH_GOOGLE_IDENTIFIER_KEY to email works, but you will lose the link to the Directus user the day that email changes.

Can I map Google Workspace groups to Directus roles?

Only if your identity provider actually sends a groups claim. Plain Google sign-in does not — its discovery document lists sub, email, email_verified, name, given_name and family_name. You need Google Workspace with a custom claim configured, and then AUTH_GOOGLE_GROUP_CLAIM_NAME and AUTH_GOOGLE_ROLE_MAPPING will work.

Why is the Google button missing from the login screen?

The login screen lists providers that have both a name in AUTH_PROVIDERS and a matching AUTH_<NAME>_DRIVER variable. If either is missing the provider is filtered out silently. Also check your Directus licence tier: SSO providers are gated behind an entitlement, and Directus logs a warning at startup when providers are configured but unavailable.

Does the user get created automatically on first login?

Only when AUTH_GOOGLE_ALLOW_PUBLIC_REGISTRATION is true and, if AUTH_GOOGLE_REQUIRE_VERIFIED_EMAIL is on, the email_verified claim is true. Google does send email_verified, so that check is safe to leave enabled.

Can I test Google SSO on localhost?

Yes. Google permits a plain-HTTP redirect URI when it points at loopback, so http://localhost:8055/auth/login/google/callback can be registered on the same OAuth client as the production URI. Directus must also be told to send it: set PUBLIC_URL to the localhost address, or add it to AUTH_ALLOWED_PUBLIC_URLS on 11.14.1 and later. Leave the cookie secure flags off over HTTP, or the browser discards the session cookie and you bounce back to the login screen with no error.

Want Google sign-in working today rather than this week?

We build on Directus full time, and SSO is one of the things we get called in to finish. Google, Entra, Okta, Keycloak or your own OpenID provider — including the parts a guide can only describe in general: which claim becomes the identifier, who is allowed to self-register, and what role they land in. Fifteen minutes is usually enough to tell whether you are one environment variable away or looking at something larger.

Book a 15-minute call

More articles

Directus8 August 20269 min read

How to Set Up Microsoft (Entra ID) SSO Login in Directus

Directus8 August 202613 min read

How to set up LDAP and Active Directory login in Directus

Directus8 August 202612 min read

How to set up GitHub SSO login in Directus

Back to all articlesBack to top