- Visibility
- JSON Envelope
- Endpoints
-
Accounts
-
Sessions
-
Passwords
-
OAuth
-
Multi-Factor Authentication (MFA) BETA
-
Other
-
AuthN exposes both public and private endpoints.
Public endpoints are intended to receive traffic directly from a client, although you may certainly route that traffic through a gateway if you prefer. These endpoints rely on trusted Origin headers to prevent CSRF attacks.
Private endpoints are intended to receive only traffic from your application's backend. They require HTTP Basic Auth username and password, and should only be accessed over HTTPS (which you should be using anyway).
Successful actions will be indicated with a HTTP 2xx code, and usually accompanied by a JSON response containing a result
key.
Example:
{
"result": {
"id_token": "..."
}
}
Failed actions will be indicated with a 4xx or 5xx HTTP code, and accompanied by a JSON response containing an errors
key that maps to an array of {field: , message: }
objects.
Example:
{
"errors": [
{"field": "username", "message": "TAKEN"},
{"field": "password", "message": "INSECURE"}
]
}
Errors might also arise when sending unsupported Content-Type
headers, or improperly formatted JSON/Form content. In this
case the error message will result in a slightly different payload, accompanied by 400
or 415
Http errors:
{
"error": "invalid character '}' looking for beginning of value"
}
All PUT / PATCH / POST endpoints support either JSON (application/json
) or Form (application/x-www-form-urlencoded
)
encoded requests, depending on which Content-Type
is found in the request headers. For backwards compatibility,
Authn-Server will try parsing a Form request body when no Content-Type
is set.
Visibility: Public
POST /accounts
Params | Type | Notes |
---|---|---|
username |
string | Must be present and unique. |
password |
string | Must meet minimum complexity scoring per zxcvbn. |
201 Created
{
"result": {
"id_token": "..."
}
}
422 Unprocessable Entity
{
"errors": [
{"field": "username", "message": "MISSING"},
{"field": "username", "message": "FORMAT_INVALID"},
{"field": "username", "message": "TAKEN"},
{"field": "password", "message": "MISSING"},
{"field": "password", "message": "INSECURE"}
]
}
The reason for FORMAT_INVALID
will depend on whether you've configured AuthN to validate usernames
as email addresses.
Visibility: Private
GET /accounts/:id
Params | Type | Notes |
---|---|---|
id |
integer | available from the JWT sub claim |
200 Ok
{
"result": {
"id": <id>,
"username": "...",
"oauth_accounts": [
{
"provider": "google"|"apple",
"provider_account_id": "91293",
"email": "[email protected]"
}
],
"last_login_at": "2006-01-02T15:04:05Z07:00",
"password_changed_at": "2006-01-02T15:04:05Z07:00",
"locked": false,
"deleted": false
}
}
404 Not Found
{
"errors": [
{"field": "account", "message": "NOT_FOUND"}
]
}
Visibility: Private
PATCH|PUT /accounts/:id
Params | Type | Notes |
---|---|---|
id |
integer | available from the JWT sub claim |
username |
string |
200 Ok
404 Not Found
{
"errors": [
{"field": "account", "message": "NOT_FOUND"}
]
}
422 Unprocessable Entity
{
"errors": [
{"field": "username", "message": "FORMAT_INVALID"}
]
}
The reason for FORMAT_INVALID
will depend on whether you've configured AuthN to validate usernames
as email addresses.
Visibility: Public
GET /accounts/available
Params | Type | Notes |
---|---|---|
username |
string |
200 Ok
{
"result": true
}
422 Unprocessable Entity
{
"errors": [
{"field": "username", "message": "TAKEN"}
]
}
Visibility: Private
PATCH|PUT /accounts/:id/lock
Params | Type | Notes |
---|---|---|
id |
integer | available from the JWT sub claim |
200 Ok
404 Not Found
{
"errors": [
{"field": "account", "message": "NOT_FOUND"}
]
}
Visibility: Private
PATCH|PUT /accounts/:id/unlock
Params | Type | Notes |
---|---|---|
id |
integer | available from the JWT sub claim |
200 Ok
404 Not Found
{
"errors": [
{"field": "account", "message": "NOT_FOUND"}
]
}
Visibility: Private
DELETE /accounts/:id
Params | Type | Notes |
---|---|---|
id |
integer | available from the JWT sub claim |
200 Ok
404 Not Found
{
"errors": [
{"field": "account", "message": "NOT_FOUND"}
]
}
Visibility: Private
DELETE /accounts/:id/oauth/:name
Params | Type | Notes |
---|---|---|
id |
integer | User account Id |
name |
string | Provider names |
200 Ok
{}
404 Not Found
Visibility: Private
POST /accounts/import
Params | Type | Notes |
---|---|---|
username |
string | Must exist and be unique, but otherwise not validated. |
password |
string | May be either an existing BCrypt hash or a plaintext (raw) string. Will not be validated for complexity. |
locked |
boolean | Optional. Will import the account as locked. |
201 Created
{
"result": {
"id": 123456789
}
}
422 Unprocessable Entity
{
"errors": [
{"field": "username", "message": "MISSING"},
{"field": "password", "message": "MISSING"}
]
}
Visibility: Public
POST /session
Params | Type | Notes |
---|---|---|
username |
string | |
password |
string | |
otp |
string | required if MFA is setup on account |
201 Created
{
"result": {
"id_token": "..."
}
}
422 Unprocessable Entity
{
"errors": [
{"field": "credentials", "message": "FAILED"},
{"field": "credentials", "message": "EXPIRED"},
{"field": "account", "message": "LOCKED"},
{"field": "otp", "message": "MISSING"},
{"field": "otp", "message": "INVALID_OR_EXPIRED"},
]
}
NOTE: no information is given to tell the user whether the username was found or the password was incorrect.
When handling the EXPIRED
error for credentials, instruct the user their password must be reset.
Visibility: Public
GET /session/refresh
As long as a device remains logged in to the AuthN server, it can hit this endpoint to fetch a fresh JWT session. The keratin/authn-js
library can automate this by pre-emptively refreshing tokens when they reach halflife.
This refresh scheme is necessary so that device sessions may be permanently and effectively revoked.
201 Created
{
"result": {
"id_token": "..."
}
}
401 Unauthorized
Visibility: Public
DELETE /session
When a user signs up or logs in, their device establishes a session with the AuthN service, and within that session is a refresh token. This endpoint will revoke the token and discard the session.
200 OK
Visibility: Public
GET /session/token
Params | Type | Notes |
---|---|---|
username |
string |
NOTE: this endpoint only exists when
APP_PASSWORDLESS_TOKEN_URL
is configured. If you see a404 Not Found
, this env variable is missing.
200 Ok
A webhook will be POSTed to your application's passwordless login URL with a request body containing:
Params | Type | Notes |
---|---|---|
account_id |
integer | Provided for your application to easily find the appropriate user. |
token |
JWT | Your application must deliver this to the user, usually by email. This JWT's audience is AuthN, and should be opaque to your application. |
200 Ok
NOTE: success and failure are indistinguishable to the client. Even the webhook is performed in the background, to prevent timing attacks.
Visibility: Public
POST /session/token
Params | Type | Notes |
---|---|---|
token |
JWT | As generated by Request Passwordless Login. |
201 Created
{
"result": {
"id_token": "..."
}
}
422 Unprocessable Entity
{
"errors": [
{"field": "token", "message": "INVALID_OR_EXPIRED"},
{"field": "account", "message": "NOT_FOUND"},
{"field": "account", "message": "LOCKED"},
{"field": "otp", "message": "MISSING"},
{"field": "otp", "message": "INVALID_OR_EXPIRED"},
]
}
NOTE:
NOT_FOUND
may happen if the account is archived after sending a passwordless login token.
Visibility: Public
GET /password/reset
Params | Type | Notes |
---|---|---|
username |
string |
NOTE: this endpoint only exists when
APP_PASSWORD_RESET_URL
is configured. If you see a404 Not Found
, this env variable is missing.
200 Ok
A webhook will be POSTed to your application's password reset URL with a request body containing:
Params | Type | Notes |
---|---|---|
account_id |
integer | Provided for your application to easily find the appropriate user. |
token |
JWT | Your application must deliver this to the user, usually by email. This JWT's audience is AuthN, and should be opaque to your application. |
200 Ok
NOTE: success and failure are indistinguishable to the client. Even the webhook is performed in the background, to prevent timing attacks.
Visibility: Public
POST /password
Handles password resets (with token) and password changes (with session).
When PASSWORD_CHANGE_LOGOUT
is enabled, all existing sessions for the account will be expired before creating a new session on the current device.
Params | Type | Notes |
---|---|---|
password |
string | Must meet minimum complexity scoring per zxcvbn. |
token |
JWT | As generated by Request Password Reset. This is optional if the user is currently logged in to AuthN. |
currentPassword |
string | Must exist when changing a password while logged in (not using token) |
otp |
string | required if MFA is setup on account |
NOTE:
password
must always be accompanied by eithertoken
orcurrentPassword
.
201 Created
{
"result": {
"id_token": "..."
}
}
422 Unprocessable Entity
{
"errors": [
{"field", "credentials", "message": "FAILED"},
{"field": "token", "message": "INVALID_OR_EXPIRED"},
{"field": "account", "message": "NOT_FOUND"},
{"field": "account", "message": "LOCKED"},
{"field": "password", "message": "MISSING"},
{"field": "password", "message": "INSECURE"}
]
}
NOTE:
NOT_FOUND
may happen if the account is archived after sending a reset token.
Visibility: Private
PATCH|PUT /accounts/:id/expire_password
Params | Type | Notes |
---|---|---|
id |
integer | available from the JWT sub claim |
Revokes all of the user's current sessions, removes their TOTP secret and flags the account for a required password change on their next login. This will manifest as an expired credentials error on what would normally have been a successful login.
200 Ok
404 Not Found
{
"errors": [
{"field": "account", "message": "NOT_FOUND"}
]
}
Visibility: Public
POST /password/score
Params | Type | Notes |
---|---|---|
password |
string | password to be checked for zxcvbn score |
Returns the zxcvbn score and required score set for PASSWORD_POLICY_SCORE
for a given password
200 Ok
{
"result": {
"score": 3,
"requiredScore": 2
}
}
422 Unprocessable Entity
{
"errors": [
{"field": "password", "message": "MISSING"}
]
}
OAuth endpoints are enabled for a supported provider when that provider's credentials are configured.
Visibility: Public
GET /oauth/:providerName
Params | Type | Notes |
---|---|---|
providerName |
string | |
redirect_uri |
URL | Return URL after OAuth. Must be in your application's domain. |
Redirect a user to this URL when you want to authenticate them with OAuth, and include a redirect_uri
where you want them to return when they're done. From here, a user will proceed to the OAuth provider and back to AuthN's OAuth Return endpoint (as configured with the provider).
303 See Other
Location: (OAuth provider)
303 See Other
Location: (redirect URI)
Visibility: Public
GET /oauth/:providerName/return
Params | Type | Notes |
---|---|---|
providerName |
string |
- github
- facebook |
This is the return URL that must be registered with a provider when provisioning credentials. From here, a user will proceed to the redirect_uri
specified at the Begin OAuth step.
If the OAuth process failed, the redirect will have status=failed
appended to the URL.
303 See Other
Location: (redirect URI)
303 See Other
Location: (redirect URI with status=failed)
Visibility: Public
GET /oauth/accounts
Returns relevant oauth information for the current session.
200 Ok
{
"result": [
{
"provider": "google"|"apple",
"provider_account_id": "91293",
"email": "[email protected]"
}
]
}
401 Unauthorized
Visibility: Public
DELETE /oauth/:providerName
Params | Type | Notes |
---|---|---|
providerName |
string |
Delete an OAuth account from the current session. If the session was initiated via the OAuth flow, the endpoint will returns an error requesting user to reset password.
200 Ok
{}
401 Unauthorized
NOTE - AuthN MFA support is currently considered in beta. The API will not be considered stable until v2.
Visibility: Public
POST /totp/new
200 Ok
{
"result": {
"secret": "XXXXXXXXXXXXX",
"url": "otpauth://xxxxxxxxxxxxxxxxxxxx",
}
}
401 Unauthorized
422 Unprocessable Entity
Visibility: Public
POST /totp/confirm
Params | Type | Notes |
---|---|---|
otp |
string | Required. |
200 Ok
401 Unauthorized
422 Unprocessable Entity
Visibility: Public
DELETE /totp
200 Ok
401 Unauthorized
422 Unprocessable Entity
Visibility: Public
GET /configuration
AuthN is not a fully compliant OpenID Connect service, and therefore does not use the /.well-known/
directory or publish all OpenID Connect-required fields.
This endpoint is primarily used by backend client libraries to fetch the jwks_uri
path.
Params | Type | Notes |
---|---|---|
issuer |
string | Base URL of AuthN service, as configured. |
response_types_supported |
array[string] | Always ["id_token"] . |
subject_types_supported |
array[string] | Always ["public"] . |
id_token_signing_alg_values_supported |
array[string] | Always ["RS256"] . |
claims_supported |
array[string] | Always ["iss", "sub", "aud", "exp", "iat", "auth_time"] |
jwks_uri |
string | URL for public key necessary to validate JWTs |
Visibility: Public
GET /jwks
This endpoint is primarily used by backend client libraries to fetch the public key necessary to validate the JWTs this AuthN service issues.
Params | Type | Notes |
---|---|---|
keys.use |
string | Always "sig" . |
keys.alg |
string | Always ["RS256"] . |
keys.kty |
string | |
keys.kid |
string | |
keys.e |
string | |
keys.n |
string |
Visibility: Private
GET /stats
Returns estimated statistics for active users over the last trailing 365 days, 104 weeks, and 60 months. Trims off trailing zero entries in each data set, on the assumption that those days predate your application's launch.
Time periods are labeled in ISO8601 formats:
Period | Format | Example |
---|---|---|
day | YYYY-MM-DD |
2016-01-15 |
week | YYYY-\WWW |
2016-W02 |
month | YYYY-MM |
2016-01 |
200 Ok
{
"actives": {
"daily": {},
"weekly": {},
"monthly": {}
}
}
Visibility: Private
GET /metrics
Returns server stats (memory usage) and traffic stats (counts, timings) that may be used to monitor and alert on server health. The data is formatted for consumption by Prometheus-compatible collectors.
200 Ok
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 10
[...]
# HELP http_requests_total How many HTTP requests processed, partitioned by name and status code
# TYPE http_requests_total counter
http_requests_total{code="200",name="GET /health"} 97
Visibility: Public
GET /health
Returns a JSON hash with key health indicators. This is the intended endpoint for determining if the system is up.
200 Ok
{
"http": true,
"db": true,
"redis": false
}