All topics
Get started8Account, team & permissions44Units & fields70Records, views & tasks39WhatsApp & Cortex Chat68Email & social27Lead ads & distribution38Automations52Documents & quotes32Dashboards40Cortex AI18Developers & API12
Help Center·448 guidesAll topicsContact support

Add a “Connect to Corteksa” button with OAuth 2.0

For an app published to many clients, use the authorization code flow with PKCE: the client approves on the permissions screen, and you exchange the code for an access token that starts with crtk_oauth_ and a refresh token.

7 min
Before you start · 1 thing · for owners
Your app registered with the Corteksa team
  • Your app registered with the Corteksa team: its name, redirect URIs, allowed scopes and client type. You get a client_id that starts with crtk_app_, and a secret for apps with a server.

Steps

1
Send the user’s browser to https://{HOST}/en/oauth/authorize with client_id, redirect_uri, scope, state and response_type=code, plus code_challenge with code_challenge_method=S256 for public clients.
This is the consent screen in the Corteksa app. A signed-out user is sent to sign in and doesn’t come back to this screen, so they have to start the connection again from your app.
2
The user presses Authorize, or Cancel to refuse.
The browser returns to your URI with ?code=...&state=..., or ?error=access_denied.
3
Check state.
4
From your server, send POST https://{HOST}/api/v1/oauth/token with grant_type=authorization_code, code, redirect_uri, client_id, and client_secret or code_verifier.
The response is standard JSON: access_token, refresh_token, expires_in and scope.
5
Save the host, the tokens and the expiry date for each client, and call the API with Authorization: Bearer crtk_oauth_....
6
Refresh before expiry with grant_type=refresh_token, and save the new refresh token every time.

Don’t call the token endpoint from the browser, and don’t put client_secret or any crtk_oauth_ token in front-end code.

The 2 client types

Type
For
Authentication
Confidential
An app with a server
client_secret
Public
A single-page app or a mobile app
PKCE (S256) required, with no secret

The rules

The redirect URI matches the registered one exactly. The code is used once, within 60 seconds. The granted scopes are within the requested ones, the requested ones are within what the app is allowed, and all of them are within the user’s live permissions.

Wildcard scopes such as read.* cover every unit the user can reach, so your app can choose any unit to sync without registering again.

Revoking

Revoke from your server with POST /api/v1/oauth/revoke, sending token, client_id and client_secret. Or the client disconnects your app as in Authorize or disconnect a third-party app, and the tokens stop straight away.

If something goes wrong

What you see
Why
What to do
A “This app can’t be connected” screen
The client_id is unknown, the redirect URI doesn’t match, a scope isn’t allowed, or PKCE is missing.
Correct the authorization request. The browser isn’t redirected on an error.
“You don’t have permission to grant the access this app is requesting.”
The user doesn’t have the permissions.
Request fewer scopes, or the owner raises their permissions.
invalid_grant: code is invalid, expired, or already used
The code is old or already used.
Exchange it right after the browser returns.
invalid_grant: redirect_uri mismatch
The URI differs by a character.
Use the same URI in both steps.
invalid_client
A wrong secret, or an inactive app.
Check the app’s details.

Good to know

An access token lasts about an hour, and a refresh token about 30 days, replaced on every refresh.
Using an old refresh token counts as a leak, and revokes every token of that connection.
The app name is up to 120 characters, and the description up to 500.
Redirect URIs are HTTPS, and http is accepted on localhost for development.
Apps are registered through the Corteksa team only.
Did this guide solve it?
If not, we’ll ask what was missing.
Open in Corteksa
Did this guide solve it?

We read every answer. To get a reply, use Contact support.