> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Request an access token

> Issues an OAuth2 access token. No Bearer token is needed; the grant itself is the credential.

Two request formats are accepted, chosen by Content-Type, and each has its own response shape:
- application/json with camelCase members (grantType, clientId, clientSecret, username, password, code, state, codeVerifier) answers with the camelCase token (accessToken, tokenType, expiresIn, ...).
- application/x-www-form-urlencoded with the standard OAuth2 members (grant_type, client_id, client_secret, username, password, code) answers with the standard snake_case token (access_token, token_type, expires_in, ...). Client credentials may instead be sent as HTTP Basic authentication, which then takes precedence over client_id/client_secret in the form.

grantType is one of password, client_credentials or sso_code. password requires username and password; client_credentials requires clientId and clientSecret; sso_code requires code, state and codeVerifier (the PKCE verifier of the code_challenge sent to GET /v1/sso/start), and is a JSON-only grant.

When the person signing in has MFA enabled, a password or sso_code grant does not issue a token: it answers 200 with mfaRequired=true and an mfaToken, which is then sent to POST /v1/login/mfa/verify to obtain the token.

When the person has no MFA factor and the organization requires one, a password or sso_code grant is refused with 401 AUT-0019 carrying an enrollment-only mfaToken and the availableMethods to enroll: the client enrolls through POST /v1/login/mfa/setup and /confirm, which continue the login with the normal challenge.

Errors use the {code, title, message} envelope, plus fields on body validation errors. 400: Content-Type missing or not one of the two formats, malformed form or Basic credentials (AUT-0009), a grant missing the members it needs (AUT-0014), an invalid or expired SSO code (AUT-0027). 401: wrong username or password (AUT-1002), wrong client credentials (AUT-1004), password grant for a person created through SSO with no password (AUT-1006), a person with MFA whose sign-in did not reach the second-factor step (AUT-0015), a person with no MFA factor whose organization requires one (AUT-0019, with mfaToken and availableMethods), suspended or expired partner (AUT-1009, AUT-1010). 403: caller IP outside the IP allowlist (AUT-0021), person not allowed to sign in (AUT-1008), password grant for a person who has a passkey while the organization offers passkey sign-in (AUT-1019; checked only after the password was verified). 429: account temporarily locked after repeated failures (AUT-1007). 503 AUT-0028: the sign-in needs a second factor and this server has no MFA signing secret configured.



## OpenAPI

````yaml /pt/openapi/v3-current/AM-auth.yaml post /v1/login/oauth/access_token
openapi: 3.1.0
info:
  contact:
    name: Lerian Studio
    url: https://lerian.studio
  description: OpenAPI 3.1 surface for the Access Manager auth component.
  license:
    name: Lerian Studio General License
  title: Access Manager Auth API
  version: v1
servers:
  - url: https://auth.sandbox.lerian.net
security: []
tags:
  - description: >-
      OAuth2 token issuance: request an access token, refresh it, and log out.
      Public issuer endpoints.
    name: OAuth
  - description: >-
      Single sign-on through the tenant's identity provider: discover how an
      email signs in, then start the login. Public, called by the browser before
      login.
    name: SSO
  - description: >-
      Multi-factor authentication challenge and verification during the login
      flow. Public (identity is carried by the MFA token, not a Bearer token).
    name: MFA
  - description: >-
      Token-secured routes: enforce a permission, list the caller's permissions,
      and fetch OIDC user info. Require a Bearer token, validated in the use
      case.
    name: User Permission
paths:
  /v1/login/oauth/access_token:
    post:
      tags:
        - OAuth
      summary: Request an access token
      description: >-
        Issues an OAuth2 access token. No Bearer token is needed; the grant
        itself is the credential.


        Two request formats are accepted, chosen by Content-Type, and each has
        its own response shape:

        - application/json with camelCase members (grantType, clientId,
        clientSecret, username, password, code, state, codeVerifier) answers
        with the camelCase token (accessToken, tokenType, expiresIn, ...).

        - application/x-www-form-urlencoded with the standard OAuth2 members
        (grant_type, client_id, client_secret, username, password, code) answers
        with the standard snake_case token (access_token, token_type,
        expires_in, ...). Client credentials may instead be sent as HTTP Basic
        authentication, which then takes precedence over client_id/client_secret
        in the form.


        grantType is one of password, client_credentials or sso_code. password
        requires username and password; client_credentials requires clientId and
        clientSecret; sso_code requires code, state and codeVerifier (the PKCE
        verifier of the code_challenge sent to GET /v1/sso/start), and is a
        JSON-only grant.


        When the person signing in has MFA enabled, a password or sso_code grant
        does not issue a token: it answers 200 with mfaRequired=true and an
        mfaToken, which is then sent to POST /v1/login/mfa/verify to obtain the
        token.


        When the person has no MFA factor and the organization requires one, a
        password or sso_code grant is refused with 401 AUT-0019 carrying an
        enrollment-only mfaToken and the availableMethods to enroll: the client
        enrolls through POST /v1/login/mfa/setup and /confirm, which continue
        the login with the normal challenge.


        Errors use the {code, title, message} envelope, plus fields on body
        validation errors. 400: Content-Type missing or not one of the two
        formats, malformed form or Basic credentials (AUT-0009), a grant missing
        the members it needs (AUT-0014), an invalid or expired SSO code
        (AUT-0027). 401: wrong username or password (AUT-1002), wrong client
        credentials (AUT-1004), password grant for a person created through SSO
        with no password (AUT-1006), a person with MFA whose sign-in did not
        reach the second-factor step (AUT-0015), a person with no MFA factor
        whose organization requires one (AUT-0019, with mfaToken and
        availableMethods), suspended or expired partner (AUT-1009, AUT-1010).
        403: caller IP outside the IP allowlist (AUT-0021), person not allowed
        to sign in (AUT-1008), password grant for a person who has a passkey
        while the organization offers passkey sign-in (AUT-1019; checked only
        after the password was verified). 429: account temporarily locked after
        repeated failures (AUT-1007). 503 AUT-0028: the sign-in needs a second
        factor and this server has no MFA signing secret configured.
      operationId: requestAccessToken
      parameters:
        - description: >-
            Optional HTTP Basic client authentication (Basic
            base64(client_id:client_secret)), read on form requests only. When
            present it takes precedence over client_id/client_secret in the form
            body.
          in: header
          name: Authorization
          schema:
            description: >-
              Optional HTTP Basic client authentication (Basic
              base64(client_id:client_secret)), read on form requests only. When
              present it takes precedence over client_id/client_secret in the
              form body.
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RequestAccessTokenInput'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/AccessTokenForm'
      responses:
        '200':
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/OAuth2Token'
                  - $ref: '#/components/schemas/OAuth2TokenStandardResponse'
                  - $ref: '#/components/schemas/MFAChallengeResponse'
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPError'
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPError'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPError'
          description: Forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPError'
          description: Too Many Requests
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPError'
          description: Internal Server Error
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPError'
          description: Service Unavailable
