- 01Why Tokens Expire After 7 Days
- 02”Testing” vs. “In Production”
- 03What Was Happening with My Tool
- 04How to Publish to Production
- 05Two Things That Tripped Me Up
- 06What Publishing Required
- 07Some Scopes Require Verification
- 08The Unverified App Warning and User Limits
- 09Other Ways Tokens Can Expire
- 10Getting a New Token
- 11Common Mistakes and Pitfalls
- 12Things to Confirm Before You Start
- 13FAQ
- 14Official Sources I Referenced
- 15Summary
Good morning, this is まさきん.
If your Google OAuth publishing status is “Testing,” refresh tokens expire after 7 days. I ran into this deadline with a personal tool that imports my health data. Here’s how to publish to production, including verification for Gmail restricted scopes, based on the official documentation.
This information is current as of publication. Please check the official sites for the latest details.
- For apps with an external user type in “Testing” status, refresh tokens expire after 7 days
- Even for a personal tool, publishing to “In production” removes the 7-day limit
- Publishing requires a homepage URL and a privacy policy URL; a contact email alone isn’t enough
- With sensitive or restricted scopes, users still see an unverified app warning in production until you pass verification
- Tokens can also expire for reasons other than the 7-day rule, such as 6 months of non-use or token count limits
Why Tokens Expire After 7 Days
Let’s start with the bottom line. Google’s official documentation says, in essence:
For a project with an external user type and a publishing status of “Testing,” refresh tokens issued there expire after 7 days.
There is an exception. If the only scopes you request are name, email address, and profile, specifically ones that stay within userinfo.email, userinfo.profile, and openid, the 7-day limit doesn’t apply. An app that only uses Sign in with Google isn’t affected.
Flip that around, and any app that reads Gmail or Calendar data is affected. The same goes for health data. Even a personal script gets the same treatment if its user type is external.
”Testing” vs. “In Production”
You can check the publishing status on the “Audience” screen of the Google Auth Platform, which is where the old “OAuth consent screen” used to be. Here’s how the two states differ:
| Item | Testing | In production |
|---|---|---|
| Who can use it | Only registered test users | Anyone with a Google account |
| Test user limit | Up to 100 | None |
| Consent validity | Expires 7 days after consent | No 7-day limit |
| Refresh tokens | Expire after 7 days | Valid until another expiration condition applies |
| Warning before consent | A test access warning appears | Warning before verification for sensitive scopes |
| Verification | Not applicable | Required depending on scopes |
Testing is really meant as a development state. Only people added as test users can grant consent, and that consent expires after 7 days.
In production, on the other hand, anyone can grant consent. For a personal tool that runs automatically every day, production is probably the better fit.
What Was Happening with My Tool
My tool was using Google’s Health-related APIs, and the project’s publishing status was still “Testing.”
That meant my refresh token was set to expire 7 days after it was issued. Once it expired, my automatic imports would stop. So I decided to fill in the branding and publish to “In production.”
How to Publish to Production
Here’s the flow from the official help, in the order I actually went through it:
- Open the Google Cloud console and check the project selector at the top of the screen
- Open “Branding” in the Google Auth Platform
- Check the app name and the user support email
- Enter the URLs for the app homepage and privacy policy
- Add the domain of those URLs to the authorized domains
- Enter the developer contact email and save
- On the “Audience” screen, click “Publish app” and continue through the confirmation
- Confirm that the publishing status now says “In production”
- Grant consent again from the tool and get a fresh refresh token
The official help recommends registering the authorized domains first. Adding them before the homepage and other URLs will likely save you some back-and-forth.
Two Things That Tripped Me Up
I Was in the Wrong Project
The first stumble was a mundane one. The Google Cloud console I’d opened was showing a different project: the one I’d created for my blog’s analytics.
The Google Cloud console remembers the last project you opened, so if you open it without thinking, you might end up somewhere else. Glancing at the project name at the top of the screen before you start is all it takes to avoid this.
When you have several personal projects, their names start to look alike. Giving them names that make their purpose obvious is a quietly effective safeguard, too.
A Contact Email Alone Isn’t Enough to Publish
The second issue was that the publish button wouldn’t become active. At first, I had only entered a contact email.
Publishing required the URLs for the app homepage and privacy policy. The official help also says these links are mandatory for external production apps. Apparently, if they’re missing, you can’t even submit for verification.
What Publishing Required
Here are the fields the Branding screen asks for, organized based on the official help:
| Field | What it is | What the official help says |
|---|---|---|
| App name | The name shown on the consent screen | Names that could be confused with Google trademarks are not allowed |
| User support email | Where users can send questions | Your own address or a group you manage |
| App homepage | A page describing the app | Required for external production apps |
| Privacy policy | A page describing how data is handled | Required for external production apps |
| Terms of service | The app’s terms page | Optional |
| Authorized domains | The domain of the URLs above | Register before entering the URLs |
| Developer contact | Where Google sends notifications | Keep it up to date |
| Logo | The icon on the consent screen | Shown in production after verification |
The logo is optional. However, uploading a logo to an external production app triggers verification. For a personal tool, leaving it blank is probably less hassle.
What to Use for the Homepage and Policy
I used pages on my own blog for the homepage and privacy policy, and added otokuken.com to the authorized domains.
The official help also lists requirements for verification: the homepage must be on a verified domain you own, the privacy policy must be on the same domain as the homepage and linked from it, and the policy must describe how Google user data is handled, among other things.
If you’re not going through verification, you might be able to publish without being that strict. But you may need verification later, so meeting the requirements from the start gives you peace of mind.
Some Scopes Require Verification
Publishing to production doesn’t make everything unrestricted. The key is how your scopes are classified.
| Scope category | Verification | Behavior before verification |
|---|---|---|
| Non-sensitive | Not required (brand verification if you display a name and logo) | Users can consent without a warning |
| Sensitive | Required | An unverified app warning appears |
| Restricted | Required, plus an annual security assessment | An unverified app warning appears |
The category is shown automatically when you add a scope in the Cloud console, so you can check which one your app falls into there.
There is an exception for personal-use apps, though. According to the official help, personal apps with fewer than 100 users can keep being used without verification. In that case, users click through the unverified app warning when they sign in.
The Unverified App Warning and User Limits
If you request sensitive scopes before verification, a warning appears before the consent screen, saying something to the effect of “Google hasn’t verified this app.”
There’s also a user cap. Apps that show the unverified app screen are limited to 100 new users in total. According to the documentation, this limit applies over the entire lifetime of the project and can’t be reset.
For a tool only you use, this limit will almost never be an issue. But if you let family or friends use it too, it’s worth keeping the headcount in mind.
If you’re taking stock of things that expire or need renewing, why not review your monthly phone bill at the same time? It might lighten your fixed costs a bit.
Clicking this opens the Rakuten login page. Once you log in, you’ll see the campaign details.
Other Ways Tokens Can Expire
Even in production, refresh tokens don’t last forever. Here are the expiration conditions listed in the official documentation:
| Condition | Details |
|---|---|
| The user revoked access | They removed the app’s connection from their Google account |
| Unused for 6 months | The refresh token wasn’t used for 6 months |
| Password changed | For tokens that include Gmail scopes |
| Token count limit | Up to 100 per account per client ID |
| Time-based access | Access was granted for a limited period and that period ended |
| Admin restrictions | A Workspace admin restricted the service |
| Session control | Your Google Cloud organization sets a session length |
The one to watch out for most is the token count limit. When you hit it, the oldest token is invalidated without warning. If you keep re-consenting while testing, you could end up wiping out the token you were using in production.
There’s also an overall limit, and the official docs suggest a workaround of keeping authorized clients to around 15 to 20 per account.
Getting a New Token
Once you’ve published to production, the next step is getting a new token. The official docs say consent granted during Testing expires 7 days after it was given, so after publishing, the user needs to grant consent again.
In my case, I still need to do this. I plan to run my tool’s auth flow and re-consent in the browser.
After you get the new token, it’s a good idea to stop using the old one. Write the new one to wherever you store it and delete the old one. If you keep tokens in multiple places, you may lose track of which one is actually live.
Common Mistakes and Pitfalls
Here’s everything so far, summarized as common mistakes:
| Mistake | What happens | How to prevent it |
|---|---|---|
| Working in the wrong project | Your settings don’t take effect | Check the project name before starting |
| Trying to publish without URLs | The publish button can’t be clicked | Prepare the homepage and policy first |
| Leaving authorized domains for later | You get stuck when registering URLs | Add the domain first |
| Assuming publishing alone fixes it | Old tokens still expire after 7 days | Re-consent after publishing |
| Re-consenting over and over | Old tokens get invalidated without warning | Only get new tokens when you need to |
| Leaving it idle for half a year | The token expires | Set it up to run regularly |
When a personal tool stops working, nobody tells you. That’s why I think it’s important to build it so an expired token surfaces as an error you’ll actually notice.
I’ve also written about hitting a free tier limit in How to work around the Cron Triggers limit on the Cloudflare Workers free plan. For personal automation, this kind of “silently stopping” might be the biggest weakness.
Things to Confirm Before You Start
- Is the project open in the console the one you intend to change?
- Is the user type external or internal?
- Is the current publishing status Testing or In production?
- Are your scopes non-sensitive, sensitive, or restricted?
- Can you provide homepage and privacy policy URLs?
- Have you added the domain of those URLs to the authorized domains?
- Is the developer contact email up to date?
- Do you have time to re-consent after publishing?
According to the official docs, consent granted during Testing expires 7 days after it was given. It’s safest to assume that publishing to production won’t extend it. After publishing, re-consent and get a new token.
I’ve written about my overall automation setup in Having AI make a one-page “today’s briefing” while I get ready in the morning. Systems like that are all quietly held up by tokens behind the scenes.
FAQ
Q. How long until my token expires if I stay in Testing?
For projects with external users in Testing, tokens expire after 7 days, counted from the moment of consent. If your scopes are limited to name, email, and profile, this limit doesn’t apply.
Q. Can I publish to production even if I’m the only user?
Yes. The official help says personal apps with fewer than 100 users can keep being used without verification. However, sensitive scopes will show an unverified app warning.
Q. Why can’t I click the publish button?
You may be missing required branding fields. External production apps need homepage and privacy policy URLs. Also check that your authorized domains are registered.
Q. Once I publish, can I keep using my current token?
The official docs say consent granted during Testing expires 7 days after it was given. To be sure, re-consent and get a new token after publishing. This requires action from the user.
Q. Do I absolutely have to go through verification?
If you use sensitive or restricted scopes for the general public, verification is required. There’s an exception for personal apps with fewer than 100 users, which can keep being used without it. Restricted scopes also require an annual security assessment.
Q. How many test users can I register?
Projects in Testing can have up to 100 test users. Once someone is added, they count against that limit.
Q. In production, can I use a token forever?
Not forever. Tokens expire if they go unused for 6 months or if the user revokes access. There’s also a limit of 100 per account per client ID.
Q. Will my logo and app name appear on the consent screen?
The official help says displaying the app name and logo requires verification. Before verification, the app’s domain is shown instead. For a personal tool, not uploading a logo is probably less hassle.
Official Sources I Referenced
- Using OAuth 2.0 to Access Google APIs (Google for Developers)
- Manage App Audience (Google Cloud Help)
- Manage OAuth App Branding (Google Cloud Help)
- Get started with the Google Auth Platform (Google Cloud Help)
- OAuth App Verification Help Center (Google Cloud Help)
- Verification requirements (Google Cloud Help)
- When is verification not needed (Google Cloud Help)
- Unverified apps (Google Cloud Help)
- OAuth 2.0 Scopes for Google APIs (Google for Developers)
- Google API Services User Data Policy
Summary
The reason my refresh token was expiring after 7 days was the “Testing” publishing status. Even for a personal tool, publishing to production removes that limit.
What I needed were URLs for a homepage and a privacy policy, plus registering the authorized domain, and being careful not to work in the wrong project. From here, I’m moving on to getting a new token.
If you have anything running automatically, it’s worth taking a quick look at its status.
Clicking this opens the Rakuten login page. Once you log in, you’ll see the campaign details.
This article contains affiliate advertising. If you sign up for a product or service through a link on this site, we may receive compensation from the partner company. The site operator is also an employee of Rakuten Group and may receive compensation through an employee referral program. The content and opinions here are based on the operator’s own experience and research regardless of any advertising relationship, but please read with the above in mind. See the Disclaimer & Affiliate Disclosure for details. Disclaimer & Affiliate Disclosure
This article includes machine-translated content. Please check the official Rakuten Mobile multilingual page for exact terms.
If you have concerns about Rakuten Mobile coverage or signal quality, you can consult through the official signal improvement request form .