Does Truto Support White-Labeled OAuth for Calendar Apps?
Yes, Truto supports fully white-labeled OAuth for Google and Microsoft calendar integrations. Learn how our 3-level credential hierarchy and proactive token refresh works.
Short answer: Yes. If you are asking the question, does Truto support white-labeled OAuth for calendar apps? the answer is a definitive yes. Truto is designed around a bring-your-own-OAuth-app model. You register your own Google Cloud project and Microsoft Azure Active Directory (Azure AD) app, hand Truto the client ID and secret through a scoped override, and every consent screen your end users see displays your brand, verified publisher status, and privacy policy—not Truto's.
When building calendar integrations for B2B SaaS, the authentication flow is your users' first interaction with the feature. If your enterprise customer's IT admin clicks "Connect Google Calendar" inside your application and is redirected to a Google consent screen that says " [Some Third-Party Unified API] wants to access your account," conversion rates plummet. Enterprise security teams will immediately flag the connection, and end-users will abandon the flow due to a lack of brand recognition.
If you're an engineering lead about to ship a calendar integration and you've been burned before by a vendor whose name showed up on the Google OAuth consent screen, this post is the one you want. To maintain trust, you must own the authentication surface. Truto is designed as a pass-through execution engine that handles the normalized data mapping, webhook ingestion, and token lifecycle management behind the scenes, while ensuring you retain complete ownership of the customer relationship.
This guide breaks down exactly how white-labeled OAuth works within Truto's architecture, how we manage the lifecycle of the tokens generated by your custom apps, how rate limits are surfaced (spoiler: they're your quotas, so you get to see them), and how you can override credentials on a per-customer basis for strict enterprise requirements.
Why White-Labeled OAuth Matters for Calendar Apps
Calendar integrations live or die on the consent screen. When your user attempts to authenticate, they see one of two things:
- Your app name, your logo, your privacy policy URL, and the exact scopes you've justified to Google or Microsoft—a native, trustworthy experience.
- A vendor's app name they've never heard of, requesting access to their entire company's calendar data—an immediate security review escalation.
Option 2 is where deals die. IT admins running SOC 2 or ISO 27001 shops will not click through a consent prompt for a third party they haven't vetted. Even if they do, the Cloud Application Security Assessment (CASA) tier check, Google's restricted scope review, and Microsoft's publisher verification all target the app owner. If that owner isn't you, you inherit none of the trust.
B2B SaaS competitors in the scheduling space explicitly market "Full white-label" capabilities as a differentiator to allow engineering teams to remove third-party branding. Providers like Cal.com position themselves as infrastructure-style choices for teams wanting deep control over the booking lifecycle. Similarly, enterprise scheduling APIs like Nylas list "self-serve access to white-labeled auth" as a core competitive advantage over simpler booking tools, and Cronofy publishes a dedicated white-label API. The pattern is consistent because the market has already spoken: if your unified API provider's brand shows up anywhere your customer can see it, you're leaking trust and conversion.
As discussed in our guide to avoiding vendor lock-in, if you use a unified calendar API without white-labeling, you are essentially renting your integration credibility. You are forcing your customers to trust a vendor they have never heard of.
There's also a severe risk profile problem regarding scopes. Google's restricted scopes for Calendar require an annual security assessment for the application that holds them. If a shared vendor app holds those scopes on behalf of hundreds of SaaS companies, you're one bad actor away from Google throttling or revoking the app entirely—taking your integrations down with it. Owning the OAuth app means isolating and owning that risk profile.
The consent screen is a trust surface, not a technical detail. Enterprises will fail your security review if the app requesting access to their calendar data isn't yours. No amount of "but the vendor is SOC 2 compliant" fixes this in procurement.
How Truto's 3-Level Credential Override Hierarchy Works
Truto's Unified Calendar API supports bring-your-own-app for every OAuth-based provider, including Google Calendar, Microsoft Outlook Calendar, and any downstream provider you connect through the platform.
To support white-labeling at scale, an integration platform cannot simply hardcode client IDs and secrets into a single global state. Real B2B SaaS environments are not monolithic—you have staging, production, per-region deployments, and occasionally large enterprise customers who demand their own dedicated OAuth apps for compliance reasons.
Truto utilizes a deep-merge configuration hierarchy that resolves credentials at runtime. The mechanism is a credential override. Credentials resolve through the following three-level hierarchy, with later levels overriding earlier ones:
flowchart TD
A["Level 1: Integration-level<br>Default OAuth app shipped with integration"] --> D["Deep Merge Engine<br>Merged credential set"]
B["Level 2: Environment-level<br>Per-workspace override (staging vs prod)"] --> D
C["Level 3: Integrated Account-level<br>Per-connection override (enterprise-specific app)"] --> D
D --> E["Final Resolved Credentials<br>Injected into OAuth Flow & API Requests"]Level 1: Integration-Level Defaults
Every integration Truto ships defines a base credential structure—what fields the OAuth flow needs, the token host, authorize path, scopes, PKCE settings, and so on. For Google Calendar, this includes the correct tokenHost (https://oauth2.googleapis.com), authorizePath, the standard calendar scopes, and S256 PKCE.
When Truto ships a calendar integration, it includes a default OAuth app definition so that you can prototype quickly in a sandbox. You don't rebuild any of this underlying OAuth 2.0 configuration.
Level 2: Environment-Level Overrides
This is where the white-label magic happens for most teams. You configure your production Google Cloud OAuth app once against your production environment and your staging OAuth app against your staging environment. Truto's environment-scoped credential resolution deep-merges your client.id and client.secret on top of the integration defaults. Same integration code, different apps, cleanly separated.
A typical override looks conceptually like this:
{
"credentials": {
"oauth2": {
"config": {
"client": {
"id": "1234567890-abc.apps.googleusercontent.com",
"secret": "GOCSPX-your-production-secret"
}
}
}
}
}Notice you only override what you need. The tokenHost, authorizePath, scopes, and PKCE config from Level 1 are perfectly preserved.
Level 3: Integrated Account-Level Overrides
The third level—Integrated Account overrides—is what separates standard unified APIs from enterprise-grade infrastructure. This is the escape hatch for enterprise customers who insist on their own dedicated OAuth app.
Imagine you sell your SaaS to a highly regulated financial institution. Their IT security policy dictates that they cannot authorize a multi-tenant OAuth application. They require you to create a dedicated, single-tenant Azure AD application exclusively for their employees, or they might even provision the Azure AD app themselves and hand you the Client ID and Secret. Their security team wants to be the direct point of contact with Microsoft.
With Truto, you do not need to fork your codebase or deploy a separate instance of your integration to support this. You simply pass the customer-specific credentials when creating their integrated account connection link.
// Example: Passing a customer-specific Azure AD app to Truto
const connectionSession = await truto.createConnectionSession({
integration_id: "microsoft-calendar",
tenant_id: "enterprise_customer_123",
integration_override: {
credentials: {
oauth2: {
config: {
client: {
id: "custom_enterprise_client_id",
secret: "custom_enterprise_client_secret"
}
}
}
}
}
});When this specific customer authenticates, Truto routes them through the custom OAuth app. All subsequent token refreshes and API calls for this account will use these isolated credentials, while the rest of your user base continues to use your primary production OAuth app. This pattern is the same 3-level override architecture Truto uses for data model customization.
Practical setup order: Start with Level 1 defaults for local development. Add Level 2 overrides before your first customer beta. Only reach for Level 3 when a specific enterprise customer contractually requires it.
Proactive Token Refresh for Custom OAuth Apps
Once your white-labeled app is minting tokens, the harder problem starts: keeping those tokens fresh across thousands of connections without silent failures. Owning your OAuth app means you are responsible for the tokens it generates.
Google and Microsoft access tokens typically expire in 3600 seconds (one hour). If a background worker attempts to sync calendar events with an expired token, the API call fails, resulting in missing data and support tickets. This is where most in-house calendar integrations degrade over the first six months—a token expires at 3 AM, refresh fails silently, and your customer notices two days later when their scheduling flow breaks.
Truto handles the entire OAuth 2.0 authorization code flow (including PKCE) and assumes full responsibility for keeping your white-labeled tokens fresh. The platform employs a two-pronged strategy to ensure tokens never silently expire.
1. The 30-Second Just-In-Time Buffer
Before Truto executes any outbound request against a third-party calendar API, the execution pipeline intercepts the call to inspect the token's TTL (Time To Live). Truto enforces a hard 30-second buffer.
If the access token is set to expire in 29 seconds or less, Truto pauses the outbound API request, executes a synchronous refresh grant against the provider (using your white-labeled Client ID and Secret), updates the encrypted context in the database, and then proceeds with the original API call. This handles the common case where a token expires during a batch of long-running calls that started an hour ago.
2. Pre-Scheduled Durable Alarms
Relying purely on just-in-time refresh has a race condition: what if the next request doesn't come for another hour, and by then Google has already invalidated the refresh token? What about accounts that only receive webhook events? If a user hasn't opened your app in weeks, but they create a new event in Google Calendar, Google will send a webhook to Truto. Truto needs a valid token to fetch the full event details.
To handle asynchronous workloads, Truto schedules durable alarms. When a token is initially granted or refreshed, the platform schedules a background worker to wake up 60 to 180 seconds before the token's known expiration time, independent of whether any API call is happening. The jitter across that window prevents thundering-herd refresh storms if you have thousands of tokens expiring at once.
sequenceDiagram
participant App as Your App
participant Truto as Truto Platform
participant Provider as Google / Microsoft (Your App)
participant DB as Encrypted Store
Truto->>Provider: Exchange Auth Code for Tokens
Provider-->>Truto: Access Token (Expires in 3600s) + Refresh Token
Truto->>DB: Store Tokens (Encrypted)
Truto->>Truto: Schedule Durable Alarm (T minus 180s)
Note over Truto: 57 minutes later...
Truto->>Truto: Alarm Triggers
Truto->>Provider: POST /oauth/token (grant_type=refresh_token)
Provider-->>Truto: New Access Token
Truto->>DB: Update Tokens
Truto->>Truto: Schedule Next AlarmThe combination is important. Just-in-time alone leaves gaps. Pre-scheduled alone can miss edge cases where clock skew makes a token expire earlier than expected. Together, they give you the reliability profile you need. For a deeper dive into these mechanics, read our post on reliable OAuth token refresh architecture.
What Happens When Refresh Fails
Refresh failures are inevitable. Users revoke access from their Google account settings, admins rotate SSO configurations, or Microsoft occasionally invalidates refresh tokens during tenant migrations. When a refresh attempt fails against your white-labeled app, Truto:
- Marks the integrated account connection status as
needs_reauth. - Stops making requests against the dead token (preventing rate-limit thrashing).
- Fires an
integrated_account:authentication_errorwebhook to your backend.
Your product can listen for this event and automatically prompt the affected user to reconnect their calendar, using your own re-auth flow that hits your own consent screen. The user never sees a Truto-branded error state, entirely automating the token failure recovery process.
Handling non-standard expires_in values: Not all APIs return an expires_in parameter during token exchange. For custom integrations, Truto allows you to define a tokenExpiryDuration override in your credential configuration to enforce a strict refresh cadence regardless of the provider's response.
Handling Rate Limits on Your White-Labeled App
Here is an underappreciated reality of building API integrations: when you use your own white-labeled OAuth app, you also own the rate limits.
Google Calendar's per-project quota (currently 1,000,000 queries per day, with per-user per-second sub-limits) applies to your project. Microsoft Graph enforces complex, multi-dimensional throttling based on the tenant, the app, and the specific endpoint. This is actually a feature, not a bug—it means one noisy customer on a shared unified API platform cannot degrade your users' experience, because your traffic is isolated to your own project quotas.
Many unified API providers market themselves as a magic shield against rate limits, claiming they "handle retries automatically." This is an architectural anti-pattern. If a unified API blindly retries a 429 Too Many Requests error without understanding the priority of the workload, it will quickly exhaust your remaining quota and lock up your entire application.
Truto takes a radically honest, developer-first approach: We do not swallow your rate limits.
When a provider returns an HTTP 429, Truto passes that error directly back to your application. However, because every provider formats rate limit headers differently (e.g., Google returns X-RateLimit-Remaining while Microsoft returns Retry-After), Truto normalizes the upstream rate limit information into standard IETF headers:
ratelimit-limit: The total request quota available in the current window.ratelimit-remaining: The number of requests left before throttling occurs.ratelimit-reset: The timestamp (in seconds) when the quota window resets.
By passing these normalized headers to your system, Truto gives your engineering team full visibility into your white-labeled app's quota consumption. You decide the retry strategy that fits your product's SLA.
Example: Implementing a Circuit Breaker
Because Truto exposes the exact reset window, your application can catch the 429 error, read the ratelimit-reset header, and pause background synchronization for that specific user until the window clears, allowing high-priority user-facing requests to succeed.
async function createCalendarEventWithBackoff(accountId: string, eventData: any) {
try {
const response = await fetch(`https://api.truto.one/unified/calendar/events?integrated_account_id=${accountId}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${TRUTO_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(eventData)
});
if (response.status === 429) {
// Truto normalizes the upstream provider's reset time
const resetTime = parseInt(response.headers.get('ratelimit-reset') || '0', 10);
const waitSeconds = Math.max(0, resetTime - Math.floor(Date.now() / 1000));
console.warn(`Rate limited by upstream provider. Pausing for ${waitSeconds} seconds.`);
// Push to a delayed queue based on the exact reset time
await delayQueue.push({ accountId, eventData }, { delay: waitSeconds * 1000 });
return null;
}
return await response.json();
} catch (error) {
// Handle network errors
}
}This architecture keeps you in control. You decide whether a background calendar sync should be delayed, or whether a user-facing booking request should fail fast with a friendly error message.
Security and Encryption of White-Labeled Credentials
Handing a third party your production OAuth client secret is not a trivial ask. When you configure a custom Google Cloud or Azure AD app in Truto, you are entrusting the platform with highly sensitive credentials. Truto's security posture around this is uncompromising:
- Strict encryption at rest: Fields like
client_secret,access_token,refresh_token, and any API keys are stored under AES-256-GCM encryption, never in plaintext. - Protected context paths: Truto maintains an internal list of protected context paths. When Truto exchanges an authorization code for tokens, the payloads are mapped to specific paths (e.g.,
context.oauth.token.access_token). Any data stored at these paths is encrypted before being written to the database. - Masked in list responses: When you query the Truto API to list your integrated accounts, sensitive fields are automatically masked in the response payload. The raw tokens are only decrypted in memory at the exact moment the execution engine needs to construct the
Authorization: Bearer <token>header for an outbound request. - Separation of material: Your client secret and the resulting access/refresh tokens are stored separately. Compromise of one does not automatically compromise the other.
This security model ensures that even if you grant your support team access to the Truto dashboard to debug integration issues, they cannot view or export the raw OAuth tokens belonging to your customers. This is the same encryption posture we cover in more depth in our OAuth lifecycle and CSRF protection guide.
Truto is SOC 2 Type II certified and does not persist calendar payload data by default when using pass-through mode. Your OAuth secrets are encrypted, and the event data itself flows through in real time without being cached.
Normalizing the Complexities of Scheduling Data
While owning the OAuth app solves the branding and trust problem, it does not solve the engineering problem of actually parsing calendar data.
Google Calendar and Microsoft Outlook treat scheduling concepts very differently. Recurrence rules (RRULEs) are notoriously difficult to parse, timezone handling varies wildly, and calculating free/busy availability requires complex aggregation logic.
By using Truto as your execution engine, you get the best of both worlds. You retain complete brand control over the OAuth consent screen, but your engineering team interacts with a single, normalized schema.
When you request availability for a user, Truto translates that request into the specific syntax required by Google or Microsoft, aggregates the response, and returns a clean array of available time slots. You do not have to read the Microsoft Graph documentation, and you do not have to write provider-specific parsing logic.
Own Your Calendar Integrations, Not Just Rent Them
B2B SaaS companies should not have to choose between engineering velocity and brand trust. Building native calendar integrations from scratch is a massive capital expense, often exceeding $80,000 per provider just for the initial build and ongoing maintenance. Conversely, using a traditional unified API provider forces you to show a third-party logo on your consent screens, alienating enterprise customers, drastically reducing conversion rates, and creating a migration cliff if you ever need to switch providers.
Truto's architecture solves this dichotomy. By supporting full white-labeled OAuth, 3-level credential overrides, and proactive token lifecycle management, Truto gives your engineering team the speed of an abstraction layer without sacrificing an ounce of brand control. Your OAuth secrets stay encrypted, your rate limits stay visible, and your customers only ever see your name.
Next steps if you're evaluating Truto for calendar integrations:
- Prototype against Truto's default OAuth app to validate the unified schema fits your product.
- Register your own Google Cloud project and Azure AD app, request the calendar scopes you need, and start Google's verification process early—it takes weeks, not days.
- Configure a Level 2 environment override with your production client ID and secret. Test the consent screen to ensure it shows your brand.
- Wire up the
integrated_account:authentication_errorwebhook so you can handle re-auth gracefully in your product UI.
FAQ
- Can I use my own Google Cloud project for calendar sync?
- Yes. Truto supports bring-your-own-app for every OAuth-based calendar integration. You configure your own Google Cloud Platform (GCP) OAuth application, ensuring your users see your branding and privacy policy on the consent screen.
- How does Truto handle OAuth token refresh for custom apps?
- Truto proactively refreshes tokens using a two-pronged strategy: a 30-second synchronous just-in-time buffer before API calls, and pre-scheduled durable alarms that refresh tokens 60-180 seconds before expiration with built-in jitter.
- Does Truto absorb rate limits for white-labeled calendar apps?
- No. Truto passes upstream 429 HTTP errors directly back to your application, alongside normalized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset), so your system can implement proper backoff logic accurately.
- Can I use different OAuth apps for different enterprise customers?
- Yes. Truto's 3-level credential hierarchy allows you to override OAuth credentials on a per-account basis. This supports strict single-tenant enterprise requirements where a customer demands their own dedicated Azure AD or Google app.
- What happens if a user revokes access to my white-labeled calendar app?
- If a refresh attempt fails due to revocation, Truto marks the connection as needs_reauth and fires an integrated_account:authentication_error webhook to your backend, allowing you to automatically prompt the user to reconnect.