components:
  schemas:
    RequestAccessTokenInput:
      additionalProperties: false
      properties:
        clientId:
          examples:
            - 00000000-0000-0000-0000-000000000000
          type: string
        clientSecret:
          examples:
            - 00000000-0000-0000-0000-000000000000
          type: string
        code:
          examples:
            - 4%2F0AbCd...idp
          type: string
        codeVerifier:
          examples:
            - dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
          type: string
        grantType:
          enum:
            - password
            - client_credentials
            - sso_code
          examples:
            - password
          type: string
        password:
          examples:
            - password
          type: string
        state:
          examples:
            - kQ7f...opaque
          type: string
        username:
          examples:
            - johndoe
          type: string
      required:
        - grantType
      type: object
    AccessTokenForm:
      additionalProperties: false
      properties:
        client_id:
          description: >-
            Client identifier. Overridden by HTTP Basic credentials when they
            are sent.
          type: string
        client_secret:
          description: >-
            Client secret. Overridden by HTTP Basic credentials when they are
            sent.
          type: string
        code:
          description: SSO code, for the sso_code grant.
          type: string
        grant_type:
          description: >-
            OAuth2 grant type. sso_code is accepted but its state and
            code_verifier cannot be sent in this format; use the JSON format for
            it.
          enum:
            - password
            - client_credentials
            - sso_code
          type: string
        password:
          description: Password, for the password grant.
          type: string
        username:
          description: Username, for the password grant.
          type: string
      required:
        - grant_type
      type: object
    OAuth2Token:
      additionalProperties: false
      properties:
        accessToken:
          description: The issued OAuth2 access token (JWT).
          examples:
            - >-
              eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
          type: string
        expiresIn:
          description: Access token lifetime in seconds.
          examples:
            - 3600
          format: int64
          type: integer
        idToken:
          description: The OIDC ID token (JWT).
          examples:
            - >-
              eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
          type: string
        refreshToken:
          description: The refresh token to obtain a new access token.
          examples:
            - >-
              eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
          type: string
        scope:
          description: Space-delimited scopes granted to the token.
          examples:
            - openid profile email
          type: string
        tokenType:
          description: The token type; always "Bearer".
          examples:
            - Bearer
          type: string
      required:
        - accessToken
        - tokenType
        - expiresIn
        - refreshToken
      type: object
    OAuth2TokenStandardResponse:
      additionalProperties: false
      properties:
        access_token:
          examples:
            - >-
              eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
          type: string
        expires_in:
          examples:
            - 3600
          format: int64
          type: integer
        id_token:
          examples:
            - >-
              eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
          type: string
        refresh_token:
          examples:
            - >-
              eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
          type: string
        scope:
          examples:
            - openid profile email
          type: string
        token_type:
          examples:
            - Bearer
          type: string
      required:
        - access_token
        - token_type
        - expires_in
      type: object
    MFAChallengeResponse:
      additionalProperties: false
      properties:
        availableMethods:
          examples:
            - - app
              - email
          items:
            type: string
          type:
            - array
            - 'null'
        mfaRequired:
          examples:
            - true
          type: boolean
        mfaToken:
          examples:
            - eyJhbGciOiJIUzI1NiJ9...
          type: string
        preferredMethod:
          examples:
            - app
          type: string
      required:
        - mfaRequired
        - mfaToken
        - availableMethods
        - preferredMethod
      type: object
    HTTPError:
      additionalProperties: false
      properties:
        availableMethods:
          description: 'Present on AUT-0019: the factors the person can enroll (app, email).'
          items:
            type: string
          type:
            - array
            - 'null'
        code:
          description: >-
            Stable, machine-readable error code (AUT-NNNN). Branch on this, not
            on the message.
          examples:
            - AUT-0009
          type: string
        fields:
          additionalProperties: {}
          description: >-
            Present on body validation errors: each offending member mapped to
            what is wrong with it (AUT-0001 missing, AUT-0009 invalid) or, for
            AUT-0003, to the unexpected value that was sent.
          type: object
        message:
          description: Human-readable explanation of this occurrence.
          type: string
        mfaToken:
          description: >-
            Present on AUT-0019: the enrollment-only token for POST
            /v1/login/mfa/setup and /confirm.
          type: string
        title:
          description: Short, human-readable summary of the error class.
          examples:
            - Bad Request
          type: string
      type: object

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.