Skip to content

Latest commit

 

History

History
1062 lines (776 loc) · 35.3 KB

File metadata and controls

1062 lines (776 loc) · 35.3 KB

Authenticator API

Contents

This document details all available HTTP API endpoints exposed by the service to manage JWT tokens.

JWT tokens assert the User's identity and status as an authorized user and my be received in 2 states: authorized or pre_authorized

  • authorized - User is fully authenticated and has completed 2FA
  • pre_authroized - User has been identified via their email or phone number, but has yet complete 2FA authentication

JWT tokens are short lived but may be refreshed with a refresh token. They have the following properties:

Property Description
client_id The hash of a JWT Token's accompanying client ID
user_id Unique ID (ULID) of the User. This value will not change
email Email address of the User. This value may be modified
phone Phone number of the User. This value may be modified
state State of the user in our system, either authorized or pre_authorized (pending 2FA)
refresh_token The hash of a JWT Token's accompanying refresh token
tfa_options A list of available 2FA options for the client to render for a user (totp, otp_email, otp_phone, device)
default_tfa The recommended enabled TFA option a client should show a user
exp The latest validity time of a token as a unix timestamps. Expired tokens may be refreshed
iat The issuing time of the token as a unix timestamp

Authentication with JWT

Clients are expected to deliver the JWT token through the following header:

Authorization: Bearer <jwtToken>

In addition to the JWT token, the client ID is also expected to be sent back in a cookie header to verify the user.

To mitigate XSS attacks, tokens are fingerprinted with the hash value of a client ID. The client ID is expected to be store securely on the client (e.g. HTTP Only, Secure Only cookie) and returned back to us in a cookie header. If a client ID is not provided, authentication will fail.

Client IDs are only provided to a user after signup/login. Other endpoints will refresh a token and therefore share the same client ID.

Cookie: CLIENTID=<clientID>

Refresh tokens are long lived tokens that allow a user to refresh a non-revoked JWT token. Refresh tokens are supplied to a user after successful authentication alongside a client ID and are expected to be returned back in a cookie header to refresh a token.

New refresh tokens may only be retrieved from a successful login.

Cookie: REFRESHTOKEN=<refreshToken>

Provides endpoints to manage user registration. It is a 2-step API and a pre-requisite in order to obtain a authentication token to access protected resources.

A client initiates registration with a POST request to api/v1/signup and completes registration with a subsequent POST request to api/v1/signup/verify in which they validate a response we return to them from their initial request.

A user provides either an email or phone number for us to tidentify them. On success we will send a random code to their contact address and a JWT token with status unverified.

  • Request (application/json)

    • Parameters

      • type (required, string) - Description of idenitty, either email or phone
      • identity (required, string) - Phone number or email address of the user.
      • password (required, string) - Password of the user.
  • Response 201 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA",
  "clientID": "TSF9SUpSdj8rQmcpXTc9VX1VUzQtVC96fVdBZ0lKIXxdKycvVGNVMw"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "invalid_field",
    "message": "Email address is invalid"
  }
}

A user proves their identity to us by sending back the randomly generated code we delivered to them. On success they will receive a JWT token asserting their status as a new authorized user.

  • Request (application/json)

    • Parameters

      • code (required, string) - 6 digit code sent to user.
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 201 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA",
  "clientID": "TSF9SUpSdj8rQmcpXTc9VX1VUzQtVC96fVdBZ0lKIXxdKycvVGNVMw",
  "refreshToken:" "eyJjb2RlIjoiWCxMN2Q2LWA6JzJcdTAwM2UhenFNb1FcImJaZlFLUyRwOGRPWj1bamBAZm9BXHUwMDNlIiwiZXhwaXJlc19hdCI6MTU5NDQwNTc1MX0"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "invalid_code",
    "message": "incorrect code provided"
  }
}

Provides endpoints to manage user authentication. It is a 2-step API where a client initiates login with a POST request to api/v1/login. After the initial request, they will complete the multi-factor authentication requirement with a POST request to either api/v1/login/device or api/v1/login/code to verify a device, randomly generated code or TOTP code.

A user provides either an email or phone number and password for us to identify them. On success we will return a JWT token with state pre_authorized.

  • Request (application/json)

    • Parameters

      • type (required, string) - Description of idenitty, either email or phone
      • identity (required, string) - Phone number or email address of the user.
      • password (required, string) - Password of the user.
  • Response 201 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA",
  "clientID": "TSF9SUpSdj8rQmcpXTc9VX1VUzQtVC96fVdBZ0lKIXxdKycvVGNVMw"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "invalid_field",
    "message": "Email address is invalid"
  }
}

