Auth of a database user¶
Your users are rows of a table of yours. An auth provider of type DB tells API Maker where : the table, the username column, the password column, the groups column. From then on the token API signs those people in, and every call carries their token in x-am-user-authorization.
| Page | API Security → Auth Providers : one provider per users table. Types : DB, AWS Cognito, Azure AD, Google, Custom. |
| Header | x-am-user-authorization: <token> |
| Get it | POST /api/system-api/<user path>/token with { "name": "<provider>", "u", "p" } |
| Require it | authProviders: ['<provider>'] in the settings of an API, a table, a database, or in common.authProviders of the secret. |
| In code | g.req.auth.authAMDB : the row of the person, without its password. |
1. Declare the provider¶
selectlimits the columns of the person put ing.req.auth.authAMDB;conditionadds a filter to the lookup ({ active: true }).passwordChangedAtColumn: update it whenever a password changes, and every token made before stops working, refresh tokens included. A token made while the column of the person is still empty ends with its first value.- Without that column the token carries a fingerprint of the stored password (
amfp1:…, a keyed hash made with the signing secret of the server), never the password or its hash : a changed password ends the tokens made before, and nothing about the password can be read out of a token.
2. Require it on the APIs¶
Settings of an API, a table or a database
let settings: T.IInstanceApiSettingsTypes = {
apiAccessType: T.EAPIAccessType.TOKEN_ACCESS,
authProviders: ['users_tg'],
};
module.exports = settings;
- Without
authProvidersin any settings, the APIs need whatcommon.authProvidersof the secret names ; nothing there means the API user token alone. - Several DB providers in the list : a token of any of them works. A provider of another type in the list (Google…) adds its own header to what the call must carry.
- A token works only for the provider which made it, in the account which made it. The token of another provider, of another account or of an API user answers
401:Invalid token provided in 'x-am-user-authorization' header., even when that table has a person with the same username and password. - Your other admin user accounts accept the token too when the root setting Allow API Maker User's Token Across Admin Users is on (
Root Settings → Deployment Settings → Security) : the account serving the request needs a provider of the same name, the token must still be valid in the account which made it, and both users tables must keep the same password for that username. The person of the request is the row of the account serving it, with its own groups ; a refresh is asked of the account which made the token. - A call without the token answers
401:Please provide 'x-am-user-authorization' token in request headers.A token whose person is not in the table any more :401,Token user not found in 'mongodb' -> 'shop' -> 'users'.
3. Sign in¶
POST /api/system-api/admin/token
{ "name": "users_tg", "u": "[email protected]", "p": "PASSWORD" }
Answer
{ "success": true, "statusCode": 200, "data": { "token": "eyJ…", "refresh_token": "eyJ…", "expires_in": 259200 } }
- The app sends the token in
x-am-user-authorization, next tox-am-authorizationof the API user. The sample custom API/default/loginof a new account gets both in one call. - The person may call an API when a group of theirs grants it and a group of the API user grants it.
- The token holds the columns of the person the provider reads (a column called
nameincluded, as the person has it), the password fingerprint or the password changed at value, and two fields of its own :__amTokenGenerator, the provider which made it, and__amAdminUserId, the account of that provider. A refresh needs therefresh_tokenof the same provider.
The Fields Generator¶
- The Fields Generator tab of a DB provider is a function which returns extra fields to put in the token, from the row of the person (
g.req.body) : a display name, a department… They come back ing.req.auth.authAMDBon every call without a lookup. - It runs in the sandbox, or on the native process with
runOnNativeProcess: true(a Native chip on the list ; useg.loggerthere, notconsole.log).
Custom providers¶
- A Custom provider is your own logic : a token generator function which answers the token API for
{ "name": "<provider>", … }with whatever it returns, and a token validator function which receivesg.req.body.tokenand returns a truthy value (or an object) when the token is valid. Calls send that token inx-custom-authorizationand your code reads the result ing.req.auth.authCustom. Example.