SDK authentication

The auth clients handle the account requests an application needs before it can exchange messages: enrollment, login, password recovery, public-key updates, and logout. They keep HTTP serialization and credential handling behind a small interface while leaving the application responsible for its user interface and session storage. Server behavior is documented in Authentication and Account.

Names follow the language: reset_password, resetPassword, or ResetPassword. Erlang takes the transport first. C takes a mesgd_auth * first and a cJSON **out last.

OperationArguments after the clientmesgd
signupuser, email, password, public_keysPOST /auth/signup
confirmuser, enrollment_token, otpPOST /auth/signup/confirm
loginuser, password, otpPOST /auth/login
reset passworduser, recovery_code, new_password, otpPOST /auth/password/reset
keysaccess_tokenGET /auth/keys
set keysaccess_token, current password, fresh otp, public_keysPUT /auth/keys
logoutaccess_tokenPOST /auth/logout

POST /auth/refresh is separate from this table. Send the live bearer and an empty body. mesgd retires that bearer and returns the next one for the same session. The auth modules do not wrap that call.

Swift names the GET operation publicKeys. Java and C# require an explicit public-key array on signup. Several other languages default that array to empty.

You get back the mesgd JSON: enrollment URI and PNG, recovery codes, session expiry, and public JWKs. Erlang returns {ok, Object} or {error, {http, Status}}. Go and Rust use their usual result types. C returns the HTTP status (negative for a local error), gives you a successful cJSON *, and sets *out to null on error. The other structured clients raise an error that carries the HTTP status. Branch on 400, 401, 409, 429, and 503. Error text omits response bodies and credentials.

Avoid automatically retrying requests that consume an authenticator code. If the first request succeeded but its response was lost, repeating it with the same code will fail. Obtain a fresh code before another attempt, including when the next request is a different operation.

Send OTP values as six ASCII digits, such as "012345". The clients check this before sending. Turning the code into a number drops a leading zero. No SDK module generates or stores an authenticator secret. Your application shows the QR code, stores recovery codes, and keeps the session.

Signup, login, and reset send no bearer header. Keys, key updates, and logout send the token you pass. The clients do not keep a password, authenticator code, seed, recovery code, or session in a key file or a singleton. After a reset, drop tokens you still hold. mesgd has revoked them.

Send access_token as Authorization: Bearer TOKEN for HTTP calls. A browser WebSocket can supply ['json', token] as its subprotocol list. A login session establishes identity without restricting delivery to assigned patterns; use an issued grant token for that restriction. See WebSocket and Routing.

Python

from auth import AuthClient, https_transport

client = AuthClient(https_transport("https://mesgd.example.com"))
enrollment = client.signup("alice", "alice@example.com", password)
session = client.confirm("alice", enrollment["enrollment_token"], "012345")
recovery_codes = session["recovery_codes"]
token = session["access_token"]
client.logout(token)

session = client.login("alice", password, otp_from_authenticator)
reset = client.reset_password("alice", recovery_code, new_password, fresh_otp)

https_transport(..., context=ssl.create_default_context(cafile="ca.pem")) trusts a private CA and still checks the certificate and hostname.

Show enrollment["qr_png_base64"] or enrollment["otpauth_uri"]. The manual key is enrollment["secret"]. Show recovery_codes once.

JavaScript

import {AuthClient, httpsTransport, AuthError} from './auth.mjs';

const client = new AuthClient(httpsTransport('https://mesgd.example.com'));
const session = await client.login('alice', password, '012345');
const publicKeys = await client.keys(session.access_token);
await client.logout(session.access_token);

The auth module works with browser fetch independently of the Node PKI module. Serve a browser application from the mesgd origin, or provide the required cross-origin handling in the deployment. A 401 AuthError means the login credentials were rejected.

Publish keys

Pass only the two public JWKs:

pub = PKI.pub_jwk()
client.set_keys(token, password, fresh_otp,
                [pub["signing_pub"], pub["encrypting_pub"]])

JavaScript uses Object.values(await PKI.pubJwk()). Go's identity.PubJWK() returns a map; use its signing_pub and encrypting_pub entries. An empty array clears linked keys. The clients reject private JWK fields. Never send the key file or a private JWK.

Bring your own HTTP

Every structured client accepts a transport:

transport(method, fixed_path, decoded_json_body_or_null, bearer_or_null)
    -> (HTTP status, decoded JSON object)

The transport serializes JSON, sets Content-Type and Content-Length, attaches Authorization only when given a token, checks the certificate and hostname, rejects redirects, and uses a finite timeout. The built-in transports do this.

Erlang: T = mesgd_auth_client:https("https://mesgd.example.com"), then mesgd_auth_client:login(T, <<"alice">>, Password, <<"012345">>). https/2 accepts DER CA certificates for a private CA.

Go: pki.HTTPSAuthTransport(origin) and pki.AuthClient{Transport: T}.

Ruby: Mesgd::AuthClient.new(Mesgd::AuthClient.https_transport(origin, ca_file: path)).

PHP: new MesgdAuthClient(MesgdAuthClient::httpsTransport(origin)).

C: fill mesgd_auth_curl_config with the origin and CA, then set the client transport to mesgd_auth_curl_transport. Call curl_global_init before concurrent use.

Lua must encode public_keys as a JSON array, including the empty table. Forth accepts pre-encoded JSON and documents its stack words in forth/auth.f.

Which languages include HTTPS is in Languages.