A user submits a random server generated code or TOTP code. On success we will return a JWT token with state authorized.

  • Request (application/json)

    • Parameters

      • code (required, string) - 6 digit code sent to user.
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 201 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA",
  "clientID": "TSF9SUpSdj8rQmcpXTc9VX1VUzQtVC96fVdBZ0lKIXxdKycvVGNVMw",
  "refreshToken:" "eyJjb2RlIjoiWCxMN2Q2LWA6JzJcdTAwM2UhenFNb1FcImJaZlFLUyRwOGRPWj1bamBAZm9BXHUwMDNlIiwiZXhwaXJlc19hdCI6MTU5NDQwNTc1MX0"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "invalid_code",
    "message": "incorrect code provided"
  }
}

A user signs a server challenge with their WebAuthn capable device. On success we will return a JWT token with status authorized.

  • Request (application/json)

    • Parameters

      • id (required, string) - id generated from browser's navigator.credentials.create API
      • rawId (required, string) - rawId generated from browser's navigator.credentials.create API and parsed from a BufferSource to a Base64 encoded string
      • response (required, object)
        • attestationObject (required, string) - attestationObject generated from browser's navigator.credentials.create API and parsed from a BufferSource to a Base64 encoded string
        • clientDataJSON (required, string) - clientDataJSON generated from browser's navigator.credentials.create API and parsed from a BufferSource to a Base64 encoded string
      • type (required, string) - Credential type. This should always be "public-key"
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 201 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA",
  "clientID": "TSF9SUpSdj8rQmcpXTc9VX1VUzQtVC96fVdBZ0lKIXxdKycvVGNVMw",
  "refreshToken:" "eyJjb2RlIjoiWCxMN2Q2LWA6JzJcdTAwM2UhenFNb1FcImJaZlFLUyRwOGRPWj1bamBAZm9BXHUwMDNlIiwiZXhwaXJlc19hdCI6MTU5NDQwNTc1MX0"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "webauthn",
    "message": "invalid signature"
  }
}

A user holding a JWT token with status identified may request this endpoint to receive a challenge value to sign. The signed value must be POSTed back to our service to complete authentication.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "publicKey": {
    "challenge": "4xH0vUsr6b2oHTKn7GS3I9ZbqEHSF4aLAil9exrCWoI=",
    "timeout": 60000,
    "rpId": "authenticator.local",
    "allowCredentials": [
      {
        "type": "public-key",
        "id": "kXV0GAUZjDSncqwfxvxVSN55IhTxty88Fhg3S38LU6w9Jl421SZQlf6epPuLhP5KwKICDUJk+/w3F8DrDj1vqA=="
      }
    ]
  }
}
  • Response 400 (application/json)
{
  "error": {
    "code": "webauthn",
    "message": "Error validating origin"
  }
}

Provides endpoints to manage WebAuthn capable devices for a User. Device registration is a 2 step process where the client retrieves necessary data to create a credential through a POST request to /api/v1/device. On success, the payload is passed to the browser's navigator.credentials.create API and the user is requested to sign the credential. This credential contains a challenge which is verified during the second step of the API through a POST request to /api/v1/device/verify.

A user requests to register a new device using their authorized JWT token and receives a WebAuthn challenge response.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "publicKey": {
    "challenge": "b9aqYRIe/grw/Z4QfK1QvhYxrgsD3Cm743sFdrKdphI=",
    "rp": {
      "name": "Authenticator",
      "id": "authenticator.local"
    },
    "user": {
      "name": "ddddd@ddd.com",
      "displayName": "ddddd@ddd.com",
      "id": "MDFFQUREMjM4WFNaSkVUSDk4QUVEVkIyWVo="
    },
    "pubKeyCredParams": [
      {
        "type": "public-key",
        "alg": -7
      },
      {
        "type": "public-key",
        "alg": -35
      },
      {
        "type": "public-key",
        "alg": -36
      },
      {
        "type": "public-key",
        "alg": -257
      },
      {
        "type": "public-key",
        "alg": -258
      },
      {
        "type": "public-key",
        "alg": -259
      },
      {
        "type": "public-key",
        "alg": -37
      },
      {
        "type": "public-key",
        "alg": -38
      },
      {
        "type": "public-key",
        "alg": -39
      },
      {
        "type": "public-key",
        "alg": -8
      }
    ],
    "authenticatorSelection": {
      "authenticatorAttachment": "cross-platform",
      "requireResidentKey": false,
      "userVerification": "preferred"
    },
    "timeout": 60000,
    "attestation": "direct"
  }
}
  • Response 400 (application/json)
{
  "error": {
    "code": "webauthn",
    "message": "Error validating origin"
  }
}

