Connect APIs with Signed JWT authentication
Last updated: 10 July 2026
Many enterprise APIs authenticate machine-to-machine clients with a signed JWT assertion (RFC 7523): you register a public key with the provider, Honeybase signs a short-lived JWT with the matching private key, and the provider either exchanges it for an access token or accepts the JWT itself as the bearer token. Your private key is stored encrypted in Honeybase's secret vault, signing happens server-side, and minted tokens are cached until they expire.
To use it, create an HTTP integration (Integrations → New → HTTP), set the Base URL to the API you want to call, and pick Signed JWT as the authentication type. Choose your provider from the preset dropdown and adjust the placeholder values as described below. Then call the API from any workflow with the Call API node — the token is minted and injected automatically.
Providers
How the form maps to JWT concepts
Every provider uses the same building blocks; only the values differ.
- Issuer (iss) — who is asking: a client id, a service-account email, or an app id.
- Subject (sub) — who to act as. For Google this is the Workspace user you impersonate; for Salesforce the integration user; often it equals the issuer.
- Audience (aud) — who the JWT is for, usually the provider's token endpoint.
- Exchange request — the HTTP call that swaps the assertion for an access token. Write
{{signed_jwt}}wherever the freshly signed JWT belongs; Honeybase substitutes it on every mint. Uncheck the exchange option for providers (Apple, Snowflake) where the signed JWT itself is the bearer token. - Private key — PKCS#8 PEM (
-----BEGIN PRIVATE KEY-----). GitHub's PKCS#1 keys (-----BEGIN RSA PRIVATE KEY-----) are also accepted. Convert anything else withopenssl pkcs8 -topk8 -nocrypt -in key.pem.
The Test button under the form signs an assertion and runs the exchange (or shows the decoded claims in direct mode) so you can verify the setup before saving.
Google service accounts (Workspace, Admin SDK, Gmail, Calendar)
- In the Google Cloud console, create a service account and download a JSON key.
- For Workspace APIs that act on behalf of users (Admin SDK, Gmail, Calendar), enable domain-wide delegation: in the Google Admin console go to Security → Access and data control → API controls → Domain-wide delegation, add the service account's client ID, and authorize the exact scopes you will request (e.g.
https://www.googleapis.com/auth/admin.directory.userto create users). - In Honeybase pick the Google service account preset and paste the downloaded JSON key — the issuer, private key and token endpoint fill themselves.
- Set Subject to the email of a super-admin (or a user with the needed admin role) — this is the user the service account impersonates. Without it, Workspace admin APIs return 403.
- Set the Scope claim to the same scopes you authorized in step 2.
Example: to create Workspace users on onboarding, set Base URL to
https://admin.googleapis.com and use a Call API node with
POST /admin/directory/v1/users.
Google caps assertion lifetime at 3600 seconds.
Microsoft Entra ID (Azure AD) — Microsoft Graph
- Register an application in Entra ID and upload a certificate (public key). Note the certificate's thumbprint-derived key id if you use one, and grant the app the application permissions you need (e.g.
User.ReadWrite.All) with admin consent. - Pick the Microsoft Entra ID preset. Set issuer and subject to the app's client ID, and replace
your-tenant-idin the audience and exchange URL with your tenant. - Entra sends the JWT as a
client_assertioninside a client-credentials grant — the preset's exchange request is already shaped that way; keepscope=https://graph.microsoft.com/.default.
Entra requires the x5t (certificate thumbprint) header rather
than a plain kid for certificate credentials; when connecting
Entra prefer a client secret via OAuth (Client Credentials) unless your policy mandates
certificates. If you do use certificates, set Key ID to the base64url SHA-1 thumbprint
Entra shows for the uploaded certificate.
Salesforce
- Create a Connected App with "Use digital signatures" enabled and upload your certificate. Enable the OAuth scopes you need and pre-authorize the integration user's profile (JWT flows never show a consent screen).
- Pick the Salesforce preset. Issuer = the Connected App's consumer key; Subject = the integration user's username; Audience =
https://login.salesforce.com(orhttps://test.salesforce.comfor sandboxes — change the exchange URL too).
Salesforce token responses contain no expires_in, so the preset uses a fixed 110-minute token lifetime; lower it if your org's session timeout is shorter. Salesforce rejects assertions older than 3 minutes, so leave the lifetime around 180 seconds.
DocuSign
- In a DocuSign app, generate an RSA keypair and grant the app consent for impersonation once (via the consent URL) for the API user.
- Pick the DocuSign preset. Issuer = the app's integration key; Subject = the API user's user GUID (not email); Audience =
account.docusign.com(account-d.docusign.comfor the developer sandbox — change the exchange URL to match). - Keep the scope claim
signature impersonation.
Note the DocuSign audience is a bare hostname without https://.
Box
- Create a Box app with JWT authentication, generate a keypair, and authorize the app in the Box admin console.
- Pick the Box preset. Issuer = client ID; Subject = your enterprise ID; Key ID = the public key ID Box shows; keep the
box_sub_typecustom claim and the randomjti(Box requires both). - Box additionally requires
client_idandclient_secretin the exchange body — the preset includes the fields; fill the secret value and mark it sensitive.
Box rejects assertions with a lifetime over 60 seconds.
Okta
- Create an API services app with public key / private key client authentication (
private_key_jwt) and grant it the Okta API scopes you need (e.g.okta.users.manage). - Pick the Okta preset. Issuer and Subject are both the app's client ID; replace
yourorg.okta.comwith your Okta domain in the audience and exchange URL, and set the requested scopes in the exchange body.
Okta requires the random jti claim (already enabled in the
preset) and caps assertion lifetime at one hour; the preset uses 5 minutes.
GitHub Apps
- In your GitHub App's settings, generate a private key (GitHub downloads a PKCS#1 PEM — paste it as-is, Honeybase converts it) and install the app on your org, noting the installation ID from the installation URL.
- Pick the GitHub App preset. Issuer = the App ID (no subject or audience), and replace
your-installation-idin the exchange URL.
GitHub is unusual: the JWT is sent as a Bearer header to the
installation-token endpoint, and the response's token +
expires_at (ISO timestamp) are mapped by the preset. GitHub
rejects JWTs living longer than 10 minutes and recommends
backdating iat by 60 seconds for clock skew — the preset does
both.
Apple (App Store Connect)
- In App Store Connect, create an API key (Users and Access → Integrations) and download the
.p8file — it is already PKCS#8. - Pick the Apple preset. Issuer = the Issuer ID shown above the key list; Key ID = the key's ID; algorithm is ES256.
Apple accepts the signed JWT directly as the bearer token — there is no exchange, so the preset unchecks it. Assertions are capped at 20 minutes; Honeybase re-signs automatically when one expires.
Snowflake
- Assign a public key to your Snowflake user (
ALTER USER ... SET RSA_PUBLIC_KEY = '...') and compute the key's SHA-256 fingerprint (DESCRIBE USERshows it asRSA_PUBLIC_KEY_FP). - Pick the Snowflake preset. Issuer =
ACCOUNT.USER.SHA256:<fingerprint>; Subject =ACCOUNT.USER(both uppercase). - Like Apple, Snowflake uses the JWT directly as the bearer token (SQL API requests also need the header
X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT— add it as a default header on the integration).
Security notes
- Private keys are write-only: they are stored in Honeybase's encrypted vault, used for signing server-side, and never returned to the browser or exposed to workflow JavaScript.
- Scope service accounts and apps minimally — grant only the scopes your workflows call, and prefer a dedicated integration user over a personal admin account for impersonation.
- Rotating a key: generate the new key with the provider, then paste the new private key into the integration and save — saving new credentials immediately discards any cached tokens, so the next request signs with the new key. Remember to also revoke the old key on the provider's side.