Authenticating with Keyless headers and JWT

The Keyless mobile SDK has built-in JWT signing functionality, which you can use in dynamic linking during enrollment or authentication.

If you don't have a secure connection between your mobile application and your application backend, you can use JWT signing and the Keyless server API to communicate securely over HTTP.

One possible use for this is to to transmit the JWT public signing key, which is only available at enrollment, to your application backend:

  1. In the mobile application, generate the HTTP request containing the public key to send to your application backend

  2. In the Keyless mobile SDK, generate Keyless authentication headers for the HTTP request

  3. In the mobile application, send the HTTP request to your application backend, with the Keyless headers

  4. In the application backend, receive the request, extract the Keyless headers and contact the Keyless server API to validate them

  5. If the Keyless headers are valid, the Keyless server API returns user ID, path and sha256 hash of the body

  6. In the application backend, validate the path and hash with what it receives and can safely associate content of the body, which is the public key, with the user ID

Example

In the mobile application, after enrollment:

// get the public key after an enrollment or authentication -> userSigningKey

// a http POST to https://api.customer.com/jwt-signing-key
method = "POST"
path = "/jwt-signing-key"
body = userSigningKey

headers = Keyless.createDeviceAuthenticationHeaders(method, path, body)

// do not forget to add content type to headers, in this case it would be text/plain

// use your normal method of sending an http request
httpRequest(method, Url("https://api.customer.com", path), headers, body)

A backend application handler for the /jwt-signing-key endpoint.

# handler for POST /jwt-signing-key endpoint (parameters is request)

# get only keyless headers, which start with the "X-Keyless-" prefix
keyless_header = request.get_headers_starting_with("X-KEYLESS-")

# validate keyless headers on the keyless server API and api key provided by keyless
keyless_response = http_request(
	method="POST",
	url="https://api.keyless.io/v2/verify-device-auth-headers",
	headers={"X-Api-Key": "<api key provided by keyless>",
  "Content-Type": "application/json"},
	body=keyless_headers)

# if status code is not 200 headers are not valid, check the body for details why
assert keyless_response.status_code == 200:

# check if headers were generated for correct path
assert keyless_response.json_body["path"] == "/jwt-signing-key"

# check if original body hash matches one in the response

# the has is stored as hex string
keyless_headers_body_hash = sha256.from_hex(keyless_response.json_body["requestHash"])

# the body is transmitted as string but to calculate sha256 we need a bytes.
# the mobile SDK uses utf8 encoding here
original_body_hash = sha256.digest_from(request.body.encode_utf8())

assert keyless_headers_body_hash == original_body_hash

# and now we can trust the body and associate it with keyless_id
save_jwt_public_key(keyless_response.json_body["keylessId"], request.body)

Last updated