openapi: 3.0.3
info:
  title: Number Verification
  description: >
    Service Enabling Network Function API to verify that the provided **mobile
    phone number** is the one used in the device. It verifies that the user is
    using a device with the same *mobile phone number* as it is declared.

    It also makes it possible for a Service provider to verify the number itself
    by returning the phone number associated to the authenticated user's access
    token.


    In this API **phone number** term refers to the mobile phone number


    # API Functionality 

    This enables a Service Provider (SP) to verify the phone number of the
    mobile device being used to access their service where the mobile device is
    accessing the *service provider* over a mobile network (WiFi connections are
    out of this API scope). This can happen either by getting the comparison
    result or receiving the phone number of the device that is used, so they can
    verify it themselves.


    # Resources and Operations overview

    This API currently provides two endpoints where both require a **3-legged
    token** and authentication via **mobile network** (**excluding** for example
    by SMS/OTP or user/password as an authentication method):

    - The first one checks if the user mobile phone number matches the phone
    number associated with the mobile device. It can receive either a hashed or
    a plain text phone number as input and it compares the received input with
    the authenticated user's phone number associated to the access token in
    order to respond **true/false**.

    - The next one retrieves the phone number associated to the user's token and
    returns it so the verification can be made by the service provider.


    # Sequence Diagram

    Number Verification API uses the **standard [OAuth2 Authorization Code
    grant](https://www.rfc-editor.org/rfc/rfc6749#section-4.1)**. The following
    diagram will help to clarify the end-to-end process, including previous
    steps prior to this API call.


    ![UML Sequence
    Diagram](https://github.com/camaraproject/NumberVerification/blob/main/documentation/API_documentation/CAMARA/uml_v0.3.jpg?raw=true)


    **Additional details:**


    - **(1):** Authentication must be automatic without any user interactions.
    Authentication methods such as SMS OTP or user/password are incompatible, as
    the goal is to validate the mobile phone number that is accessing the App.
    So it is required to be authentication via mobile network and without the
    user being involved. the use of parameter prompt=none, as described in
    **[OIDC
    Connect](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest)**,
    ensures no user interaction.


    - **(2):** The way in which the phone_number is retrieved depends on the
    implementation. For example, access token may be a self contained encrypted
    JWT, so API can decrypt and identify phone_number. Some other
    implementations might request the phone_number associated to the token from
    Authserver.
  version: 0.3.1
  termsOfService: http://opgw.u.com.my/terms/
  contact:
    name: API Support
    url: http://opgw.u.com.my/support
    email: awsgsma@u.com.my
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - url: >-
      https://api-sandbox.opgw.u.com.my/number-verification-service/number-verification/v0
    description: Sandbox server (uses test data)
tags:
  - name: Phone number verify
    description: >-
      API operation to verify a phone number received as input. It can be
      received either in plain text or hashed format.
  - name: Phone number share
    description: API operation to return the phone number associated to the access token.
paths:
  /verify:
    post:
      tags:
        - Phone number verify
      summary: >-
        Verifies if the received hashed/plain text phone number matches the
        phone number associated with the access token
      description: >
        Verifies if the specified phone number (plain text or hashed format)
        matches the one that the user is currently using.
         - The number verification will be done for the user that has authenticated via mobile network and so their `sub` is in the access token
         - It returns true/false depending on if the hashed phone number received as input matches the authenticated user's `device phone number` associated to the access token
      operationId: phoneNumberVerify
      parameters:
        - in: header
          name: x-correlator
          required: false
          description: Correlation id for the different services
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NumberVerificationRequestBody'
        required: true
      responses:
        '200':
          description: OK
          headers:
            x-correlator:
              description: Correlation id for the different services
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NumberVerificationMatchResponse'
        '400':
          $ref: '#/components/responses/Generic400'
        '401':
          $ref: '#/components/responses/Generic401'
        '403':
          $ref: '#/components/responses/PhoneNumberVerificationPermissionDenied403'
        '500':
          $ref: '#/components/responses/Generic500'
        '503':
          $ref: '#/components/responses/Generic503'
        '504':
          $ref: '#/components/responses/Generic504'
      security:
        - three_legged:
            - number-verification-verify-read
  /device-phone-number:
    get:
      tags:
        - Phone number share
      summary: Returns the phone number associated with the access token
      description: >
        Returns the phone number so the API clients can verify the number
        themselves:
         - It will be done for the user that has authenticated via mobile network and so their `sub` is in the access token
         - It returns the authenticated user's `device phone number` associated to the access token
      operationId: phoneNumberShare
      parameters:
        - in: header
          name: x-correlator
          required: false
          description: Correlation id for the different services
          schema:
            type: string
      responses:
        '200':
          description: OK
          headers:
            x-correlator:
              description: Correlation id for the different services
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NumberVerificationShareResponse'
        '400':
          $ref: '#/components/responses/Generic400'
        '401':
          $ref: '#/components/responses/Generic401'
        '403':
          $ref: '#/components/responses/PhoneNumberVerificationPermissionDenied403'
        '500':
          $ref: '#/components/responses/Generic500'
        '503':
          $ref: '#/components/responses/Generic503'
        '504':
          $ref: '#/components/responses/Generic504'
      security:
        - three_legged:
            - number-verification-share-read
components:
  securitySchemes:
    three_legged:
      type: openIdConnect
      openIdConnectUrl: https://api-sandbox.opgw.u.com.my/.well-known/openid-
  schemas:
    NumberVerificationRequestBody:
      type: object
      description: Payload to verify the phone number
      oneOf:
        - $ref: '#/components/schemas/PhoneNumber'
        - $ref: '#/components/schemas/HashedPhoneNumber'
    PhoneNumber:
      type: object
      properties:
        phoneNumber:
          description: >-
            A phone number belonging to the user in **E.164 format (starting
            with country code)**. Optionally prefixed with '+'.
          type: string
          example: '+346661113334'
    HashedPhoneNumber:
      type: object
      properties:
        hashedPhoneNumber:
          description: >-
            Hashed phone number. SHA-256 (in hexadecimal representation) of the
            mobile phone number in **E.164 format (starting with country
            code)**. Optionally prefixed with '+'.
          type: string
          example: 32f67ab4e4312618b09cd23ed8ce41b13e095fe52b73b2e8da8ef49830e50dba
    NumberVerificationMatchResponse:
      type: object
      description: Number verification result
      required:
        - devicePhoneNumberVerified
      properties:
        devicePhoneNumberVerified:
          $ref: '#/components/schemas/DevicePhoneNumberVerified'
    NumberVerificationShareResponse:
      type: object
      description: Number verification share result
      required:
        - devicePhoneNumber
      properties:
        devicePhoneNumber:
          $ref: '#/components/schemas/DevicePhoneNumber'
    DevicePhoneNumber:
      description: >-
        The device phone number associated to the access token in **E.164 format
        (starting with country code)**. Optionally prefixed with '+'.
      type: string
      example: '+346661113334'
    DevicePhoneNumberVerified:
      description: Number verification. True, if it matches
      type: boolean
    ErrorInfo:
      type: object
      required:
        - status
        - code
        - message
      properties:
        status:
          type: integer
          description: HTTP response status code
        code:
          type: string
          description: Code given to this error
        message:
          type: string
          description: Detailed error description
  responses:
    Generic400:
      description: Problem with the client request
      headers:
        x-correlator:
          description: Correlation id for the different services
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorInfo'
          example:
            status: 400
            code: INVALID_ARGUMENT
            message: Client specified an invalid argument, request body or query param
    Generic401:
      description: Authentication problem with the client request
      headers:
        x-correlator:
          description: Correlation id for the different services
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorInfo'
          example:
            status: 401
            code: UNAUTHENTICATED
            message: >-
              Request not authenticated due to missing, invalid, or expired
              credentials
    PhoneNumberVerificationPermissionDenied403:
      description: >
        Client does not have sufficient permission.

        In addition to regular scenario of `PERMISSION_DENIED`, other scenarios
        may exist:
          - Client authentication was not via mobile network. In order to check the authentication method, AMR parameter value in the 3-legged user's access token can be used and make sure that the authentication was not either by SMS+OTP nor username/password (`{"code": "NUMBER_VERIFICATION.USER_NOT_AUTHENTICATED_BY_MOBILE_NETWORK","message": "Client must authenticate via the mobile network to use this service"}`)
          - Phone number cannot be deducted from access token context.(`{"code": "NUMBER_VERIFICATION.INVALID_TOKEN_CONTEXT","message": "Phone number cannot be deducted from access token context"}`)
      headers:
        x-correlator:
          description: Correlation id for the different services
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorInfo'
          examples:
            PermissionDenied:
              value:
                status: 403
                code: PERMISSION_DENIED
                message: >-
                  Client does not have sufficient permissions to perform this
                  action
            UserNotAuthenticatedByMobileNetwork:
              value:
                status: 403
                code: NUMBER_VERIFICATION.USER_NOT_AUTHENTICATED_BY_MOBILE_NETWORK
                message: >-
                  Client must authenticate via the mobile network to use this
                  service
            InvalidTokenContext:
              value:
                status: 403
                code: NUMBER_VERIFICATION.INVALID_TOKEN_CONTEXT
                message: Phone number cannot be deducted from access token context
    Generic500:
      description: Server error
      headers:
        x-correlator:
          description: Correlation id for the different services
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorInfo'
          example:
            status: 500
            code: INTERNAL
            message: Server error
    Generic503:
      description: Service unavailable. Typically the server is down.
      headers:
        x-correlator:
          description: Correlation id for the different services
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorInfo'
          example:
            status: 503
            code: UNAVAILABLE
            message: Service unavailable
    Generic504:
      description: >-
        Request time exceeded. If it happens repeatedly, consider reducing the
        request complexity
      headers:
        x-correlator:
          description: Correlation id for the different services
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorInfo'
          example:
            status: 504
            code: TIMEOUT
            message: Request timeout exceeded. Try later.
externalDocs:
  description: Project documentation at CAMARA
  url: https://github.com/camaraproject/NumberVerification
