Enrollment and login

Enrollment establishes the password and authenticator a person or program will use to sign in. It is a two-step process: signup creates a pending account and returns authenticator setup information; confirmation proves that the authenticator works and activates the account. The field limits are in Accounts, and session behavior is covered in Security.

Sign up

POST /auth/signup with user, email, and password. You can include public_keys, the public JWKs described in Account API.

mesgd creates the account as pending. 201 returns:

FieldWhat you do with it
userThe username
enrollment_tokenA one-time proof that this signup may be confirmed. It is not a session
expires_in600 seconds. Start over at signup if it expires
secretThe Base32 authenticator key, for the person to type in
otpauth_uriThe URI to scan or enter
qr_png_base64A PNG, when mesgd can encode one

Show the QR code or the manual key only to the person enrolling. A pending account cannot log in. Signup cannot overwrite an account that is already active.

Confirm

POST /auth/signup/confirm with user, enrollment_token, and otp.

A current authenticator code and an unexpired token activate the account. 200 returns access_token, token_type (Bearer), expires_in, expires_at (Unix seconds), and eight recovery_codes. expires_in is the bearer lifetime in seconds. The default is 86400, 24 hours, unless {session_ttl, Seconds} sets another value from 60 to 2592000. Show the recovery codes once. The person stores them somewhere other than the authenticator.

The code used for confirmation cannot be reused for login until the next time step.

mesgd user add does this confirmation itself and writes the recovery codes to a file. mesgd user confirm does the same for a pending enrollment file in the current directory, then deletes that file.

Log in and log out

POST /auth/login with user, password, and otp. Both the password and a fresh code are required. The response is the same session object as confirm, without recovery codes.

POST /auth/logout with Authorization: Bearer TOKEN and an empty body ends that session. An expired, revoked, or altered token is rejected.

POST /auth/refresh with the same bearer, and an empty body, continues that session. mesgd retires the bearer you sent and returns a new one whose lifetime is session_ttl from the moment of the call. The session id does not change. Refresh the bearer before it expires. Once it has expired, or after it has already been refreshed, the call is rejected and the caller logs in again.

Change the password while signed in

POST /auth/password/change with the bearer token and JSON password, new_password, and otp. Success returns password_changed: true and ends existing sessions. The user logs in again.

POST /auth/otp/rotate with the bearer token and JSON password and otp starts a replacement authenticator. The response is a new secret, an otpauth URI, an enrollment token, and expires_in of 600 seconds, plus a QR PNG when encoding works. The old authenticator still works until confirm.

POST /auth/otp/confirm with the bearer token and JSON enrollment_token and otp installs that secret. Success returns otp_rotated: true and eight new recovery codes, and ends existing sessions.

Replace a forgotten password

Use this when the person still has the authenticator and a saved recovery code.

POST /auth/password/reset with user, recovery_code, new_password, and otp. Success returns password_reset: true and eight replacement recovery codes. Old recovery codes and existing sessions are invalidated. mesgd does not return a session. The user logs in with the new password and the next authenticator code.

mesgd user reset USER is the same operation from the node. It reads the newest recovery file and authenticator file, then writes a new password file and a new recovery file.

A lost authenticator is a different problem. Use Recovery.