Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Introduction

This page introduces how we will implement passwordless login for set top boxes.

It describes the standard flow to implement passwordless login with Amino supplied STB interacting with Amino API

Basis of solution

This solution is based on /wiki/spaces/BOOX/pages/38273392/wiki/spaces/BOOX/pages/38273392

The flow is identical to DNA with the following exceptions:

  • The method of signing the token is JWT RS256
  • The call to /api/stb/auth is made using the JWT token

Solution summary

In three lines, the solution hinges on this:

  • When logging in the STB makes a claim about its identity to Amino
  • Solution summary

    In three lines, the solution hinges on this:

    1. When logging in the STB makes a claim about its identity to Amino
    2. Amino is able to verify that claim
    3. We know which user has which STB and so can log the user in

    Drawio
    bordertrue
    viewerToolbartrue
    fitWindowfalse
    diagramNamebig picture
    simpleViewerfalse
    width400
    diagramWidth842
    revision1

    Table of Contents


    User Stories

    High level diagrams

    Manufacturing process

    Drawio
    bordertrue
    viewerToolbartrue
    fitWindowfalse
    diagramNamemanufacture
    simpleViewerfalse
    width600
    diagramWidth771
    revision1

    Entone has a certificate authority (CA).

    At the time of manufacture an RSA keypair signed by this CA will be added to the box.

    User provisioning


    Drawio
    bordertrue
    viewerToolbartrue
    fitWindowfalse
    diagramNameuser provisioning
    simpleViewerfalse
    width600
    diagramWidth811
    revision12

    The user purchases a STB.

    The retail partner provisions a user account by calling the user management API (documentation)

    The retail partner links the STB to the user (documentation)

    The retail partner only needs to inform Amino of the STB mac addressserial number

    Info

    You can see details of how to manage the user account here on this page.

    User login


    Drawio
    bordertrue
    viewerToolbartrue
    fitWindowfalse
    diagramNameuser login
    simpleViewerfalse
    width600
    diagramWidth1061
    revision23

    Note:

    The Entone API will include the STB public key as one of the claims of the signed JWT token.

    Detailed flow

    Details of logging in with JWT

    Sequence overview

    1. Client calls the Entone API to get a JWT used for logging in
    2. Client sends login JWT token to Middleware
    3. Middleware responds with two tokens that can be used to authenticate future requests

    This is diagrammed in the section "user login" above.

    Entone API

    The View team will add a new function to the API with the following signature:

    String ENTONE.stb.createJWT(algorithm, claim) 

    Where claim is a object containing the payload of the JWT, algorithm is the mechanism to sign the signature.

    The returned string is a JWT which is based64 encoded string. 

    Parameters to pass to Entone API

    The algorithm must be one of the values supported as the "alg" parameter in the JWT spec (here).  The only algorithm supported is RSA with sha-256 and so the algorithm parameter value should always be "RS256".

    The client MUST use this format for the claim object:

    Code Block
    languagephp
    $claim = [
        "iss"                => "EntoneAPI",
        "iat"                => time(),
        "exp"                => time() + TEN_MINUTES,
        "aud"                => "www.aminocom.com",
        "subsn"                 => "Serial number 12325-1234567",
        'certificate' "cdsn"         => getPublicKey(),     'batchCACertificate' => getBatchCACertificate(),
    ];

    It will receive a JWT from EntoneAPI and must then call the MoveAPI endpoint as below.

    MoveAPI

    Endpoint

    Method typeURLAuthorizationPOSThttps://domain.tld/api/stb/authService-Token

    The code behind this endpoint must be modified to accept the JWT token. 

    We cannot make a breaking change to the endpoint that will affect other customers.

    Options to consider:

    • Make signature optional and if it is missing assume that the token is a JWT (bad, makes magic assumption, could be made better through strategy pattern though, I guess)
    • Add a new optional parameter for JWT (slightly better, but then we're having two parameters for token)
    • Use a new version of the endpoint

    Note:

    • It would be better to have a new endpoint for this, but we need to use the most efficient way of doing this

    Service authorization

    Is this 100% needed?

    Validation rules

    The MoveAPI must validate the JWT as follows:

    1. Decode the JWT
    2. Retrieve the supplied public key from the "certificate" claim
    3. Retrieve the suppled CA certificate from the "batchCACertificate" claim
    4. Verify that:
      1. The issuer is EntoneAPI
      2. The audience is www.aminocom.com
      3. The token has not expired
      4. The token was issued in the past, or otherwise within a tolerable window to allow for server time drift
      5. JWT was signed with the key you obtained in step 2
    5. Verify that the CA certificate is signed by the Entone CA certificate
    6. Obtain the "sub" claim
    7. Find the user associated with the STB serial code indicated in the "sub"

    (warning) It is important that the JWT is signed with the supplied key AND that the key was generated from the Entone root CA

    (warning) Note: Please expect different "iss" types that have different logic.  Try to encapsulate steps of 3 to 6 and link it to this specific "iss" type.... in other words deploy this as a changeable strategy in case we ever want to support other issuers of JWT (which seems plausible right now).   I don't want to have loads of jwt login endpoints, like one for Entone, one for Bob, another for Alice.  I'd rather we're able to use one JWT login url and swap logic depending on the "iss"

    Response

    The Move Middleware will respond with two JWT tokens that can be used for authentication in future requests.  This is identical to DNA.

    200
    {
    "jwt": "jp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiw...",
    "jwt_expiry": "Fri, 04 Dec 2015 16:01:07 +0000",
    "refresh_token": "WkiUzKELZ49eM7oWxAQK_ZX...",
    "refresh_token_expiry": "Fri, 04 Jan 2016 16:01:07 +0000",
    "client_keystore": "MIIKwIBAzCCoYCSqGSIb3...",
    "serial_no": "615500266162",
    "chipset_id": "8c10d4de5760",
    "mac": "8C10D4DE5761",
    "user_id": "email@example.com"
    }

    JWT token both jwt and refresh_token are encrypted using a pass phrase and HS256 encryption.

    Pass phrase is configurable by config file and will be shared separately.

    JWT Sample Data

    {
    "iss": "dna.booxmedia.com",
    "aud": "dna.booxmedia.com",
    "type": "access",
    "jti": "lAjYiDbptZ",
    "iat": 1459161322,
    "nbf": 1459161323,
    "exp": 1459161922,
    "data": {
             "stb": "370",
              "serial_no": "615500266162",
             "chipset_id": "8c10d4de5760",
             "mac": "8C10D4DE5761",
             "userId": "email@example.com"
    }
    }

    401none -

    Logout STB

    API to handle logout request of STB

    Request

    MethodURLAuthorization
    POST
    https://boox.fi/api/stb/logout
    STB (Using JWT), Service (Using service_token)

    POST Body

    Please note that M is for Mandatory and O is for Optional. 

    Body FieldsM/ODescriptionValues
    service_token
    M

    Token generated for a service. For example DNA has own service_token.

    This token is generated from Backend and provided to application developers.

    Warning

    This token should be kept in a secured location on application, i.e STB

    This param will be skipped if Service-Token HTTP Header  exists.
    String of Alpha numeric values. Mostly MD5 or SHA1 string.
     e.g. 8f9cf3f5789e16124f38936954a98668

    Headers

    Please note that M is for Mandatory and O is for Optional.

    HeaderM/ODescription
    Authorization: Bearer
    MJWT json web token provided by backend after STB authenticated successfully

    Response

    HTTP CodeResponse200

    none

    401none

    Link STB to a User

    After user bought a STB this API need to be called. This API link or grant ownership of a STB to a user.

    Request

    MethodURLAuthorization
    POST
    https://boox.fi/api/management/stb/link_user
    IP, Service (Digest Authentication)

    POST Data Parameters

    Please note that M is for Mandatory and O is for Optional.

    ParametersM/ODescriptionValuesserviceMService to which the user belongs.String of service username. Shared separately.
    serial_no
    MSerial Number of STB. If device does not exists with provided serial no then it will be added.

    Alpha numeric string.
    e.g.  615507895162

    email
    MEmail address of user who is provisioned for using the STBValid email address.
    e.g. john.doe@example.com 
    public_keys
    M

    8 Public keys which will be used to authenticate the STB.

    Note

    Public keys are stored based on the POST body order.

    So first public key is considered having key index 0.

    Last public key is considered having key index 7.

    key0_base64;key1_base64;...........;key7_base64 (no limit on max length).

    where each public key is base-64 encoded,semicolon(;) is used between keys as separator.

    chipset_idOSTB device chipset number/ID.chipset_id is a random list of characters (max 32 characters).macOEthernet interface MAC address.mac is a random list of characters (max 18 characters).

    Response

    HTTP CodeResponse200

    {

    	"id": "123",
    	"serial_no": "DNA-STB0001",
    	"user": {
    		"id": "10001",
    		"email": "stb_user@dnastb.com"
    	}
    }
    400
    {
      "error" {
        "code": 9,
        "text": "Access to this resource is locked to IP addresses"
      }
    }
    401none

    Error Codes

    Error CodeDescription1414Email does not exist1426Parameter is required1427Invalid length of chipset_id1428Invalid length of mac1433STB exists and linked1434Record already exists for value1435STB is already assigned1436Invalid email address format

    Unlink STB from User

    This API remove ownership of a STB from an user. Use cases: when user sells his/her device, when a device got stolen. 

    Request

    MethodURLAuthorization
    POST
    https://boox.fi/api/management/stb/unlink_user
    IP, Service (Digest Authentication)

    POST Data Parameters

    Please note that M is for Mandatory and O is for Optional.

    ParametersM/ODescriptionValuesserviceMService to which the user belongs.String of service username. Shared separately.
    serial_no
    MSerial Number of STBAlpha numeric string.
    e.g.  615507895162
    email
    MEmail address of user who is provisioned for using the STBValid email address.
    e.g. john.doe@example.com 

    Response

    HTTP CodeResponse200

    none

    400
    {
      "error" {
        "code": 9,
        "text": "Access to this resource is locked to IP addresses"
      }
    }
    401none

    Error Codes

    Error CodeDescription1414Email does not exist1426Parameter is required1432serial_no does not exists1418Invalid STB link1436Invalid email address format

    Add New User Account

    Info
    Existing API linkhttps://dna.booxmedia.com:10086/docs/d5/d8b/user_management.html#add_account

    This API is used to add a new user account. Following rules apply:

    • Email address or customer-id should not belong to any customer that is not in DELETED state; otherwise API will return an error.
    • If the user with that email exists in DELETED state and his grace period is not expired, his previous registration state is restored.
    • A new user is created in UNREGISTERED state.

    Design Points (to be considered for future):

    1. The main problem with making the two pin params as mandatory is that this feature is very specific to DNA requirements, while other frontends don't expect them. Therefore, we need a way so that both parties remain happy by giving a better design
    2. For that we should make it configurable whether the two params are mandatory. So for DNA we will configure them as mandatory, so that if they are not provided by Visio when creating a new user API will return an error to provide the mandatory input param. While for others e.g. Delta we will configure them as optional so that if they don't provide the params, API will successfully create a user and set the pins in DB as NULL (empty). Also until DNA is not ready for the params to be mandatory we can keep it configured as optional for them
    3. It is easy to implement from effort point of view and much flexible and reliable

    Request

    Method Type
    "Client Device-allocated Serial Number 48318382081",
        'certificate'        => "String containing the STB public key"
        'batchCACertificate' => "String containing the STB batch CA certificate",
    ];

    It will receive a JWT from EntoneAPI and must then call the MoveAPI endpoint as below.

    Example of generating a JWT

    Code Block
    languagejs
    themeEclipse
    titleJavascript example of creating JWT
    collapsetrue
    let passwordlessLoginHandle = null;
    export const passwordlessLogin = async () => {
      if (!ENTONE) {
        return Promise.reject();
      }
    
      // Combine concurrent login requests
      if (passwordlessLoginHandle) {
        return passwordlessLoginHandle;
      }
    
      const now = sdk.time.get();
      const claim = {
        iss: "EntoneAPI",
        iat: now,
        exp: now + 60 * 10,
        aud: "www.aminocom.com",
        sn: ENTONE.stb.getFullSerialNumber(),
        cdsn: ENTONE.system.getIrdetoCDSN() || "",
        certificate: ENTONE.stb.getPublicKey(),
        batchCACertificate: ENTONE.stb.getBatchCACertificate()
      };
      const token = ENTONE.stb.createJWT(ENTONE.stb.ALG_RS256, claim);
    
      passwordlessLoginHandle = sdk.user.stbLogin(token);
    
      try {
        const user = await passwordlessLoginHandle;
        setUserCallback && setUserCallback(user);
        passwordlessLoginHandle = null;
      } catch (error) {
        passwordlessLoginHandle = null;
        throw error;
      }
    };
    
    window.passwordlessLogin = passwordlessLogin;


    What is the STB serial number?

    Amino STBs with Irdeto Chipset contain several identifiers, two of them are:

    1. SN - basic serial number (printed on the STB) (73-2345532)
    2. CDSN - secure SN, which is stored on the device. STB UI gets it via Entone JS API, sends it to Amino backend. Entitlements with Irdeto are based on this identifier (6454386863). This is device id.

    The basic STB serial number is composed of two parts: the hw model prefix and the ESN. e.g. 87(hw model)-6593553 (ESN). and the mac address is derived from the ESN of the STB.

    MoveAPI

    Endpoint

    Method typeURLAuthorizationParameters
    POST
    https://domain.tld/api/stb/auth
    Service-TokenThe JWT must be passed as POST body parameter named "Token"

    Validation rules

    The MoveAPI must validate the JWT as follows:

    1. Decode the JWT
    2. Retrieve the supplied public key from the "certificate" claim
    3. Retrieve the suppled CA certificate from the "batchCACertificate" claim
      1. If it is omitted then read the CA certificate for batch 0133 from disk
    4. Verify that:
      1. The issuer is EntoneAPI
      2. The audience is www.aminocom.com
      3. The token has not expired
      4. The token was issued in the past, or otherwise within a tolerable window to allow for server time drift
      5. JWT was signed with the key you obtained in step 2
    5. Verify that the CA certificate is signed by the Entone CA certificate
    6. Obtain the "sn" claim
    7. Find the user associated with the STB serial code indicated in the "sn" claim

    (warning) It is important that the JWT is signed with the supplied key AND that the key was generated from the Entone root CA

    Info

    If the CDSN is stored in the STBDevice table then the API needs to compare the "cdsn" claim


    Response

    The Move Middleware will respond with two JWT tokens that can be used for authentication in future requests.

    200
    {
    "jwt": "jp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiw...",
    "jwt_expiry": "Fri, 04 Dec 2015 16:01:07 +0000",
    "refresh_token": "WkiUzKELZ49eM7oWxAQK_ZX...",
    "refresh_token_expiry": "Fri, 04 Jan 2016 16:01:07 +0000",
    "client_keystore": "MIIKwIBAzCCoYCSqGSIb3...",
    "serial_no": "615500266162",
    "chipset_id": "8c10d4de5760",
    "mac": "8C10D4DE5761",
    "user_id": "email@example.com"
    }

    JWT token both jwt and refresh_token are encrypted using a pass phrase and HS256 encryption.

    Pass phrase is configurable by config file and will be shared separately.

    JWT Sample Data

    {
    "iss": "example.com",
    "aud": "example.com",
    "type": "access",
    "jti": "lAjYiDbptZ",
    "iat": 1459161322,
    "nbf": 1459161323,
    "exp": 1459161922,
    "data": {
             "stb": "370",
              "serial_no": "615500266162",
             "chipset_id": "8c10d4de5760",
             "mac": "8C10D4DE5761",
             "userId": "email@example.com"
    }
    }

    401none -

    Refreshing the access token

    The JWT is valid for an hour, configurable at deployment time. The client should use the refresh token to obtain a new access token when access token is expired or about to expire.

    This can be done by calling

    POST https://domain.tld/api/stb/auth/refresh_token?refresh_token=123abc...

    The refresh token should be supplied as a query string parameter.

    The API will respond with a new access token and refresh token


    Logout STB

    API to handle logout request of STB

    Request

    MethodURLAuthorization
    POST
    https://customer.domain/api/stb/logout
    STB (Using JWT), Service (Using service_token)

    POST Body

    Please note that M is for Mandatory and O is for Optional. 

    Body FieldsM/ODescriptionValues
    service_token
    M

    Token generated for a service.

    This token is generated from Backend and provided to application developers.

    Warning

    This token should be kept in a secured location on application, i.e STB

    This param will be skipped if Service-Token HTTP Header  exists.
    String of Alpha numeric values. Mostly MD5 or SHA1 string.
     e.g. 8f9cf3f5789e16124f38936954a98668

    Headers

    Please note that M is for Mandatory and O is for Optional.

    HeaderM/ODescription
    Authorization: Bearer
    MJWT json web token provided by backend after STB authenticated successfully

    Response

    HTTP CodeResponse
    200

    none

    401none

    Link STB to a User

    After user bought a STB this API need to be called. This API link or grant ownership of a STB to a user.

    Request

    MethodURLAuthorization
    POST
    https://boox.fi/api/management/stb/link_user
    IP, Service (Digest Authentication)
    Query Strings

    POST Data Parameters

    Please note that M is for Mandatory and O is for Optional.

    Querystrings
    String of service username. Shared separately. the user.
    ParameterParametersM/ODescriptionValues
    serviceMService to which the user belongs.belongs.String of service username. Shared separately.
    serial_no
    MSerial Number of STB. If device does not exists with provided serial no then it will be added.

    Alpha numeric string.
    e.g.  615507895162

    email
    MEmail address (being used as an user identifier in AminoTV) of Email address of the user
    cidMCustomer Identifier.Numeric ID generated from Visio
    auth_pinM

    Authentication PIN code.

    Info
    titleChange

    This is new field.

    At the DNA TV Rel 2.9 publish time, the provisioning party (Visio)
    is not capable of supporting this. Change to optional temporarily. See Design Points above

    Number with the length of 4.
    e.g. 8798 
    purchase_pinM

    Purchase PIN code.

    Info
    titleChange

    This is new field.

    At the DNA TV Rel 2.9 publish time, the provisioning party (Visio)
    is not capable of supporting this. Change to optional temporarily. See Design Points above

    Number with the length of 4.
    e.g. 8798 
    dobOUser Date of birth in YYYY-MM-DD format.SUSPEND or ACTIVATE keywords are allowed only.

    Error Codes

    Error CodeDescription1403email is missing1405cid is missing1406auth_pin is missing1407purchase_pin is missing1412Email already exists1413CID already Exists

    Edit Existing User Account

    Info
    Existing API linkhttps://dna.booxmedia.com:10086/docs/d5/d8b/user_management.html#edit_account

    This API is used to suspend or activate a user account. It can also be used to change the email or customer-id of an existing account. Following rules apply:

    • A user in DELETED state is not updated.
    • "email" and "cid" parameters should not belong to any existing user, even if the user in in DELETED state
    • If a user is suspended, his state is changed to DISABLED
    • If a DISABLED user is activated and grace period has not expired, then previous registration state is restored, otherwise his state is changed to UNREGISTERED
    • In other cases, if a user is activated, his state changed to REGISTERED.

    Request

    Method TypeURLAuthorizationPUThttps://boox.fi/api/management/user/<email>Service (Digest Authentication)
    user who is provisioned for using the STBValid email address.
    e.g. john.doe@example.com 
    public_keys
    O

    Public keys which will be used to authenticate the STB. Maximum 8 keys.



    key0_base64;key1_base64;...........;key7_base64 (no limit on max length).

    where each public key is base-64 encoded,semicolon(;) is used between keys as separator.


    chipset_idOSTB device chipset number/ID.chipset_id is a random list of characters (max 32 characters).
    macOEthernet interface MAC address.mac is a random list of characters (max 18 characters).

    Response

    HTTP CodeResponse
    200

    {

    	"id": "123",
    	"serial_no": "STB0001",
    	"user": {
    		"id": "10001",
    		"email": "stb_user@example.com"
    	}
    }
    400
    {
      "error" {
        "code": 9,
        "text": "Access to this resource is locked to IP addresses"
      }
    }
    401none

    Error Codes

    Error CodeDescription
    1414Email does not exist
    1426Parameter is required
    1427Invalid length of chipset_id
    1428Invalid length of mac
    1433STB exists and linked
    1434Record already exists for value
    1435STB is already assigned
    1436Invalid email address format

    Unlink STB from User

    This API remove ownership of a STB from an user. Use cases: when user sells his/her device, when a device got stolen. 

    Request

    MethodURLAuthorization
    POST
    https://customer.domain/api/management/stb/unlink_user
    IP, Service (Digest Authentication)

    POST Data Parameters

    Please note that M is for Mandatory and O is for Optional.

    username. Shared separately.Number with the length of 4
    ParameterParametersM/ODescriptionValues
    serviceMService to which the user belongs.String of service
    emailONew email address of the user. Defaults to no value.Email address of the user
    cidONew customer Identifier. Defaults to no value.Numeric ID generated from Visio
    auth_pinO

    Authentication PIN code.

    Info
    titleChange

    This is new field.

    username. Shared separately.
    serial_no
    MSerial Number of STBAlpha numeric string.
    e.g.  615507895162
    email
    MEmail address of user who is provisioned for using the STBValid email address.
    e.g. 8798 
    purchase_pinO

    Purchase PIN code.

    Info
    titleChange

    This is new field.

    Number with the length of 4.
    e.g. 8798 
    actionOSUSPEND or ACTIVATE keywords. Defaults to no value.SUSPEND or ACTIVATE keywords are allowed only.. john.doe@example.com 

    Response

    HTTP CodeResponse
    200

    none

    400
    {
      "error" {
        "code": 9,
        "text": "Access to this resource is locked to IP addresses"
      }
    }
    401none

    Error Codes

    cid is invlid
    Error CodeDescription
    1407action value is invalid
    100User not found in the system
    1404email is invalid
    1406
    1414Email does not exist
    1426Parameter is required
    1432serial_no does not exists
    1418Invalid STB link
    1436Invalid email address format