A user completes device registration by signing a WebAuthn server challenge with their device. On success, a refreshed JWT token is returned to the user.

  • Request (application/json)

    • Parameters

      • id (required, string) - id generated from browser's navigator.credentials.create API
      • rawId (required, string) - rawId generated from browser's navigator.credentials.create API and parsed from a BufferSource to a Base64 encoded string
      • response (required, object)
        • attestationObject (required, string) - attestationObject generated from browser's navigator.credentials.create API and parsed from a BufferSource to a Base64 encoded string
        • clientDataJSON (required, string) - clientDataJSON generated from browser's navigator.credentials.create API and parsed from a BufferSource to a Base64 encoded string
      • type (required, string) - Credential type. This should always be "public-key"
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 201 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "webauthn",
    "message": "Error validating origin"
  }
}

A user removes a device from their account. Removed devices can no longer be used for authentication. On success, a refreshed JWT token is returned to the user.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request,
    "message": "No device found"
  }
}

A user may set a name on a device by initiating a POST request for the device ID (retrieveable from teh device list endpoint.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
    • Parameters

      • name (required, string) - New name for the device
  • Response 200 (application/json)

{
  "device": {
    "id": "01EEVD47S5V1GZPV1XWB89NW1W",
    "name": "Yubikey 4C",
    "createdAt": "2020-08-04T00:14:50.68491Z",
    "updatedAt": "2020-08-04T00:14:50.68491Z"
  }
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request,
    "message": "No device found"
  }
}

Retrieve all devices available to be used for 2FA on the account. The device list includes a device ID which may be used for device removal and renaming requests.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "devices": [{
    "id": "01EEVD47S5V1GZPV1XWB89NW1W",
    "name": "Yubikey 4C",
    "createdAt": "2020-08-04T00:14:50.68491Z",
    "updatedAt": "2020-08-04T00:14:50.68491Z"
  }]
}
  • Response 401 (application/json)
{
  "error": {
    "code": "invalid_token",
    "message": "User is not authenticated"
  }
}

Provides endpoints to manage a User's token.

A user revokes a token, rendering it invalid for authentication. Revoked tokens can no longer be refreshed.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "status": "ok"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "invalid token ID"
  }
}

A user confirms the currently used token is valid. This endpoint intends to be used internally by other trusted services to verify a User is in possession of a JWT token in an authorized state with accompanying client ID.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "status": "ok"
}
  • Response 401 (application/json)
{
  "error": {
    "code": "invalid_token",
    "message": "Token is invalid"
  }
}

A user refreshes an expiring token. Only authorized tokens may be refreshed.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "invalid_token",
    "message": "Token is revoked"
  }
}

Provides endpoints to manage TOTP secret configuration on a user. By default, 2FA is enabled on all users through delivery of an OTP code via a verified email or SMS. Users may instead opt to generate a TOTP code through a supported app or device.

A client initiates a request to api/v1/totp to generate a new TFA secret on their profile. If TOTP is already enabled for the user, this request will fail. After successfully creating a secret, the server will return a a TOTP URI containing the TFA secret value. Clients may use this string to generate a QR code to be scanned by the user, or optionally render the URI contents for manual entry.

TOTP is enabled after the user generates a TOTP code sends it back to the server through a POST request to api/v1/totp/configure.

If a user wishes to disable TOTP, they make a DELETE request to api/v1/totp/configure with a valid TOTP code.

A user requests a new TOTP URI to generate TOTP codes.

  • Request (application/json)

    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "totp": "otpauth://totp/Example:jane@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "totp is already configured"
  }
}

A user enables TOTP as a 2FA method after sending us a valid TOTP code generated by their secret key.

  • Request (application/json)

    • Parameters

      • code (required, string) - 6 digit code sent to user.
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 201 (application/json)

{}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "totp is already configured"
  }
}

A user disables TOTP as a 2FA method after sending us a valid TOTP code generated by their secret key.

  • Request (application/json)

    • Parameters

      • code (required, string) - 6 digit code sent to user.
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "totp is not enabled"
  }
}

Provides endpoints to allow users to manage their contact addresses for OTP delivery. Users may add/remove an address, or optionally leave an address attached to their profile while disabling it as an OTP delivery channel.

Addresses may not be disabled for OTP delivery unless an alternative 2fA method such as TOTP or FIDO is enabled on the account.

Request a new address (email or phone number) to be added onto the account. On receipt, a randomly generate OTP code will be delivered to the new address and the client will receive a refreshed JWT token containing the OTP hash. Clients are expected to send the OTP back through api/v1/contact/verify in order to complete the address change.

  • Request (application/json)

    • Parameters

      • deliveryMethod (required, string) - email or phone
      • address (required, string) - Email address or phone number with country code
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 202 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "deliveryMethod must be `phone` or `email`"
  }
}

