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

Get token

Gives the two tokens every call may need : the token of an API user (which application calls, sent in x-am-authorization) and the token of a person, a row of your own users table read by a DB token generator (sent in x-am-user-authorization). See the two gates.

Method POST
URL /api/system-api/admin/token : admin is the user path of your account
Body { u, p, expiresInSeconds? }, { name, u, p }, { refresh_token, name? }, or an array of them
Answer data : { token, refresh_token, expires_in }, or an array
From code g.sys.system.getToken

The token of an API user

Body : without name, an API user of API Maker
{ "u": "default", "p": "12345", "expiresInSeconds": 259200 }
Answer
{ "success": true, "statusCode": 200, "data": { "token": "eyJhbGciOi…", "refresh_token": "eyJhbGciOi…", "expires_in": 259200 } }
  • expiresInSeconds is optional : Tokens Expire After of the Deployment Settings otherwise (72 hours by default).
  • The password of an API user lives in the secret, under the path set on the API user (common.apiUserPasswords.default for the API user of a new account).

The token of a person

Body : with the name of a token generator
{ "name": "users_tg", "u": "[email protected]", "p": "PASSWORD" }
  • The generator (an auth provider of type DB) knows the users table and its username and password columns. A hashed password column works : the password given is hashed and compared.
  • The groups of the person come from the groups column of the generator.

Refresh

{ "name": "users_tg", "refresh_token": "eyJhbGciOi…" }
  • refresh_token of an earlier answer gives a new token without the password. For a person, add the name of the generator. A refresh token is valid refreshTokenValidForS seconds (900 by default) after the token expired.

Several tokens in one call

[
    { "u": "default", "p": "12345" },
    { "name": "users_tg", "u": "[email protected]", "p": "PASSWORD" }
]
  • The answer is an array in the same order. The sample custom API /default/login of a new account does exactly this and returns both tokens to the app.

The token of a tenant user

POST /api/system-api/admin/token
x-am-tenant-username: acme

{ "name": "users_tg", "u": "[email protected]", "p": "PASSWORD" }
  • When the generator reads a users table of a multi-tenant instance, name the tenant : the person is read from the database of that tenant, and the token works for that tenant only, also after a refresh.

From code

g.sys.system.getToken makes the same call from your code, whatever the settings of the token API say about HTTP callers.

The token of an API user

  • Token of an API Maker API user: no name.
1
2
3
4
5
const apiUser = await g.sys.system.getToken({
    "u": "USER_NAME",
    "p": "USER_PASSWORD"
});
// apiUser.token goes in x-am-authorization
1
2
3
4
5
api_user = await g.sys.system.get_token(
    'USER_NAME',
    'USER_PASSWORD',
)
# apiUser.token goes in x-am-authorization
1
2
3
4
5
$apiUser = $g->sys->system->getToken(
    'USER_NAME',
    'USER_PASSWORD',
);
// apiUser.token goes in x-am-authorization
var apiUser = await g.Sys.System.GetToken(new GetToken("USER_NAME", "USER_PASSWORD"));
// apiUser.token goes in x-am-authorization
1
2
3
4
5
6
7
8
apiUser, err := g.Sys.System.GetToken(am.GetToken{
    U: "USER_NAME",
    P: "USER_PASSWORD",
})
if err != nil {
    return nil, err
}
// apiUser.token goes in x-am-authorization
let api_user = g.sys.system.get_token(GetToken::new("USER_NAME", "USER_PASSWORD"))?;
// apiUser.token goes in x-am-authorization
var apiUser = g.sys.system.getToken(new GetToken("USER_NAME", "USER_PASSWORD"));
// apiUser.token goes in x-am-authorization
val apiUser = g.sys.system.getToken(GetToken("USER_NAME", "USER_PASSWORD"))
// apiUser.token goes in x-am-authorization

The token of a person

  • Token of a database user (application user): the name of its token generator.
1
2
3
4
5
6
const databaseUser = await g.sys.system.getToken({
    "name": "TOKEN_GENERATOR_NAME",
    "u": "USER_NAME",
    "p": "PASSWORD"
});
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
4
5
6
database_user = await g.sys.system.get_token(
    'USER_NAME',
    'PASSWORD',
    name='TOKEN_GENERATOR_NAME',
)
# databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
4
5
6
$databaseUser = $g->sys->system->getToken(
    'USER_NAME',
    'PASSWORD',
    name: 'TOKEN_GENERATOR_NAME',
);
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
4
5
var databaseUser = await g.Sys.System.GetToken(new GetToken("USER_NAME", "PASSWORD")
{
    Name = "TOKEN_GENERATOR_NAME",
});
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
4
5
6
7
8
9
databaseUser, err := g.Sys.System.GetToken(am.GetToken{
    Name: "TOKEN_GENERATOR_NAME",
    U:    "USER_NAME",
    P:    "PASSWORD",
})
if err != nil {
    return nil, err
}
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
4
5
let database_user = g.sys.system.get_token(
    GetToken::new("USER_NAME", "PASSWORD")
        .name("TOKEN_GENERATOR_NAME"),
)?;
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
var databaseUser = g.sys.system.getToken(new GetToken("USER_NAME", "PASSWORD")
    .name("TOKEN_GENERATOR_NAME"));
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later
1
2
3
4
5
val databaseUser = g.sys.system.getToken(
    GetToken("USER_NAME", "PASSWORD")
        .name("TOKEN_GENERATOR_NAME"),
)
// databaseUser.token goes in x-am-user-authorization, databaseUser.refresh_token gets a new one later

