This page assumes that you have already registered your application with SID, received your client credentials, and set them as environment varibles. See the credentials page for more details.

Initiate Flow

The authorization flow is initiated by redirecting a user to the SID authorization URL, shown below:

https://me.sid.ai/api/oauth/authorize

To correctly initate the flow, you must also provide a set of query parameters to the URL. One way to achieve this is to navigate to an API route in your application, which constructs the authorization URL and redirects the user to it.

import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const params = {
      'response_type': 'code',
      'scope': 'query:data offline_access',
      'client_id': process.env.SID_CLIENT_ID,
      'redirect_uri': process.env.SID_REDIRECT_URI,
  };

  const authUrl = new URL('https://me.sid.ai/api/oauth/authorize');
  authUrl.search = new URLSearchParams(params).toString();

  res.redirect(authUrl.toString());
}

With this route exposed under https://example.com/api/sid/connect, you can allow the user to initiate the flow by providing a link to this path, as shown below:

<a href="https://example.com/api/sid/connect">Connect to SID</a>

This will dynamically construct the authorization URL and redirect the user to it.

The required scopes are currently fixed to query:data and offline_access. The former allows usage of the query endpoint, and the latter allows refreshing of tokens. In the future, the API may support more granular scopes.

Currently, all query parameters take fixed values, and the URL could be constructed statically. However, dynamic query parameters may be added in the future, so it is recommended to construct the URL dynamically.

Callback

The authorization URL will redirect the user to their SID account, where they will be prompted to log in and grant access permissions to your application. Once they have done so, they will be redirected back to your application with an authorization code. You will need to provide a redirect URI to handle this callback.

For example, if your application is hosted at https://example.com, you could specify a redirect URI of https://example.com/api/sid/callback. You should then handle incoming GET requests to this URI to receive the authorization code, which is provided in the code query parameter.

Continuing with the example, a possible callback would be a GET request to https://example.com/api/sid/callback?code=96843854772.

After handling the callback, you should redirect the user back to your application. In the following example, the user is redirected to https://example.com, but you can redirect them to any page in your application.

The token exchange is discussed in the next section.

import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  // get authorization code from query string
  let code = req.query.code;
  if (!code) {
    // show an error page to the user
    res.redirect('http://example.com/error');
    return;
  }
  // perform token exchange to get access token and refresh token
  let { accessToken, refreshToken } = await tokenExchange(code);

  // save tokens to database 
  // ...

  // redirect user back to your application
  res.redirect('http://example.com');
}

After the user has been redirected back to your application, the authorization flow is complete. You now have an access token and a refresh token, which you can use to make requests to the SID API.

Do not persist the authorization code. It is only valid for a few minutes, and its sole purpose is to be exchanged for tokens.

Token Exchange

The authorization code received in the callback is only valid for a short time, and must be converted into an access token and a refresh token using a token exchange, as shown below:

import axios from 'axios';

async function tokenExchange(code: string) {
  // construct request data
  const data = {
    grant_type: 'authorization_code',
    client_id: process.env.SID_CLIENT_ID,
    client_secret: process.env.SID_CLIENT_SECRET,
    redirect_uri: process.env.SID_REDIRECT_URI,
    code: code,
  };

  // send request to SID token endpoint
  const response = await axios.post('https://auth.sid.ai/oauth/token', data);

  // return tokens
  return {
    refreshToken: response.data.refresh_token,
    accessToken: response.data.access_token,
    expiresIn: response.data.expires_in,
  }
}

Refreshing Tokens

The access token is valid for a limited time period. After it expires, you will need to use the accompanying refresh token to obtain a new access token. The below code example shows the process.

import axios from 'axios';

async function refreshAccessToken(refreshToken: string) {
    const data = {
        grant_type: 'refresh_token',
        client_id: process.env.SID_CLIENT_ID,
        client_secret: process.env.SID_CLIENT_SECRET,
        redirect_uri: process.env.SID_REDIRECT_URL,
        refresh_token: refreshToken,
    };
    const response = await axios.post('https://auth.sid.ai/oauth/token', data);
    const { access_token } = response.data;
    return access_token;
}

Storing Tokens

The tokens are values which are associated with a particular user of your application. Hence, you should store them in your database, associated with the user’s account. For exmple, your users table could have the following additional columns:

  • sid_access_token
  • sid_refresh_token
  • sid_expires_at

When you receive the tokens, you should store them in these columns. Then, when you need to make a request to the SID API, you can retrieve the access token from the database.

The expires_at value can be used to determine whether the access token is still valid, or whether you need to refresh it.

Redis

As the refresh token is the only long-lived object, and new access tokens can always be derived from it, it is not strictly necessary to store the access token in your database. You may want to consider storing it in an in-memory cache such as Redis if performance is a concern.

In Redis, you can store the access token as an item with an expiry time. You can then retrieve it from Redis when you need to make a request to the SID API, and refresh it if it is unavailable due to having expired.