Skip to Content
ConceptsBring your own credentials

Bring your own credentials

Synq ships with default OAuth credentials so you are running in sixty seconds. Once your Brand has any reputation, swap them for your own. The user will see your company name on Google’s or Apple’s consent dialog instead of Synq’s. This page is how.

What “BYO” actually means

For each OAuth provider, you register an app on the provider’s side (Google Cloud Console, Apple Developer, Discord Developer Portal, etc.), get a client_id + client_secret from them, and plug those into the Brand’s configuration in Synq.

After that, when a user signs in via your Brand:

  • The OAuth consent dialog the user sees during sign-in shows your company name (the one registered with the provider).
  • Your logo and your privacy policy URL render on the provider’s consent dialog.
  • The OAuth tokens issued by the provider are tied to your app, not Synq’s. Your usage counts against your provider quota, not ours.

The model

interface BrandConnection { brand: string // owning Brand id type: | 'google' | 'apple' | 'microsoft' | 'discord' | 'facebook' | 'x' | 'telegram' | 'matrica' enabled: boolean encryptedConfig: string // AES-256-GCM ciphertext of JSON config createdAt: string updatedAt: string }

The (brand, type) pair is unique — at most one connection per provider per Brand. The config is encrypted at rest; only the metadata (enabled state, audit info) is queryable from the API.

Per-provider config shapes

Each provider’s connection stores the fields Synq needs to act on the brand’s behalf during a sign-in.

Google

{ type: 'google', config: { clientId: '<from Google Cloud Console>', clientSecret: '<from Google Cloud Console>', // callbackUrl is derived; you only confirm it on Google's side } }

Apple

{ type: 'apple', config: { teamId: 'XXXXXXXXXX', // 10-char Team ID from Apple Developer clientId: 'com.acme.web', // Service ID keyId: 'YYYYYYYYYY', // Key ID from Keys page privateKey: '-----BEGIN PRIVATE KEY-----\n\n-----END PRIVATE KEY-----', } }

Microsoft (Azure AD)

{ type: 'microsoft', config: { tenantId: '<your tenant uuid>' | 'common', clientId: '<application (client) id>', clientSecret: '<client secret value>', } }

Discord

{ type: 'discord', config: { clientId: '<application id>', clientSecret: '<oauth2 client secret>', } }

Facebook

{ type: 'facebook', config: { appId: '<app id>', appSecret: '<app secret>', } }

X (Twitter v2)

{ type: 'x', config: { clientId: '<x developer portal client id>', clientSecret: '<x developer portal client secret>', } }

Matrica

{ type: 'matrica', config: { clientId: '<matrica developer console client id>', clientSecret: '<matrica developer console client secret>', } }

Telegram

{ type: 'telegram', config: { botUsername: 'AcmeAuthBot', // without @ botToken: '<from @BotFather>', } }

The Telegram bot domain must be bound to synq.id in BotFather (/setdomain), since that is the domain serving the login widget. One bot per Brand; the default Synq bot only works on synq.id-hosted sign-in surfaces. See Providers — Telegram.

The callback URL is brand-stable

When you register the OAuth app on the provider’s side, the redirect URI you give them looks like this:

https://synq.id/oauth/<provider>/<brand.oauthCallbackId>/callback

oauthCallbackId is a globally unique, immutable identifier on the Brand. You can rename the brand, change its slug, change its logo, move it to a different org — the oauthCallbackId stays. The redirect URI you gave Google never has to change once configured.

You set it once, on the provider’s side, and forget it.

API — setting up a connection

Setup via the Dashboard is the path for almost everyone. The API path is for automation (Terraform, CI, agents):

PUT /identity/organizations/<orgSlug>/brands/<brandSlug>/connections Authorization: Bearer <m2m token with IdentityOrgPermission.ConnectionsEdit> Content-Type: application/json { "type": "google", "enabled": true, "config": { "clientId": "1234567890-abc.apps.googleusercontent.com", "clientSecret": "GOCSPX-…" } }

Response: the connection metadata (no plaintext config). The encryptedConfig is stored server-side encrypted at rest.

Toggle without rewriting the config:

PATCH /identity/organizations/<orgSlug>/brands/<brandSlug>/connections/google/enabled Content-Type: application/json { "enabled": false }

Delete (reverts to Synq default credentials):

DELETE /identity/organizations/<orgSlug>/brands/<brandSlug>/connections/google

Encryption at rest

Configs are encrypted with AES-256-GCM. The key lives in Synq’s secret store; it never appears in logs, audit records, or API responses. Decryption happens only at sign-in time, only in memory, only on the request path that needs it.

When you rotate a provider credential (a new secret in Google Console, a new .p8 for Apple), do PUT again with the new value:

  • The new ciphertext overwrites the previous one.
  • The old plaintext is unrecoverable from Synq’s side.
  • The change takes effect on the next sign-in attempt; no users are signed out.

When BYO is required

Some providers practically require BYO before you ship to real users.

ProviderBYO needed for production?
AppleEffectively yes. Apple’s review team checks. Brand-mismatched consent screens damage trust.
TelegramYes always. The default Synq bot is hostname-scoped to synq.id; your sign-in surface (typically app.yourdomain.com) needs its own bot.
MicrosoftYes if you ship to Azure AD tenants (their admins will only consent for your app).
GoogleRecommended before any traffic. Synq defaults will hit quota and the wrong company name appears.
DiscordRecommended; rate limits matter at scale.
FacebookRequired if you need email permission for non-developers.
XRecommended; per-app quotas.
MatricaRecommended; vendor relationship makes BYO cleaner.

For prototype-stage products, defaults are fine. For production traffic, BYO is the right move.

Provider-by-provider setup guides

The exact click paths for each provider are in Guides:

Mental model summary

  • BYO swaps Synq’s defaults for your own provider credentials on a per-Brand basis.
  • The callback URL pattern includes the brand’s oauthCallbackId, so once you set the URL with the provider, it never needs to change.
  • Configs are encrypted at rest. Decryption is request-path only.
  • Apple, Telegram, Microsoft tenants — these are the providers that need BYO before you can take real traffic. Default-friendly providers (Google, Discord, X) can wait until you cross meaningful scale.
Last updated on