Disable an address from receiving OTP codes. If a secondary 2FA method is enabled on the profile (an alternative contact address, TOTP, or FIDO device), users may opt to disable a contact address from being used as a 2FA method. On success, a refreshed JWT token will be returned to the user.

  • Request (application/json)

    • Parameters

      • deliveryMethod (required, string) - Delivery method to be disabled (email or phone)
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 202 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "deliveryMethod must be `phone` or `email`"
  }
}

Verify ownership of an address by submitting an OTP code. This is the follow up step to api/v1/contact/check-address. Verified addresses are enabled as an OTP delivery channel by default unless the client explicitly requests otherwise. On success, a refreshed JWT token will be returned to the user.

  • Request (application/json)

    • Parameters

      • code (required, string) - OTP code delivered to address
      • isDisabled (optional, boolean) - Boolean to disable the address from OTP delivery
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "deliveryMethod must be `phone` or `email`"
  }
}

Remove an address from a user's profile. A removed address must go through the 2 step process (request change -> verify ownership) to be re-added to the account in the future. On success, a refreshed JWT token will be returned to the user.

  • Request (application/json)

    • Parameters

      • deliveryMethod (required, string) - Delivery method to be disabled (email or phone)
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "deliveryMethod must be `phone` or `email`"
  }
}

Reesend an OTP to a verified address. If an OTP is not received during login, it may be requested again through this endpoint. A refreshed PreAuthorized JWT token (retrieved during the first step of login) is required for this endpoint.

User's who are already authenticated and are re-requesting an OTP should use api/v1/contact/check-address instead.

  • Request (application/json)

    • Parameters

      • deliveryMethod (required, string) - Delivery method to be disabled (email or phone)
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 202 (application/json)

{
  "token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE4MTg2MDUsImp0aSI6IjAxRUFGVkMxMFBSRzE5REQyNUZFWUFRQVpLIiwiaXNzIjoiYXV0aGVudGljYXRvciIsImNsaWVudF9pZCI6IjA3ZmE3ODBiNjdmNTI3N2YzZTE0MDRjNDMyN2Y0NTBkYjllMzBlNGZjYTE4MmMwNmFkNzEyZDA5NTYwMWI0MTI1NWVlNjg2Y2JlNWI5NDBlZGZmMGVhYzcwZTVkZmY0NDU0MmVlZTI2ODE2NDBmNjA4YTljNmRmYWM2ZDg4NWNmIiwidXNlcl9pZCI6IjAxRUFGVkMwWUowUzZLM0Y5VjdKNDNGR1FCIiwiZW1haWwiOiJ0ZXN0OEB0ZXN0LmNvbSIsInBob25lX251bWJlciI6IiIsInN0YXRlIjoicHJlX2F1dGhvcml6ZWQiLCJjb2RlIjoiYjUwMDZhODU3MTIyNWIyMWNkZjVmYzgwZGNkNGU5ZGFmYzZlNGY3ODZhZTk1OTRjMmMzZGQ3NGY4NzRlYWM3OGNjYTVmYmRjYjk4ZjZjMDUxNDI2MmVlYjQzZDQ0ZWFmODhiNzUyODBkZWMyMjhhZjJhNWJmOTA5YWM4NGI4MjEifQ.N8l-mqp6hnWN2Z630hpGNITvfDR6PT4Yl2Rt52_HzWjG4NqWG8CfXJ8AntNDOfsvIGLR6t7qlVmUlUwd4cEwuA"
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "deliveryMethod must be `phone` or `email`"
  }
}

Provides an endpoint to retrieve historical login history. Token ID's are exposed in this endpoint to be used for revocation if required.

Retrieve a paginated list of historical user login h istory.

  • Request (application/json)

    • Query Parameters

      • limit (optional, number) - Maximum amount of records to retrieve. Defaults to 10
      • offset (optional, number) - Starting point of query. Defaults to 0
    • Headers

      • Authorization: Bearer <jwtToken>
      • Cookie: CLIENTID=<clientID>
  • Response 200 (application/json)

{
  "loginHistory": [
    {
      "tokenId": "01EF7XJ0FXBYV3PFBCVA5HENW9",
      "isRevoked": false,
      "ipAddress": "127.0.0.1",
      "expiresAt": "2021-01-31T16:52:52Z",
      "createdAt": "2021-01-16T16:52:52.658972Z",
      "updatedAt": "2021-01-16T16:52:52.658972Z"
    }
  ]
}
  • Response 400 (application/json)
{
  "error": {
    "code": "bad_request",
    "message": "Pagination param should be a number"
  }
}