Authentication

This guide explains how to integrate with the Mindoo API using the OAuth 2.0 authorization code flow with PKCE (proof key for code exchange). This is the recommended approach for securely accessing user data on behalf of your users.

Prerequisites

Before you begin, make sure you have:

  1. A registered OAuth application with Mindoo (contact support@mindoo.ai to obtain your client_id). Only approved clients will be able to consume the API through OAuth.
  2. A configured redirect URI for your application

Overview

The OAuth flow consists of three main steps:

  1. Authorization: Redirect the user to the Mindoo authorization endpoint to obtain an authorization code
  2. Token exchange: Exchange the authorization code for tokens
  3. API access: Use the id_token to authenticate API requests

Step 1: Obtain user authorization

Redirect your user to the Mindoo authorization endpoint to initiate the OAuth flow. The link to this endpoint should be given to you by the Mindoo support team.

Authorization endpoint

GET https://api.mindoo.ai/auth/oauth2/authorize

Required parameters

Parameter Description
response_type Must be code
client_id Your OAuth application’s client ID
redirect_uri The URL where users will be redirected after authorization (must match your registered redirect URI)
scope Space-separated list of requested scopes
state A random string to prevent CSRF attacks (you should verify this value when the user is redirected back)
code_challenge A PKCE code challenge (Base64 URL-encoded SHA-256 hash of a random code verifier)
code_challenge_method Must be S256

Available scopes

Scope Description
openid Required for OpenID Connect
profile Access to user profile information
email Access to user email address
offline_access Request a refresh token for long-lived access
read Read access to API resources
write Write access to API resources

At minimum, you should request the openid, email, read, and write scopes to consume the API. It’s also adviced to include the offline_access scope in order to obtain new tokens without requiring user interaction.

Example authorization URL

https://api.mindoo.ai/auth/oauth2/authorize?response_type=code&client_id=TkkjdhfiuhibksufiniutUgUQRjQlREwS&redirect_uri=https://your-website.com/api/oauth/callback&scope=openid%20profile%20offline_access%20email%20read%20write&state=<RANDOM_STATE_TO_PREVENT_XSRF_ATTACK>&code_challenge=<UNIQUE_CODE_CHALLENGE>&code_challenge_method=S256

Generating the PKCE code challenge

The PKCE flow requires you to generate a code verifier and its corresponding code challenge:

Node.js example

import crypto from "node:crypto"

const codeVerifier = crypto
  .randomBytes(32)
  .toString("base64")

const codeChallenge = crypto
  .createHash("sha256")
  .update(codeVerifier)
  .digest("base64url")

Python example

import base64
import hashlib
import secrets

code_verifier = base64.b64encode(secrets.token_bytes(32)).decode()

digest = hashlib.sha256(code_verifier.encode()).digest()

code_challenge = base64.urlsafe_b64encode(digest).decode().rstrip("=")

Store the code_verifier securely. You will need it in Step 2 to exchange the authorization code for tokens.

Handling the callback

After the user authorizes your application, they will be redirected to your redirect_uri with the following query parameters:

  • code: The authorization code (valid for a short time)
  • state: The state value you provided (verify this matches your original value)

Example callback URL:

https://your-website.com/api/oauth/callback?code=abc123&state=your_random_state

Always verify that the state parameter matches the value you sent in the authorization request to prevent CSRF attacks.

Step 2: Exchange the authorization code for tokens

Once you have the authorization code, exchange it for tokens by making a POST request to the token endpoint.

Token endpoint

POST https://api.mindoo.ai/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

Request body parameters

Parameter Description
grant_type Must be authorization_code
code The authorization code received from the callback
redirect_uri The same redirect URI used in the authorization request
client_id Your OAuth application’s client ID
code_verifier The PKCE code verifier you generated in Step 1

Example request

curl -X POST https://api.mindoo.ai/auth/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=<AUTHORIZATION_CODE>" \
  -d "redirect_uri=https://your-website.com/api/oauth/callback" \
  -d "client_id=<YOUR_CLIENT_ID>" \
  -d "code_verifier=<YOUR_CODE_VERIFIER>"

Response

A successful response returns a JSON object containing:

{
  "access_token": "mrIFnBgEZhujFqGOXr...",
  "expires_in": 3600,
  "expires_at": 1768476855,
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "scope": "openid profile offline_access email read write",
  "refresh_token": "uvTyyNoCtyPwpUFkTtCIWR...",
  "token_type": "Bearer"
}
Field Description
access_token The access token (not used yet)
id_token A JWT containing user identity information and granted scopes, used to authenticate API requests
refresh_token A long-lived token used to obtain new tokens (only present if offline_access scope was requested)
token_type Always Bearer
expires_in Token validity in seconds
scope Space-separated list of granted scopes

Store the refresh_token securely in your database. You will need it to obtain new tokens when the current one expires.

Step 3: Use the token to access the API

Use the id_token to authenticate your API requests by including it in the Authorization header.

Verifying API access

Use the GET /api/verify-token endpoint to verify that your token works and to see which user and organization you are authenticated as.

curl -X GET https://api.mindoo.ai/verify-token \
  -H "Authorization: Bearer <ID_TOKEN>"

You can optionally specify which organization to authenticate as by setting the x-organization-id header. The user must be a member of the specified organization.

curl -X GET https://api.mindoo.ai/verify-token \
  -H "Authorization: Bearer <ID_TOKEN>" \
  -H "x-organization-id: <ORGANIZATION_ID>"

Example response:

{
  "organization": {
    "id": "abc123",
    "name": "Example Hospital"
  },
  "user": {
    "email": "doctor@example.com",
    "firstName": "John",
    "type": "oauth"
  }
}

Refreshing tokens

When the id_token expires, use the refresh_token to obtain new tokens without requiring user interaction.

Refresh token request

POST https://api.mindoo.ai/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

Request body parameters

Parameter Description
grant_type Must be refresh_token
refresh_token The refresh token from your database
client_id Your OAuth application’s client ID

Example request

curl -X POST https://api.mindoo.ai/auth/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=<YOUR_REFRESH_TOKEN>" \
  -d "client_id=<YOUR_CLIENT_ID>" 

Response

The response contains a new set of tokens:

{
  "access_token": "mrIFnBgEZhujFqGOXr...",
  "expires_in": 3600,
  "expires_at": 1768476855,
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "scope": "openid profile offline_access email read write",
  "refresh_token": "uvTyyNoCtyPwpUFkTtCIWR...",
  "token_type": "Bearer"
}

Each refresh request returns a new refresh_token and revokes the previous one. Always update the stored refresh_token in your database with the new value.

Security best practices

Please keep in mind to:

  1. Store tokens securely. Never expose tokens in client-side code or logs. Store refresh_token encrypted in your database.
  2. Validate the state parameter. Always verify the state parameter matches your original value to prevent CSRF attacks.
  3. Handle token expiration. Implement automatic token refresh before the id_token expires.
  4. Minimize scope. Only request the scopes your application actually needs.