Both in one call

  • Both at once: an array in, an array of tokens out.
1
2
3
4
5
const [apiUser, databaseUser] = await g.sys.system.getToken([
    { "u": "USER_NAME", "p": "USER_PASSWORD" },
    { "name": "TOKEN_GENERATOR_NAME", "u": "USER_NAME", "p": "PASSWORD" }
]);
// apiUser.token goes in x-am-authorization, databaseUser.token in x-am-user-authorization
1
2
3
4
5
api_user, database_user = await g.sys.system.get_tokens([
    GetToken('USER_NAME', 'USER_PASSWORD'),
    GetToken('USER_NAME', 'PASSWORD', name='TOKEN_GENERATOR_NAME'),
])
# api_user.token goes in x-am-authorization, database_user.token in x-am-user-authorization
1
2
3
4
5
[$apiUser, $databaseUser] = $g->sys->system->getTokens([
    new GetToken('USER_NAME', 'USER_PASSWORD'),
    new GetToken('USER_NAME', 'PASSWORD', name: 'TOKEN_GENERATOR_NAME'),
]);
// $apiUser->token goes in x-am-authorization, $databaseUser->token in x-am-user-authorization
1
2
3
4
5
6
var tokens = await g.Sys.System.GetTokens([
    new GetToken("USER_NAME", "USER_PASSWORD"),
    new GetToken("USER_NAME", "PASSWORD") { Name = "TOKEN_GENERATOR_NAME" },
]);
var (apiUser, databaseUser) = (tokens[0], tokens[1]);
// apiUser.Token goes in x-am-authorization, databaseUser.Token in x-am-user-authorization
1
2
3
4
5
6
7
8
9
tokens, err := g.Sys.System.GetTokens([]am.GetToken{
    {U: "USER_NAME", P: "USER_PASSWORD"},
    {Name: "TOKEN_GENERATOR_NAME", U: "USER_NAME", P: "PASSWORD"},
})
if err != nil {
    return nil, err
}
apiUser, databaseUser := tokens[0], tokens[1]
// apiUser.Token goes in x-am-authorization, databaseUser.Token in x-am-user-authorization
1
2
3
4
5
6
let tokens = g.sys.system.get_tokens(vec![
    GetToken::new("USER_NAME", "USER_PASSWORD"),
    GetToken::new("USER_NAME", "PASSWORD").name("TOKEN_GENERATOR_NAME"),
])?;
let (api_user, database_user) = (&tokens[0], &tokens[1]);
// api_user.token goes in x-am-authorization, database_user.token in x-am-user-authorization
1
2
3
4
5
List<TokenResponse> tokens = g.sys.system.getTokens(List.of(
    new GetToken("USER_NAME", "USER_PASSWORD"),
    new GetToken("USER_NAME", "PASSWORD").name("TOKEN_GENERATOR_NAME")));
TokenResponse apiUser = tokens.get(0), databaseUser = tokens.get(1);
// apiUser.getToken() goes in x-am-authorization, databaseUser.getToken() in x-am-user-authorization
1
2
3
4
5
6
7
val (apiUser, databaseUser) = g.sys.system.getTokens(
    listOf(
        GetToken("USER_NAME", "USER_PASSWORD"),
        GetToken("USER_NAME", "PASSWORD").name("TOKEN_GENERATOR_NAME"),
    ),
)
// apiUser.token goes in x-am-authorization, databaseUser.token in x-am-user-authorization

Who may call it

  • The token API is public by default : anybody can ask for a token with a username and a password.
  • When its system API settings list auth providers, it needs the tokens those settings ask for, like any other API.
  • A token is a JWT signed with passJWT of the server. Changing the password of the API user, or passwordChangedAtColumn of a person, invalidates the tokens made before.

Access and settings

  • Over HTTP, a system API answers once its settings give it apiAccessType: TOKEN_ACCESS (the token of an API user whose group grants this system API, in x-am-authorization) or IS_PUBLIC. Without settings it is NO_ACCESS : your code calls it through g.sys, the admin panel tests it, and an HTTP call is refused. The token API itself is public unless its settings say otherwise.
  • The settings can also cache the answer or require person tokens (authProviders) ; pre and post hooks run around it like around any API.
  • The request headers apply : x-am-response-case, x-am-content-type-response, x-am-internationalization, x-am-tenant-username…

Errors

Code When
400 The body is wrong : the message names the missing or invalid key, Please provide token request with ['u', 'p'] or ['refresh_token']. for an incomplete body.
401 No valid API user token, or the API is NO_ACCESS : You are not authorized to access this API.
403 No group grants this system API.