openapi: 3.0.3
info:
  title: MFA API
  description: |
    ### Introduction
    The MFA API allows to retrieve and confirm an authentication challenge and is meant to be used by custom 
    MFA connectors. 
    This functionality enables secure verification before proceeding with sensitive operations.
    
    ### Current Implementations inside Plumery Services
    The existing MFA Plugins APIs (e.g. Device signature verification, SK-ID V1/V2) use the following pattern:
    1. An initiation request is made to initiate the signing session.
    2. A verification request is made to verify the signature.
    
    Between step 1 and 2, depending on the use case, there could be a series of steps to be performed (e.g. user input, 
    confirmation message display, asynchronous operations) before proceeding with the signature verification.
    
    Both calls receive a challenge ID as a parameter. The challenge ID is used to correlate the initiation and 
    verification requests.
    
    Using the challenge ID, the MFA Plugins can retrieve the contents of the challenge session and also obtain, 
    based on this information, the confirmation message to be displayed to the user.
    
    ### Implementing a new MFA Connector API
    The custom MFA connector to be implemented does not have access to the challenge ID session details.
    These details can be retrieved using the 'Get Challenge Details' endpoint.
    The response will also contain a confirmation message which can be displayed to the end user when prompted 
    to confirm the signature.
    
    As part of the final step, the MFA connector should call the 'Confirm Challenge' endpoint to confirm the signature.
    
    In the context of the new MFA connector, the challengeId parameter should be used to correlate the initiation 
    and verification requests.
    
    Depending on the use case, a “Sensitive Operation Signed Event” event can be published.
    
    In the following diagram, a custom new MFA Connector API is used to initiate the signing session and to verify the signature
    for a payment initiated request.
    ![Architecture](/MFAConnectorFlow.svg)
  version: '1'
  x-plumery-audit-action-source: https://capabilities.plumery.com/mfa-custom/api
servers:
  - url: 'https://api.plumery.com'
    description: Live Server
tags:
  - name: Challenge
paths:
  '/internal/v1/mfa/challenges/{challengeId}':
    get:
      tags:
        - Challenge
      operationId: Get challenge details
      summary: getChallengeDetails
      x-plumery-audit-action-type: GetChallengeDetails
      x-plumery-audit-action-name: Get Challenge Details
      x-plumery-audit-action-description: Get challenge details for step-up authentication
      x-internal: true
      description: |-
        Get challenge details for step-up authentication.
      parameters:
        - name: challengeId
          in: path
          required: true
          schema:
            type: string
          description: |
            The ID is challenge id received during operation initiation which required challenge.
      responses:
        '200':
          description: Challenge retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RetrieveChallengeResponse'
        '400':
          description: Invalid request provided
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Entity not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  '/internal/v1/mfa/challenges/{challengeId}:confirm':
    post:
      tags:
        - Challenge
      operationId: Confirm challenge
      summary: confirmChallenge
      x-plumery-audit-action-type: ChallengeConfirmed
      x-plumery-audit-action-name: Challenged Confirmed
      x-plumery-audit-action-description: Step up challenge has been confirmed
      x-internal: true
      description: |-
        Confirm challenge for step-up authentication.
      parameters:
        - name: challengeId
          in: path
          required: true
          schema:
            type: string
          description: |
            The ID is challenge id received during operation initiation which required challenge.
      responses:
        '204':
          description: Challenge confirmed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NoContentResponse'
        '400':
          description: Invalid request provided
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error occurred
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: Unexpected error
components:
  schemas:
    RetrieveChallengeResponse:
      type: object
      required: [ challengeId, confirmationMessage, stepUpRequestContext ]
      properties:
        challengeId:
          type: string
          description: The challenge ID used to correlate the initiation and verification requests.
          example: "7c73c21b-e9dc-4037-89d1-5f24556488f7"
        confirmationMessage:
          type: string
          description: Confirmation message to be displayed to the user.
          example: "Please sign the request"
        stepUpRequestContext:
          required: [ action, method, path, userId ]
          type: object
          properties:
            action:
              type: string
              description: The action to be performed as part of the request.
              example: "initiate-payment"
            method:
              type: string
              description: The method used for the request.
              "example": "POST"
            path:
              type: string
              description: The path of the request
              "example": "/api/v1/parties/45a6aa805cef29f58c1382e4669c5884/payments"
            body:
              type: string
              description: The body of the request.
              "example": "{\n\"amount\": 1000\n}\n"
            userId:
              type: string
              description: The id of the user performing the request.
              "example": "7c73c21b-e9dc-4037-89d1-5f24556488f7"
    ErrorCode:
      enum:
        - 'urn:plmr:mfa:api:BAD_REQUEST'
        - 'urn:plmr:mfa:api:RESOURCE_UNKNOWN'
        - 'urn:plmr:mfa:api:UNAUTHORIZED'
        - 'urn:plmr:mfa:api:FORBIDDEN'
        - 'urn:plmr:mfa:api:INTERNAL_SERVER_ERROR'
        - 'urn:plmr:mfa:api:USER_NOT_FOUND'
        - 'urn:plmr:mfa:api:USER_ID_DOES_NOT_MATCH_WITH_CHALLENGE_SUBJECT_USER_ID'
        - 'urn:plmr:mfa:api:STEP_UP_REQUEST_CONTEXT_NOT_FOUND'
        - 'urn:plmr:mfa:api:SIGNING_CONFIRMATION_MESSAGE_TEMPLATE_NOT_FOUND'
        - 'urn:plmr:mfa:api:SIGNING_CONFIRMATION_MESSAGE_TEMPLATE_EVALUATION_FAILED'
      type: string
      example: 'urn:plmr:mfa:api:UNAUTHORIZED'
    FieldErrorCode:
      enum:
        - 'urn:plmr:mfa:api:NOT_BLANK'
        - 'urn:plmr:mfa:api:NOT_NULL'
      type: string
    FieldError:
      type: object
      properties:
        code:
          $ref: '#/components/schemas/FieldErrorCode'
        message:
          type: string
        field:
          type: string
    ErrorResponse:
      type: object
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
        requestId:
          type: string
        fieldErrors:
          type: array
          items:
            $ref: '#/components/schemas/FieldError'
    NoContentResponse:
      type: string
      description: |
        Request was successfully executed, without further response being returned.