OAuth2 Authentication
Intro
OAuth2 is a authentication method allowing users to access a website without setting up credentials with that website. In lieu of credentials, trust between the website and the user are established via some third-party identity provider, such as Microsoft. Okta, Google, Amazon, Facebook, GitHub, etc.. Trust is established in the form of token exchanges, which happen transparently to the user.
That trust can be also expanded to the Profound API server via OAuth2. A Profound API server can be setup to authenticate a user's OAuth2 token, and only respond to API requests when a valid token is present. This capability allows services already using OAuth2 to take advantage of Profound API without needing to invent another trust mechanism between that service and the Profound API server.
OAuth2 for Profound API is available beginning in version 7.0.0 of Profound.js.
Why Use OAuth2?
OAuth2 can improve the user experience by allowing them to access participating websites by simply clicking a few sign-on buttons rather than needing to create new accounts or remember various credentials. Security is improved as well, because authentication goes through providers using best practices; whereas, someone operating a small website might not have the resources to handle security appropriately.
Setup
To setup a Profound API server to allow OAuth2 as an authentication method, an OpenAPI configuration must be setup for the server including:
security schemes - the distinct resources needed for handling OAuth2 with various providers must be defined.
security rules - the "security" object defines which security schemes are permitted or required for authorizing API requests.
These rules will be added to an openapi.json file, which is created when a developer configures Open API via the Profound.js IDE. To configure Open API if you do not already have an openapi.json file, then see: OpenAPI Configuration
Note: it is not necessary to setup an OAuth2 app with a provider to get the Profound API server to simply validate user tokens. Further, it is not necessary to share the client_id or client_secret of an OAuth2 app with the Profound API server when only user token validation for API routes is desired.
Security Schemes in openapi.json for OAuth2
Enter OAuth2 security schemes inside the components.securitySchemes object. There can be multiple OAuth2 schemes defined, one for each OAuth2 provider with whom the Profound API server will communicate.
An OAuth2 security scheme object should have a “type” property with value “oauth2”.
For Profound API to validate a user, there should be two fields inside of a “flows” object in the security scheme object:
x-userinfoUrl – a URL pointing to some server that accepts an HTTP GET request and returns a JSON object.
x-userinfoField – a string that names a property in the returned JSON object whose value contains the user-id expected in the PAPI security store; e.g. “email”, “userPrincipalName”, “login”, etc.
Optional Field:
x-cacheTokenTTL – a number specifying how long in seconds to cache a user’s validated ID string before re-validating their username with the OAuth2 provider.
A value of 0 means that each API request will cause a request to be made to the OAuth2 provider to validate the user.
Default: 300 (5 minutes).
Set this to a reasonable value for your organization, where too low can slow down API responses and result in unnecessary network traffic, but too high can result in users remaining validated too long after their session or token has ended or expired.
Example excerpts
Examples showing minimum properties needed for validating PAPI requests via OAuth2 are below. If you need to setup Profound.js as an authentication server to let users sign on, then see the section, “Sample Workspace for OAuth2 Sign-On”.
Microsoft Entra (Azure Active Directory)
"OAuth2_MS_Entra_Identity": {
"type": "oauth2",
"description": "Microsoft Azure Active Directory (Entra)",
"flows": {
"authorizationCode": {
"x-userinfoUrl": "https://graph.microsoft.com/v1.0/me",
"x-userinfoField": "userPrincipalName",
"x-cacheTokenTTL": 120
}
}
},
"OAuth2_Google": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"x-userinfoUrl": "https://www.googleapis.com/oauth2/v3/userinfo",
"x-userinfoField": "email"
}
}
},
GitHub
"OAuth2_GitHub": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"x-userinfoUrl": "https://api.github.com/user",
"x-userinfoField": "login"
}
}
},
Note: the URLs above are valid for User-Validation APIs as of August 30, 2023.
Security Rules
The “security” object inside of the openapi.json file determines which security schemes are used for requests, and whether one or all must be valid before a request is authorized. (See OpenAPI Configuration under “Multiple Security Schemes” for more information.)
Example excerpt where requests matching EITHER “OAuth2_MS_Entra_Identity” OR “ApiKeyAuth” are permitted.
Example excerpt where requests must match BOTH OAuth2_MS_Entra_Identity and ApiKeyAuth , or else the API returns a Not validated response:
Complete Example openapi.json
Note: the x-allowAnonymous
property must be false
in order for API security to function properly.
Conventions
By default, Profound API expects certain conventions with OAuth2:
OAuth2 Bearer tokens are sent in HTTP request headers to the Profound API route.
The OAuth2 identity provider has an user validation API that accepts GET requests and Bearer tokens in HTTP Authorization headers.
The identity provider’s user validation API returns JSON responses.
In the JSON response, the user-ID can be found as a property in the top-most object, not in any deeper objects; e.g.
Expired authentication tokens are not automatically renewed via refresh tokens
If a token is expired, then the user will not be verified, and the Profound API route will respond with not-authorized.
The API caller must track whether tokens are expired and whether to renew them and how.