Update email settings
curl --request PUT \ --url http://localhost:9090/api/v1/admin/settings/email \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "smtpEnabled": true, "smtpHost": "example", "smtpPort": 1, "smtpUsername": "example", "smtpPassword": "example", "clearSmtpPassword": false, "smtpEncryption": "example", "smtpFromName": "example", "smtpFromEmail": "example" }'Update SMTP/email settings. A change needs authserver:manage: these settings decide
where password reset links are sent, so authserver:manage-settings reads them but is
refused a change with 403 MANAGE_SCOPE_REQUIRED. A save with smtpEnabled: false
clears every SMTP field, the stored password included.
The stored SMTP password is kept, replaced or removed:
an absent or empty smtpPassword keeps it, a non-empty one replaces it, and
clearSmtpPassword: true removes it. The two together are refused with 400
VALIDATION_ERROR.
A stored password reaches only the host it was entered for: a save that changes
smtpHost while a password is stored, carrying neither a new smtpPassword nor
clearSmtpPassword: true, is refused with 400 VALIDATION_ERROR and writes nothing.
The hosts are compared with surrounding space trimmed, one pair of brackets taken off
an IPv6 literal, and without regard to case. A change of port, username, encryption or
sender keeps the stored password.
Once every other check has passed, a save with smtpEnabled: true opens a TCP
connection to smtpHost on smtpPort, with a 3-second timeout. It only checks that
something answers there: it does not speak SMTP, negotiate TLS or authenticate, which is what
the send-test operation is for. A connection that fails is a 400; see that response.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
A new SMTP password, at most 256 bytes. The stored password is never returned, only
hasSmtpPassword, so an absent or empty value keeps the stored password; a non-empty
value replaces it. Sending one together with clearSmtpPassword: true is refused with
400 VALIDATION_ERROR and nothing is written.
true removes the stored SMTP password. Removing it when none is stored is an ordinary
save. Refused with 400 VALIDATION_ERROR together with a non-empty smtpPassword.
Ignored when smtpEnabled is false, which clears every SMTP field, the password included.
Responses
Section titled “Responses”Settings updated
object
Example generated
{ "smtpEnabled": true, "smtpHost": "example", "smtpPort": 1, "smtpUsername": "example", "smtpEncryption": "example", "smtpFromName": "example", "smtpFromEmail": "example", "hasSmtpPassword": true}Error_code is INVALID_REQUEST_BODY for a body that will not parse; a refused field answers VALIDATION_ERROR, or its catalog key, such as validator.email.invalid_format, when the refusal is localized; and a connection that fails answers VALIDATION_ERROR. Nothing is written.
A failed connection answers one of these fixed messages, naming at most its coarse cause:
- “Unable to connect to the SMTP server: host name not found.” Check the host name: it is misspelt, or the auth server cannot resolve it, or its resolver did not answer in time. The auth server’s resolver may not be the one your own machine uses.
- “Unable to connect to the SMTP server: connection timed out.” Nothing answered within 3 seconds: check the port, and any firewall between the auth server and the SMTP server.
- “Unable to connect to the SMTP server: connection refused.” The host answered but nothing listens on that port: check the port.
- “Unable to connect to the SMTP server.” Any other failure, such as a network the auth server has no route to.
No address, port or operating-system error is answered; the full error goes to the auth server’s log, at Warn, as “unable to connect to the smtp server” under the request’s request_id.
Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.
object
Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for catalog-keyed localized codes (e.g. validator.email.required).
A sentence for people to read: in the request’s language when error_code is a catalog key, in English otherwise. Route on error_code, not on this text.
Example generated
{ "error_code": "example", "error_description": "example"}Missing or invalid bearer token
Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.
object
Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for catalog-keyed localized codes (e.g. validator.email.required).
A sentence for people to read: in the request’s language when error_code is a catalog key, in English otherwise. Route on error_code, not on this text.
Example generated
{ "error_code": "example", "error_description": "example"}Headers
Section titled “Headers”Bearer challenge on token refusals. An operation may also return a handler-level 401 without this header.
The token is valid but does not authorise this request. Four checks answer here, and a caller distinguishes them by error_code.
INSUFFICIENT_SCOPE comes from the route’s authorisation middleware,
before the handler runs: an Admin operation needs one of the scopes
its route names, and an Account operation needs
authserver:manage-account.
USER_CONTEXT_REQUIRED comes from the same middleware on the Account operations, which also require the token to have been issued for a user: one obtained through the client credentials grant carries no auth_time claim and is refused here.
FORBIDDEN comes from the handler, on the account endpoints that resolve a resource by id and then check it belongs to the caller, so a valid token for the wrong user reaches this rather than a 404.
MANAGE_SCOPE_REQUIRED comes from the handler, on the Admin operations
the administrative policy guards. Only authserver:manage creates an
administrator, changes one, or changes what reaches one, so no
granular scope will ever be enough: the remedy is a token holding
authserver:manage, not requesting the route’s scope as for
INSUFFICIENT_SCOPE. An administrator is a user, group or client
holding any of the six administrative permissions (manage,
admin-read, manage-users, manage-clients, manage-settings,
browser-sessions), a user directly or through any of its groups,
the admin console’s own client whatever it holds, and a client
allowed to request the administrative scopes. A granular scope is
refused here when it:
- grants or revokes an administrative permission, directly or by moving a user into or out of a group that holds one, or deletes such a group;
- writes to an administrator user (profile, credentials, enabled, sessions, consents, attributes, memberships, permissions, deletion), an administrative group (settings, attributes, members, permissions, deletion), or an administrator client (settings, authentication, flows, redirect URIs, web origins, token settings, permissions, logo, deletion);
- switches whether a client may request the administrative scopes, on or off, on any client;
- reads an administrator client’s secret;
- changes the email or the audit-log settings;
- changes an administrative permission’s description.
Granular scopes still read administrators. The refusal is answered
after the request’s 400 and 404, writes nothing, carries
WWW-Authenticate: Bearer realm="goiabada", error="insufficient_scope", error_description="...", scope="authserver:manage", and leaves anadministrator_change_refusedaudit record.
Every operation this document secures declares a 403. The public
client logo endpoint, which carries security: [] and authorises
nothing, is the one that does not.
Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.
object
Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for catalog-keyed localized codes (e.g. validator.email.required).
A sentence for people to read: in the request’s language when error_code is a catalog key, in English otherwise. Route on error_code, not on this text.
Example generated
{ "error_code": "example", "error_description": "example"}Headers
Section titled “Headers”Bearer challenge on scope and administrative-policy refusals; other forbidden responses omit it.
The request failed inside the server, most often a storage error. error_code is INTERNAL_SERVER_ERROR: no detail about the failure, only the request id an operator can find the log line by, and retrying is reasonable. Key rotation’s 500 also answers KEY_SET_INCOMPLETE, which names its cause and no retry clears.
Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.
object
Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for catalog-keyed localized codes (e.g. validator.email.required).
A sentence for people to read: in the request’s language when error_code is a catalog key, in English otherwise. Route on error_code, not on this text.
Example generated
{ "error_code": "example", "error_description": "example"}