openapi: 3.1.0
info:
  title: MemoID OAuth 2.0 / OpenID Connect API
  version: "1.0.0"
  description: |
    Public integration reference for MemoID. Use OpenID Connect discovery as the
    authoritative source for currently supported endpoints and capabilities.
    MemoID authenticates the user and determines whether the MemoID account may
    enter a registered application. Application roles and business permissions
    remain the application's responsibility.
servers:
  - url: https://id.memolab.me
    description: Production
paths:
  /.well-known/openid-configuration:
    get:
      summary: OpenID Connect discovery metadata
      operationId: getOpenIdConfiguration
      responses:
        "200":
          description: OpenID Provider metadata
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /.well-known/jwks.json:
    get:
      summary: Public signing keys
      operationId: getJwks
      responses:
        "200":
          description: JSON Web Key Set
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
  /oauth/authorize:
    get:
      summary: Start an Authorization Code flow
      description: Browser redirect endpoint. Use state, nonce, and PKCE S256.
      operationId: authorize
      parameters:
        - { name: response_type, in: query, required: true, schema: { type: string, const: code } }
        - { name: client_id, in: query, required: true, schema: { type: string } }
        - { name: redirect_uri, in: query, required: true, schema: { type: string, format: uri } }
        - { name: scope, in: query, required: true, schema: { type: string, example: "openid profile email" } }
        - { name: state, in: query, required: true, schema: { type: string } }
        - { name: nonce, in: query, required: true, schema: { type: string } }
        - { name: code_challenge, in: query, required: true, schema: { type: string } }
        - { name: code_challenge_method, in: query, required: true, schema: { type: string, const: S256 } }
      responses:
        "302": { description: Browser redirect to sign-in, consent, or registered callback }
  /oauth/token:
    post:
      summary: Exchange an authorization code or refresh token
      operationId: token
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                grant_type: { type: string }
                code: { type: string }
                redirect_uri: { type: string, format: uri }
                client_id: { type: string }
                code_verifier: { type: string }
                refresh_token: { type: string }
              required: [grant_type]
      responses:
        "200":
          description: Token response
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "400": { description: Invalid OAuth request }
  /oauth/userinfo:
    get:
      summary: Read claims for the authenticated user
      operationId: userinfo
      security: [{ bearerAuth: [] }]
      responses:
        "200":
          description: UserInfo claims
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "401": { description: Missing or invalid access token }
  /oauth/revoke:
    post:
      summary: Revoke a token
      operationId: revoke
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                token: { type: string }
                token_type_hint: { type: string, enum: [access_token, refresh_token] }
              required: [token]
      responses:
        "200": { description: Revocation request accepted }
  /oauth/logout:
    get:
      summary: End the MemoID browser SSO session
      operationId: logout
      parameters:
        - { name: id_token_hint, in: query, required: false, schema: { type: string } }
        - { name: post_logout_redirect_uri, in: query, required: false, schema: { type: string, format: uri } }
        - { name: state, in: query, required: false, schema: { type: string } }
      responses:
        "302": { description: Logout flow redirect }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
