openapi: "3.0.2"
info:
  title: BankID with biometrics Permissions API
  description: The Permissions API
  version: "1.0"
  contact:
    url: https://developer.bankid.no
security:
  - BearerAuth: []

tags:
  - name: permissions
    description: Permission API

servers:
  - url: https://api.app.bankid.no/permissions/v1

paths:
  /:
    post:
      operationId: postPermission
      summary: Create permission request
      tags: [permissions]
      description: |
        Create a new permission request.
        The requesting party is responsible for storing the permission data
      requestBody:
        content:
          application/json:
            schema:
              allOf:
                - type: object
                  required:
                    - type
                    - iat
                    - exp
                    - permission
                  properties:
                    iat:
                      type: integer
                      minimum: 1600000000
                      maximum: 1800000000
                    exp:
                      type: integer
                      minimum: 1600000000
                      maximum: 1800000000
                      description: Permission request valid until, will be deleted after. Max 30 days into future because GDPR
                    securityData:
                      $ref: "#/components/schemas/SecurityData"
                    loginHint:
                      $ref: "#/components/schemas/LoginHint"
                    signals:
                      $ref: "#/components/schemas/Signals"
                    redirect_uri:
                      $ref: "#/components/schemas/RedirectUri"
                    app_callback_uri:
                      $ref: "#/components/schemas/AppCallbackUri"
                    platform:
                      $ref: "#/components/schemas/Platform"
                    type:
                      $ref: "#/components/schemas/PermissionType"
                    acr_values:
                      $ref: "#/components/schemas/AcrValues"
                    permission:
                      $ref: "#/components/schemas/PermissionStatement"
                    intents:
                      $ref: "#/components/schemas/Intents"

      responses:
        "201":
          description: Permission data registered
          content:
            application/json:
              schema:
                type: object
                required:
                  - id
                  - permissionToken
                properties:
                  id:
                    type: string
                    description: |
                      Permission ID and challenge string in urlsafe base64 alphabet to be used for assertion.
                      A the digest of the permission bytearray is embedded in the permission ID.
                    example: 1.Ag._esziS0YZ2JtbSsGtVlmUyAuaj7ZlizE9ULYa6BoN7E.E9ULYa6BoN7E.IC5qPtmWLMT1QthroGg3sQ
                  permissionToken:
                    $ref: "#/components/schemas/PermissionToken"
                  bindingMessage:
                    description: |
                      Binding message used for multi client scenarios like CIBA or 2 channel authentication.
                    type: string
                    example: "Flott App"
                additionalProperties: true

  /{permissionId}:
    get:
      operationId: getPermission
      summary: Get an existing permission request.
      description: Get an existing permission request.
      parameters:
        - $ref: "#/components/parameters/permissionId"
      tags: [permissions]
      responses:
        "200":
          description: Permission data
          content:
            application/json:
              schema:
                type: object
                properties:
                  iat:
                    type: integer
                    minimum: 1600000000
                    maximum: 1800000000
                  exp:
                    type: integer
                    minimum: 1600000000
                    maximum: 1800000000
                    description: Permission request valid until, will be deleted after. Max 30 days into future because GDPR
                  type:
                    $ref: "#/components/schemas/PermissionType"
                  permissionDigest:
                    $ref: "#/components/schemas/PermissionStatementDigest"
                additionalProperties: true

  /{permissionId}/grant:
    parameters:
      - $ref: "#/components/parameters/permissionId"
    get:
      operationId: getPermissionGrant
      description: |
        Get the signed permission. Note that even after a sucessful call has been made to grant a permission, this endpoint
        may return 404 (permission not yet granted) for a short period of time. Callers should retry this call in a polling loop
        with a small delay between each call.
      tags: [permissions]
      responses:
        "200":
          description: "Return the signed permission"
          content:
            application/jose:
              schema:
                $ref: "#/components/schemas/PermissionGrant"
        "404":
          description: Not yet signed.

  /user-exists:
    post:
      operationId: userExists
      description: |
        Check whether a user is registered with a BankID App sufficiently up to date to support authentication flows requiring an app, such as CIBA.
      tags: [permissions]
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                loginHint:
                  $ref: "#/components/schemas/LoginHint"

      responses:
        "200":
          description: User exists
          content:
            application/json:
              schema:
                type: object
                required:
                  - exists
                properties:
                  exists:
                    type: boolean
                    description: |
                      `true` if the user is registered with a BankID App sufficiently up to date to support authentication flows requiring an app, such as CIBA.
                additionalProperties: true

