AIRisk API OAuth2 Authentication
Describing Oauth2 and, more specifically, our authentication process in AIRisk, Prescribing usage, and Explaining our components and process.
Last updated
Describing Oauth2 and, more specifically, our authentication process in AIRisk, Prescribing usage, and Explaining our components and process.
Last updated
The AIRisk API uses OAuth 2.0 – the industry-standard protocol for authorization – to allow third-party applications to access its resources securely (see the OAuth 2.0 spec RFC 6749 and a high-level OAuth2 overview for more information).
In essence, OAuth2 enables your application (the client) to obtain limited access to a resource owner's account (the user) without sharing the user's credentials. It works by delegating user authentication to the service that hosts the user account (the AIRisk platform) and then authorizing the client to access resources on the user's behalf, as described in this introduction to OAuth 2.0.
AIRisk API implements an Authorization Code Grant flow. This is a two-step process:
Authorization Request: Your application directs the user’s browser to AIRisk’s Authorization Endpoint with your client_id
, a redirect_uri
, and optionally a userid
if you are requesting a user-specific token. If requesting a user-specific token, the userid
must be an existing id
on some ApplicationUser
in the AIRisk deployment. Also,
client_id
and client_secret
must be valid for some APIUser
in the instances database.
redirect_uri
must match at least one comma-separated value in the same APIUser
s (as the client id & secret) redirect_uri
column
Authorization Code Redirect: If AIRisk’s authorization server authorizes the request, then it redirects the client back to the specified redirect_uri
with an authorization code in the URL (e.g. https://localhost/callback?code=REMOTELY_GENERATED_AUTH_CODE_HERE). This code is short-lived and cannot be used by itself except to request a token.
Token Request: Your application then makes a secure POST request to the Token Endpoint, providing the code along with your client_id
, client_secret
, redirect_uri
, and (if used in step 1) the same userid
. This step happens server-to-server (backend of your app to AIRisk API) and does not involve the user’s browser.
Token Response: If the request is valid, the AIRisk authorization server responds with a JSON payload containing an access_token (and possibly other details like expiration). This token can then be used by your app to authenticate future API requests to AIRisk (usually by including it in an HTTP Authorization: Bearer header).
(Optional) Error Handling: If any step fails (e.g., missing parameters, invalid code, or user denies access), an error will be returned instead of an access token. Error responses are yielded as HTTP Reponses with a status_code
int, and a reason
string explaining the error. Some endpoints like /api/oauth2
return a response with json bodies containing fields for further understanding and debugging the error.
Note: The AIRisk OAuth2 flow supports two modes of obtaining tokens:
Generic tokens – obtained by omitting the
userid
parameter. These tokens are not tied to any specific end-user; they represent the application’s own access.User-specific tokens – obtained by including a
userid
. These tokens represent an authorization on behalf of a particular user. The following sections detail how to use each endpoint and clarify the differences between these token types.
GET /api/oauth2
)The Authorization Endpoint is the URL that the user’s browser visits to initiate the OAuth flow. It is used to request user authorization and produce an authorization code.
Endpoint: GET /api/oauth2
Purpose: Initiate an OAuth2 authorization code request (user login & consent).
Query Parameters:
client_id
(string, Required)
– Your application’s client identifier. This value is provided when you register your app with AIRisk. It tells the authorization server which application is making the request.
redirect_uri
(string, Required)
– The URL in your application where users will be sent after authorization. This must match one of the allowed redirect URIs you configured for your client. After the user approves or denies the request, AIRisk will redirect their browser to this URL with additional parameters (code or error).
userid
(string, Optional)
– An identifier for the user on whose behalf the authorization is being requested. Include this if you want a user-specific token. When provided, the authorization process will associate the resulting code with the specified user. If omitted, the authorization is not tied to a specific user and will result in a generic token (suitable for application-level access).
To start the flow, redirect the user’s browser to the authorization endpoint. For example, if your client ID is abc123 and your redirect URI is https://localhost/callback, you would use:
https://api.AIRisk.example.com/api/oauth2?client_id=abc123&redirect_uri=https%3A%2F%2Flocalhost%2Fcallback
If you want a token on behalf of a user (e.g., user ID user_42), include the userid
parameter:
https://api.AIRisk.example.com/api/oauth2?client_id=abc123&redirect_uri=https%3A%2F%2Flocalhost%2Fcallback&userid=user_42
When the user visits this URL, if the client id and user id are valid, the user’s browser will be redirected to:
https://localhost/callback?code=SplxlOBeZQQYbYS6WxSbIA
The query parameter code=SplxlOBeZQQYbYS6WxSbIA
(this is a sample code) is the authorization code that your application will exchange for an access token in the next step. The code is typically a short-lived, single-use string. (If the server denied the request or an error occurred, you might instead receive error parameters in this redirect, or may be redirected to a json response with error parameters).
401 - Unauthorized
For example, if passing in an unknown client_id
, the endpoint returns a response like:
With Parameters:
type
: string url - Link to the RFC
title
: string - Human-readable name of the error
status
: int - The Error Code
traceId
: string - The id of the trace with which to use to check the stack trace later on.
Note: It’s recommended to also include a "state" parameter (in our case: code
) in the authorization URL (not shown above) to maintain state between the request and callback (protecting against CSRF attacks). The AIRisk authorization server will return this state value unmodified in the redirect. This is part of OAuth2 best practices, though for brevity the examples here focus on the core parameters.
POST /api/oauth2/Token
)The Token Endpoint is used by your application to exchange the authorization code for an actual access token. This is a server-to-server request (the user does not interact with this endpoint directly). Your client must authenticate itself when calling this endpoint, typically by providing its client secret, to ensure the request is secure.
Endpoint: POST /api/oauth2/Token
Purpose: Exchange an authorization code for an access token.
Request Parameters (POST body):
client_id
(string, Required)
– Your client identifier, as in the authorization step.
client_secret
(string, Required)
– Your client secret, which is a confidential key provided when you registered your application. This secret proves to the authorization server that the request is coming from your application (and not a malicious attacker who intercepted the code).
redirect_uri
(string, Required)
– The same redirect URI that was used in the authorization request. It must exactly match the URI originally provided. This is used as an additional security check: the authorization server will ensure the code was issued for this specific redirect URI.
code
(string, Required)
– The authorization code received from the Authorization Endpoint redirect. This is the value of the code
query parameter that was passed to your redirect URI. The code has a short expiration time and can only be used once.
userid
(string, Optional)
– The user identifier, if one was included in the authorization request. You must include the same userid
here to obtain a user-specific token. If you omit userid
here (and the code was associated with a user), the token request will fail. Conversely, if no userid
was used in the authorization step, you should not include one in this request.
Request Format: The token request is an HTTP POST. You can send the parameters as form URL-encoded (Content-Type application/x-www-form-urlencoded
) or as a JSON body. The examples below demonstrate both approaches using curl and Python.
userid
)Using curl (with form-encoded body):
In this example:
Replace YOUR_client_id
and YOUR_client_secret
with your actual credentials.
redirect_uri
is URL-encoded (https%3A%2F%2Flocalhost%2Fcallback corresponds to https://localhost/callback).
AUTH_CODE_HERE
should be replaced with the code you received in the previous step (e.g., SplxlOBeZQQYbYS6WxSbIA).
Alternatively, using Python and the requests
library (sending JSON payload):
Here we post a JSON body with the required fields. The server will respond with a JSON object (as shown below). We then parse the JSON to extract the access_token. In a real application, you would store this token and use it to authorize API calls via the HTTP Header for a bearer token.
Example Success Response (JSON):
access_token
– The OAuth2 access token string. This is typically a long opaque string or JWT that you will use to authenticate requests to the AIRisk API.
expiration
– The UTC-formatted datetime in which the token expires.
userid
)If you included a userid
in the authorization step, use the same userid
when exchanging the code. For example, suppose we indicated userid=user_42
in the authorization URL and got back a code. We would make the token request as follows:
This is identical to the earlier request, except we have appended &userid=user_42
(using the same user ID that was in the auth request). The response format for a user-specific token is the same JSON structure:
In this case, access_token
here is associated with User 42’s account. When using this token to call protected endpoints, the AIRisk API will treat the request as on behalf of that user.
If the token request is invalid or the authorization code has expired/been used, the token endpoint will return an error instead of an access token. Error responses use HTTP status codes (like 400 or 401) and an HTTP reason.
For example, if a Required parameter (ex. client_id
) is missing:
Or if the provided code
is not valid (e.g., already used or expired):
Or if the provided Client ID isn't valid: Full HTTP Response:
Response Content JSON (ex...)
Or if the client_secret is missing
Or if the client_secret is invalid
Each error response with JSON content includes an "status_code" code and a human-readable "reason" (Is only not JSON if entirely not passing in a necessary parameter. Even if invalid, it will return JSON decode-able content). The error responses without JSON content only have their status code number (ex. 404 in
), the status name e.g. "Unauthorized", and the error message e.g "Invalid client_secret".
Always check for an error response and handle it gracefully in your application (e.g., in your app interacting with an AIRisk instance, prompt the user to re-authenticate if the code is no longer valid).
When using the AIRisk API’s OAuth2 flow, you have the flexibility to obtain tokens that are (conceptually) either generic (not tied to any user) or user-specific. The difference comes down to whether you supply the optional userid
parameter in the flow:
Generic Access Tokens (Application-Only, not attached to particular ApplicationUser
although retrieved using credentials from valid APIUser
): If you do not include userid
in the authorization and token requests, the resulting access_token represents your application itself, not any particular user. These tokens are useful for accessing endpoints or performing actions that are not user-specific.
For example, accessing public data or using client-wide privileges. The token is still scoped to what your client application is allowed to do, but no specific user's data is directly implicated. In practical terms, when your app uses this token, the AIRisk API will see the request as coming from your application in a general context, only identifying the client by client_id
which is tied to an APIUser
in which may be used via arbitrary ApplicationUser
instances.
In our case, one may access /api/Users/ListUsers
if using a generic token as the bearer token in the HTTP headers. In this case, one may fetch the list of known user ids and then select one with which to further log in as.
User-Specific Access Tokens (On-Behalf-of User): If you do include a userid
in the requests to /api/oauth2
and /api/api/oauth2/Token
, the flow will produce a token associated with that user. This typically means the user has explicitly authorized your app to act on their behalf. The token carries the identity or context of the specified user. Use these tokens to access or modify data that the user has access to in the AIRisk API.
A generic token might grant only limited, generic scope access, whereas a user token can grant permissions to read or write to database tables which they can access.
You cannot use a generic token to access user-specific endpoints that require a user context. Similarly, a user-specific token only grants access to the scope of their existing access; you would need separate tokens for different users.
However, you may use an a user-specific access token to access any endpoints accessible via just a generic token.
The userid
parameter should be treated carefully. The user must correspond to an actual ApplicationUser
in the AIRisk system, and the authorization server will not ensure that the person approving the request is that user, and therefore provides a means of impersonating other users. (In many OAuth systems, you don't manually specify the user – the user logs in themselves. AIRisk’s userid
parameter might be used in scenarios where the user identity is known ahead of time or to streamline first-party integrations. Always follow AIRisk’s guidelines on how to obtain or use this parameter.)
In summary, use a generic token when your app needs to perform application-level actions or maintenance tasks that aren't tied to a single user (such as listing available users). Use a user-specific token when your app is performing actions on behalf of a specific user, such as accessing that user's data or acting in their name within the AIRisk platform.
Two-Step Authentication Process
Description: You have an app using the remote AIRisk instance in which only admins / trusted persons use.
Use Case / Needs:
See Available Users
Select One & Authenticate as them
i.e. Impersonation
Access endpoints and/or switch user (authenticating) as needed
Methodology
First, use CLIENT_ID
& CLIENT_SECRET
from the local environment
Invoke the authentication process for a generic token and store that to be used as the bearer token (for now)
Have a local endpoint that calls the remote endpoint /api/ListUsers
, collects the returned JSONdata, and then redirects to a "Select User" page, listing the available users names & ids
If having a USER_ID
in the environment for example, you could have the form default to it
Common practice for this in flask
would be to redirect to an endpoint for select_user which, when called via a GET request renders the form page (with the form action pointing to the same URL), or when called via a POST request collecting the submitted form data from the same page and then redirecting as needed.
When a user is selected, set that as the active user id in the session and invoke the authentication process again but this time also passing userid={SELECTED_USER_ID}
as respective parameter types for the respective Authentication endpoints. Then save the returned access_token
as the active bearer token to use in the headers of future GET requests.
Single-User App
Description: You have an App with a custom interface and which interacts with a remote AIRisk project instance. You will be the only person running this program, and only will do so on your own secure device.
Use Case / Needs
Load APIUser
related CLIENT_ID
and CLIENT_SECRET
from a .env
file
Load ApplicationUser
related id
also from a .env
file in which belongs to your user account
Assuming both of the above exist and are valid.
Methodology
Load from .env
Store the USER_ID
environment variable as userid
in the session / local memory for usage across views/pages.
Invoke the authentication process but include userid
as a parameter for both respective endpoints (encoding it in the URL for the GET request to /api/oauth2
. Passing as a parameter in the POST request to /api/oauth2/Token
)
Use the access token as the bearer token across the app.
Regardless of token type, once you have an access_token, your application will include it in API requests to AIRisk to authenticate. Most commonly, this is done by adding an HTTP header:
Authorization: Bearer <ACCESS_TOKEN>
For example, using a placeholder user token (where /api/GetConversations
is only accessible by users, thus requiring a user token):
or in python:
The AIRisk API will verify the token (and the user context, if any) and then process the request if the token is valid and has the required permissions. If the token is expired or invalid, the API will return an HTTP 401 Unauthorized error (with a status_code
(401) and reason
).
By following the above OAuth2 authorization flow, your application can securely obtain access tokens from AIRisk API. This design ensures that users can grant or revoke access as needed and that your app never needs to handle raw passwords. It also allows AIRisk to scope the issued tokens to specific users or to your application overall, depending on the presence of the userid
parameter.
Furthermore, it allows AIRisk admins to define sets of credentials and allowed redirect uris (corresponding to APIUser
instances), and then share the client id, secret, and the redirect uris as well as set them accordingly. These are all one needs to be able to get a generic token via the authentication process.
Moreover, the admins also have control over the ApplicationUser
instances (each with a unique userid
, corresponding with an actual user of the platform), the agents they can access, particular chat-related settings, as well as their Company
to which they belong to further scope their permissions.
For more information on OAuth2 and best practices, you may refer to external resources like the official OAuth 2.0 framework specification RFC 6749 for in-depth details, or approachable guides such as OAuth 2 Simplified and the DigitalOcean tutorial "An Introduction to OAuth 2" for a conceptual overview. Using this information to properly authenticate and acquire tokens, you may now explore the AIRisk API endpoints with authenticated requests, knowing that the OAuth2 standard is handling the authorization securely under the hood. Happy building!