Skip to content
This page View Markdown Open in ChatGPT Open in Claude

Sign-in providers

Your app signs people in, and sends the token it gets to API Maker with every call. An auth provider checks that token, finds the person in a table of yours, and runs the call with the groups of that person. Make one on Security → Auth Providers.

Provider The app sends Your code reads
Your users table x-am-user-authorization : a token of API Maker, from a username and a password g.req.auth.authAMDB
Google x-google-authorization : the id token of Google g.req.auth.authGoogle
Azure AD (Microsoft Entra ID) x-azure-authorization : the token of Microsoft g.req.auth.authAzure
AWS Cognito x-aws-authorization : the token of the user pool g.req.auth.authAWS
A provider of your own x-custom-authorization : whatever your system issues g.req.auth.authCustom

The call carries the token of the API user in x-am-authorization as well : the application and the person both need a group which grants the API.

Google

The provider
1
2
3
4
5
6
7
8
9
import * as T from 'types';

let googleTokenGenerator: T.IAuthTokenGoogle & { name: string; testObj?: any; } = {
    name: 'google_token_generator',
    clientId: '<OAuth client id>.apps.googleusercontent.com', // the aud of your tokens : a list when several apps sign in
    sourceFieldOfUniqueId: 'sub',        // or 'email'
    groupsDataSource: { instance: 'mongodb', database: 'shop', collection: 'users', targetFieldForUniqueId: 'google_sub', groupsColumn: 'groups', select: { name: 1, email: 1 } },
};
module.exports = googleTokenGenerator;

Google signs the id tokens of every application with the same keys. clientId is the application a token has to be made for (its aud claim) : the OAuth client id of your app, or a list of them. Without clientId, a token Google made for any other site is taken too : that site could call your APIs as each person who signed in there. The API Security Report lists such a provider as takes the Google tokens of any application (high).

Azure AD

The provider
import * as T from 'types';

let azureTokenGenerator: T.IAuthTokenAzureAD & { name: string; testObj?: any; } = {
    name: 'azure_token_generator',
    appId: '<application (client) id>',
    tenant: '<directory (tenant) id>',
    audience: '<application (client) id>',                                   // the aud of your tokens
    issuer: 'https://login.microsoftonline.com/<directory (tenant) id>/v2.0', // the iss of your tokens
    maxRetries: 3,                       // fetching the signing keys
    sourceFieldOfUniqueId: 'oid',        // or 'preferred_username' for the email
    groupsDataSource: { instance: 'mongodb', database: 'shop', collection: 'users', targetFieldForUniqueId: 'azure_oid', groupsColumn: 'groups', select: { name: 1, email: 1 } },
};
module.exports = azureTokenGenerator;

Microsoft signs the tokens of every application with the same keys. The keys prove that Microsoft made a token, not that it was made for your application :

  • audience is the application a token has to be made for (its aud claim) : the application (client) id, or the Application ID URI (api://...) when your tokens carry that.
  • issuer is the directory a token has to come from (its iss claim) : https://login.microsoftonline.com/<directory id>/v2.0 for tokens of version 2, https://sts.windows.net/<directory id>/ for tokens of version 1.
  • Either can be a list : a token which carries one of its entries is taken.
  • Left empty (or an empty list), the claim is not checked. A token Microsoft made for another application is then taken too, and the API Security Report lists the provider as takes the Azure tokens of any application (high).

Paste one of your tokens in jwt.ms to read its aud and iss.

AWS Cognito

The provider
import * as T from 'types';

let awsTokenGenerator: T.IAuthTokenAWS & { name: string; testObj?: any; } = {
    name: 'aws_token_generator',
    cognitoUserPoolId: 'us-east-1_xxxxxx',
    region: 'us-east-1',
    tokenUse: 'access',                 // 'access' | 'id' : which Cognito token the app sends
    tokenExpiration: 3600000,           // milliseconds, at most 3600000
    sourceFieldOfUniqueId: 'sub',       // the claim which identifies the person
    groupsDataSource: { instance: 'mongodb', database: 'shop', collection: 'users', targetFieldForUniqueId: 'cognito_sub', groupsColumn: 'groups', select: { name: 1, email: 1 } },
};
module.exports = awsTokenGenerator;
  • tokenUse is the Cognito token the app sends, access or id. The user pool and the region come from AWS.

The groups of the person

  • sourceFieldOfUniqueId is the claim of the token which identifies the person (an email, sub, oid).
  • groupsDataSource names the table of yours which holds that person : targetFieldForUniqueId is the column with the same value, groupsColumn the comma separated groups of the person, select the columns to put in g.req.auth.
  • Without groupsDataSource, the token is checked but the person gets no group of its own : only the API user decides.

Require it

  • authProviders: ['google_token_generator'] (the name of the provider) in the settings of the APIs, tables or databases, or in common.authProviders of the secret.
  • The call carries the API user token in x-am-authorization, and the token of the provider in its header.
  • testObj in the provider is the person the API testing page pretends to be.

A provider of your own

For any other system, write a Custom provider : a token generator, which answers the token API for it, and a token validator, which says whether a token is valid, in any of the languages. The app sends its token in x-custom-authorization, and your code reads the result in g.req.auth.authCustom. See the example.