components:
  parameters:
    permissionId:
      in: path
      name: permissionId
      schema:
        type: string
        minLength: 68
        maxLength: 255
      required: true
      description: Unique id of the permission request.
      example: 1.Ag._esziS0YZ2JtbSsGtVlmUyAuaj7Zliz.E9ULYa6BoN7E.IC5qPtmWLMT1QthroGg3sQ

    keyId:
      name: keyId
      in: path
      description: Key id
      required: true
      schema:
        type: string
        example: 47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU

    bindingId:
      name: bindingId
      description: Unique id of a binding between an identity and a keyinstance.
      required: true
      in: path
      schema:
        example: 923e4567-e89b-12d3-a456-426614174123
        type: string

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  responses:
    TooManyRequestsError:
      description: Rate limiting
      headers:
        Retry-After:
          schema:
            type: integer
            minimum: 0
            maximum: 3600

    UnauthorizedError:
      description: API key is missing or invalid (Unauthenticated)
      headers:
        WWW_Authenticate:
          schema:
            type: string

    ForbiddenError:
      description: Unauthorized, need a higher level authentication or assertion of identity

    ServiceUnavailable:
      description: Service unavailable
      headers:
        Retry-After:
          schema:
            type: integer
            minimum: 0
            maximum: 3600

  schemas:
    BasePermission:
      type: object
      required:
        - nonce
      properties:
        nonce:
          $ref: "#/components/schemas/Nonce"

    PermissionType-authentication.v1:
      allOf:
        - $ref: "#/components/schemas/BasePermission"

    PermissionType-webAuthnKeyRegistration.v1:
      description: |
        A permission representing the creation of a WebAuthn key.

        **Note: Exclusively used by specially permitted apps.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - keyId
          properties:
            keyId:
              type: string
              example: 47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU

    PermissionType-verifiedConfirmation.v1:
      description: |
        A permission representing the confirmation of a text message displayed to the user.
        **Note: This permission type shall not be used for payment confirmations, use `PermissionType-payment.v1` instead.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - text
            - lang
          properties:
            text:
              type: string
              description: Text that is displayed to the user.
              example: I confirm the address change as presented to me.
              maxLength: 250
            lang:
              type: string
              example: nb-NO
              description: Language of text as BCP-47 code
              pattern: "^(((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?))$"
              maxLength: 30
              minLength: 1

    PermissionType-payment.v1:
      description: |
        A permission representing the approval of a payment satisfying PSD2 RTS Article 4 Authentication code and Article 5 Dynamic Linking.
        **Instead of charging 0/1 kr to confirm cards and refunding the amount, use `PermissionType-approvecard.v1` for a smoother card approval flow.**
        **For 3-D secure flows, use `PermissionType-cardPayment.v1` instead.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - id
            - payments
          properties:
            id:
              type: string
              description: |
                Payment or basket id used for lookup at ASPSP.
                The user does not approve the id itself or anything implicitly inferred from the id.
              example: 1234-basket-567
            payments:
              type: array
              maxItems: 100
              items:
                $ref: "#/components/schemas/Permission-paymentBase.v1"

    PermissionType-cardPayment.v1:
      description: |
        A permission representing the approval of a card payment satisfying PSD2 RTS Article 4 Authentication code and Article 5 Dynamic Linking. Used in 3-D secure flows.
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - id
            - payments
          properties:
            id:
              type: string
              description: |
                Payment or basket id used for lookup at ASPSP.
                The user does not approve the id itself or anything implicitly inferred from the id.
              example: 1234-basket-567
            payments:
              type: array
              maxItems: 100
              items:
                $ref: "#/components/schemas/Permission-paymentBase.v1"

    PermissionType-legacyPaymentText.v1:
      description: |
        A permission representing the approval of a text string that may also include payment information.
        **Warning: This permission type is deprecated and is discouraged from being used in new integrations.
        Use `PermissionType-payment.v1` as it provides a much better user experience and handling of payment information.**

        **Note: This permission type additionally requires the `permissions/legacy_payment_text` scope to be enabled for your client, and included as a `scope` when retrieving your access token. Get in touch to enable the scope for your client.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - text
            - lang
          properties:
            text:
              type: string
              description: Text that is displayed to the user.
              example: I approve the payment of 100kr to Example Merchant.
              maxLength: 250
            lang:
              type: string
              example: nb-NO
              description: Language of text as as BCP-47 code
              pattern: "^(((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?))$"
              maxLength: 30
              minLength: 1

    Permission-paymentBase.v1:
      description: |
        An payment entry in a payment permission.
      type: object
      required:
        - paymentId
        - amount
        - currency
        - creditorName
      properties:
        paymentId:
          type: string
          description: |
            Payment id used for lookup at ASPSP.
            Payment id is not displayed to the user.
          example: Gm1rYOxUyzBQ03BLgr_EpEXq5HTwm-K-uUMroUNlRpI=
        amount:
          description: |
            The amount given with fractional digits, where fractions must be compliant to the currency definition.
            Up to 14 significant figures. Negative amounts are signed by minus.
            The decimal separator is a dot.

            **Example:**
            Valid representations for EUR with up to two decimals are:

              * 1056
              * 5768.2
              * -1.50
              * 5877.78
          type: string
          pattern: "-?[0-9]{1,14}(\\.[0-9]{1,3})?"
          example: "5877.78"
        currency:
          type: string
          description: |
            ISO 4217 Alpha 3 currency code.
          minLength: 3
          maxLength: 3
          pattern: "[A-Z]{3}"
          example: "NOK"
        creditorName:
          type: string
          description: Human readable payee
          maxLength: 70

    PermissionType-approveCard.v1:
      description: |
        A permission representing the approval of adding a payment card.

        **Note: This permission type additionally requires the `permissions/approve_card` scope to be enabled for your client, and included as a `scope` when retrieving your access token. Get in touch to enable the scope for your client.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - lastCardDigits
            - merchantName
          properties:
            lastCardDigits:
              description: Last 4 digits of a card number to help the user recognize the card
              type: string
              pattern: "[0-9]{4}"
              example: "1234"
            merchantName:
              type: string
              description: The merchant where the card will be approved
              maxLength: 70

    PermissionType-approveAccount.v1:
      description: |
        A permission representing the approval of adding a bank account.

        **Note: This permission type additionally requires the `permissions/approve_account` scope to be enabled for your client, and included as a `scope` when retrieving your access token. Get in touch to enable the scope for your client.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"
        - type: object
          required:
            - accountNumber
            - merchantName
          properties:
            accountNumber:
              description: Account number
              type: string
              pattern: "^[0-9]{11}$"
              example: "12341212345"
            merchantName:
              type: string
              description: The merchant where the account will be added
              maxLength: 70

    PermissionType-customerServiceCall.v1:
      description: |
        A permission representing a Safe Conversation authentication scenario.

        **Note: This permission type additionally requires the `permissions/ciba` scope to be enabled for your client. Get in touch to enable the scope for your client.**
        **Note: Creating a permission with this permission type must be done with the "ciba" intent. See the `intents` property in the `Permission` schema.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"

    PermissionType-customerServiceChat.v1:
      description: |
        A permission representing a customer service chat authentication scenario.

        **Note: This permission type additionally requires the `permissions/ciba` scope to be enabled for your client. Get in touch to enable the scope for your client.**
        **Note: Creating a permission with this permission type must be done with the "ciba" intent. See the `intents` property in the `Permission` schema.**
      allOf:
        - $ref: "#/components/schemas/BasePermission"

    PermissionToken:
      type: string
      minLength: 128
      maxLength: 1024
      description: |
        An access token that must be used in the process of granting this permission.

    PermissionGrant:
      type: object
      properties:
        gv:
          type: integer
          example: 1
          minimum: 0
          maximum: 9999
          description: The grant version
        pt:
          type: string
          description: |
            The type of proof that is submitted to signify 
            that the user has demonstrated their intent to grant the permission.
        type:
          type: string
          description: Type of the permission statement. Must match Permission.type.
        rpId:
          description: The OIDC client id of the Requesting Party
          type: string
          example: bankid-app
        sv:
          description: Version of this system at time of signing.
          type: string
          example: "2020-10-30@deadbeef"
        iat:
          type: integer
          minimum: 1600000000
          maximum: 1800000000
        iss:
          type: string
        nonce:
          type: string
          description: The nonce from the permission statement
        proofKeyId:
          type: string
          description: The keyid of the fido2 assertion
        sub:
          type: string
          description: |
            The primary identifier of the subject that granted the permission.
            The syntax is "identifierType:identifierValue". For
            NNINs, the identifierType is "nnin".
          example: "nnin:010112345"
        permissionId:
          $ref: "#/components/parameters/permissionId"
        digest:
          type: string
          format: bytes
          description: |
            The digest of the permission statement (URL-safe Base64-encoded
            SHA-256 hash of the permission statement bytes)
      additionalProperties: true

    Nonce:
      type: string
      minLength: 16
      maxLength: 64
      example: -MEDBtU6SeGtFsdHHI-rlA

    AuthenticatorAssertion:
      description: This is the result of a client-side Webauthn authenticator assertion
      type: object
      required:
        - credentialId
        - clientDataJson
        - authenticatorData
        - userHandle
        - signature
      properties:
        credentialId:
          type: string
          format: byte
        clientDataJson:
          type: string
          format: byte
          example: eyJjbGllbnQiOiJkYXRhSnNvbiJ9
        authenticatorData:
          type: string
          format: byte
        signature:
          type: string
          format: byte
        userHandle:
          type: string
          format: byte

    Signals:
      type: object
      properties:
        browserAcceptHeader:
          type: string
          description: Browser Accept Headers. 3DS 2.2 page 170
          maxLength: 2048
        browserIP:
          type: string
          description: Browser IP Address. 3DS 2.2 page 171. This will be added in backend and not from client, but kept as reminder for now
          maxLength: 45
        browserJavaEnabled:
          type: boolean
          description: Browser Java Enabled. 3DS 2.2 page 172, navigator.javaEnabled property Unsure about usefulness
        browserJavascriptEnabled:
          type: boolean
          description: Browser JavaScript Enabled. 3DS 2.2 page 172 This is always true as there is no FIDO authentiation without it
        browserLanguage:
          type: string
          description: Browser Language 3DS 2.2 page 172 navigator.language property
          maxLength: 8
          minLength: 1
        browserColorDepth:
          type: string
          description: Browser Screen Color Depth 3DS 2.2 page 173 screen.colorDepth property
          maxLength: 2
          minLength: 1
          enum:
            - "1"
            - "4"
            - "8"
            - "15"
            - "16"
            - "24"
            - "32"
            - "48"
        browserScreenHeight:
          type: string
          description: Browser Screen Height 3DS 2.2 page 173 screen.height property
          maxLength: 6
          minLength: 1
          pattern: '^\d{1:6}$'
        browserScreenWidth:
          type: string
          description: Browser Screen Width 3DS 2.2 page 173 screen.width property
          maxLength: 6
          minLength: 1
          pattern: '^\d{1:6}$'
        browserTZ:
          type: string
          description: Browser Time Zone 3DS 2.2 page 173 timezone offset in minutes
          maxLength: 5
          minLength: 1
        browserTzIana:
          type: string
          description: IANA timezone string if available
          maxLength: 38
          pattern: "^[a-zA-Z_/]+$"
        browserUserAgent:
          type: string
          description: Browser User-Agent
          maxLength: 2048

    Jwk:
      type: object
      description: JSON Web Key ref https://tools.ietf.org/html/rfc7517, https://tools.ietf.org/html/7518
      required:
        - kid
        - kty
      properties:
        kid:
          type: string
          description: Key ID
        kty:
          type: string
          description: Key Type
          enum: [RSA, EC]
        crv:
          type: string
          description: Elliptic Curve type
          enum: [P-256]
        x:
          type: string
          description: Elliptic Curve X Coordinate
        y:
          type: string
          description: Elliptic Curve Y Coordinate
        n:
          type: string
          description: RSA Modulus
        e:
          type: string
          description: RSA Exponent

    FrequencyCode:
      description: |
        The following codes from the "EventFrequency7Code" of ISO 20022 are supported:
        - "Daily"
        - "Weekly"
        - "EveryTwoWeeks"
        - "Monthly"
        - "EveryTwoMonths"
        - "Quarterly"
        - "SemiAnnual"
        - "Annual"
        - "MonthlyVariable"
      type: string
      enum:
        - "Daily"
        - "Weekly"
        - "EveryTwoWeeks"
        - "Monthly"
        - "EveryTwoMonths"
        - "Quarterly"
        - "SemiAnnual"
        - "Annual"
        - "MonthlyVariable"

    SecurityData:
      type: object
      required:
        - type
        - data
      properties:
        type:
          type: string
          maxLength: 256
          description: |
            Type of security data. The contents of the "data" field must adhere to the schema for the
            type given here. The location of the security data schema has yet to be determined.
          example: bankidFraud.v1
        data:
          type: string
          format: byte
          maxLength: 4096
          description: Base64 encoded string (possibly urlsafe) with data adhering to the schema for type.

    LoginHint:
      type: array
      maxItems: 5
      items:
        type: object
        required:
          - scheme
          - value
        properties:
          scheme:
            type: string
            maxLength: 64
            description: Type of login hint, for example nnin
            enum:
              - nnin
            example: nnin
          value:
            type: string
            maxLength: 64
            description: Value of login hint of type

    RedirectUri:
      type: string
      format: uri
      minLength: 13
      maxLength: 256
      example: https://login.bankid.no/idFederationLanding
      description: User will be redirected here afterwards, this value is trusted as it's in the JWT

    AppCallbackUri:
      type: string
      format: uri
      pattern: "^https://.*$"
      minLength: 13
      maxLength: 256
      example: https://merchant.app/app_callback
      description: (Public preview) A universal link that is used to switch back to the merchant app after authentication is finished in the authenticating app on iOS. Required for the app2app flow unless `platform` is set to `android`, in which case it is optional because the authenticating app minimizes back to the merchant app.

    Platform:
      type: string
      enum:
        - android
        - ios
      description: |
        The target platform of the merchant app for the app2app flow.
        When set to `android`, `app_callback_uri` is optional because the
        authenticating app minimizes back to the merchant app after authentication,
        rather than switching back via a universal link.
        When omitted or set to `ios`, `app_callback_uri` is required for the app2app flow.
      example: android

    PermissionType:
      type: string
      enum:
        - webAuthnKeyRegistration.v1
        - authentication.v1
        - payment.v1
        - verifiedConfirmation.v1
        - legacyPaymentText.v1
        - approveCard.v1
        - approveAccount.v1
        - customerServiceCall.v1
        - customerServiceChat.v1
      description: |
        The type of permission statement. 
        The permission statement in the "permission" attribute must adhere to the
        published schema for the type given here.
        Note that some permission types might require special agreements before use.
      example: authentication.v1

    Intents:
      type: array
      maxItems: 3
      description: |
        Intents are flags that enable additional processing or alternate flows for granting the permission.
        The following intents are defined:
        * ciba: Use this permission with the CIBA flow. A binding message will be generated and returned when
          creating the permission.
        * iframe: Use this intent if you intend to use this permission with the iframe flow.
        * app2app: Use this intent if you intend to use this permission with the app2app flow.
      items:
        type: string
        enum: [ciba, iframe, app2app]

    AcrValues:
      type: array
      maxItems: 10
      items:
        type: string
        description: |
          Authentication Context Class Reference. See https://openid.net/specs/openid-connect-core-1_0.html#acrSemantics
          If not specified, the default is urn:bankid:bis and urn:bankid:bis will always be used first
          If multiple values are specified, they will be tried in order and the first one that is supported by the user will be used and billed for
        enum:
          - urn:bankid:bih
          - urn:bankid:bis

    PermissionStatement:
      type: string
      description: URL safe base64 encoded permission statement, statement structure must adhere to schema for the specified type.
      example: "eyJub25jZSI6ImprTkx3bVBrZnNVTllQNld0VXIyZGcifQ"

    PermissionStatementDigest:
      type: string
      description: URL safe base64 encoded byte array of the permission digest (SHA-256 hash of the permission statement)
      example: "urGMXD%2BWbGzokuB3gb9FOvdwbt6gNqAzxdfKt8%2B5PnA%3D"
