POST/api/auth/loginPublic

Log in with email and password

Verifies the credentials and starts a PKCE authorization-code grant for client_app_id: on success the authorization code is bound to the code challenge, the redirect_uri, the granted scopes and the nonce, and the auth server's HTTP-only session cookie is set. Accounts with a verified second factor get an mfa_required challenge instead (complete it at POST /api/auth/mfa/verify). Wrong credentials and unknown accounts answer the same 401. Rate limited per IP + e-mail (a sliding window plus a lockout counter of failed attempts).

operationId post_api_auth_loginAuthentication

Authentication & permissionsPublic

Anyone — no credentials required

Accepted credentials
None required
Notes
Credentials travel in the body. An existing auth server session cookie is only used to refuse signing in as a different user.

Request body

Required — The body is parsed by the handler itself so its error format stays stable.

application/json
LoginRequestUnknown keys are rejected.
PropertyTypeDescription
credentials*LoginCredentials
email*string (email)

Account e-mail address; trimmed and lower-cased before lookup

password*string

Account password (must satisfy the password policy)

minLength: 10maxLength: 255

client_app_id*string

Client application the authorization code is issued for

minLength: 2maxLength: 64pattern: ^[a-z0-9_-]*$

code_challenge*string

PKCE S256 code challenge (RFC 7636) the authorization code is bound to

minLength: 43maxLength: 1024

challenge_time*number

Unix epoch milliseconds when the PKCE verifier was created; stale challenges are refused at redemption

minimum: 0

redirect_uristring (uri) | null (uri) | null

OAuth2 redirect_uri bound to the authorization code. Required for third-party client apps and must be registered for the app; omitted (or null) only for the auth server's own /account flow.

noncestring | null | null

OIDC login nonce (OIDC Core §3.1.2.1), echoed in the id_token at redemption. Optional.

minLength: 1maxLength: 512pattern: ^[\x20-\x7E]+$

scopestring

Requested scopes, space delimited (RFC 6749 §3.3). The server re-derives the granted subset; absent, or naming no supported scope, is a plain OAuth 2.1 grant without an id_token.

minLength: 1maxLength: 256pattern: ^[\x21\x23-\x5B\x5D-\x7E]+(?: [\x21\x23-\x5B\x5D-\x7E]+)*$

JSONExample
"credentials"
"email""jane@example.com"
"password""string"
"client_app_id""my-web-app"
"code_challenge""string"
"challenge_time"1.5
"redirect_uri""https://example.com"
"nonce""string"
"scope""openid profile email"

Responses

application/json
AuthenticateSuccessResult

Discriminated on kind: authenticated or mfa_required.

JSONExample
"kind""authenticated"
"success"true
"message""string"
"authorization_code""string"

Example request

bashcurl
curl -X POST 'https://auth.schemavaults.com/api/auth/login' \
  -H 'Content-Type: application/json' \
  -d '{
  "credentials": {
    "email": "jane@example.com",
    "password": "string"
  },
  "client_app_id": "my-web-app",
  "code_challenge": "string",
  "challenge_time": 1.5,
  "redirect_uri": "https://example.com",
  "nonce": "string",
  "scope": "openid profile email"
}'