Auth JWT

Authenticity API → Authenticity JWT

The VivoKey Authenticity API enables applications and services to check the authenticity of components and products containing VivoKey technology using strong standards based cryptographic proofs over NFC (contactless near field communication). Once the VivoKey NFC chip is scanned, a cryptographic challenge is obtained from VivoKey servers. That challenge is passed to the NFC chip and a response is generated. The response is sent back to VivoKey for validation.

Once validated, a signed "Json Web Token" or JWT called an "authenticity token" is issued. The typical format of a JWT is three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments, while being more compact when compared to XML-based standards such as SAML.

Authenticity JWT Table of Contents

Securing Modern Applications with JWTs

In today's digital age, security and seamless user experience are paramount for application developers. VivoKey combines cutting-edge chip authentication technology with the versatility of JSON Web Tokens (JWTs) to provide a robust solution for secure user authentication and authorization. By utilizing the VivoKey API, developers can easily integrate this advanced security mechanism into their applications.

What Are JWTs?

A JSON Web Token (JWT) is an open, industry-standard method (RFC 7519) for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed using a secret or a public/private key pair.

A typical JWT consists of three parts:

 

  1. Header: Specifies the type of token and the signing algorithm used.
  2. Payload: Contains the claims or statements about an entity (usually the user) and additional data.
  3. Signature: Used to verify the token hasn't been altered and, in the case of tokens signed with a private key, to verify that the sender of the JWT is who they say they are.

Authentication and JWT Generation

VivoKey microchips are secure, NFC-enabled devices which store cryptographic keys and can perform secure cryptographic operations. When integrated with our API, VivoKey powered products become powerful authentication tokens that  can be used to generate JWTs for secure communication between clients and servers.

How It Works

 

  1. User Interaction: The user taps their VivoKey enabled device against an NFC-enabled device, such as a smartphone.
  2. Secure Interaction: The application on the phone facilitates cryptographic communication between the VivoKey chip and API.
  3. Verification via VivoKey API: The API confirms the authenticity of the chip and the integrity of the cryptographic operation.
  4. JWT Issuance: Upon successful verification, the VivoKey API generates a JWT containing chip identity and additional relevant claims.
  5. Token Utilization: The application receives the JWT and uses it for authenticated requests to backend APIs or microservices.

Securing Your Application Backend

If you are using VivoKey enabled products with your applications or services, you will want to be sure that the data being passed from your user interface to your backend services is legitimate. User authentication and session states for your application only go so far. You need to be sure your authenticated user session is sending you legitimate chip scan data. Regular NFC chips are not secure in this way, and the data on them can be falsified by spoofing an NFC device or by simply sending the copied data directly to your API endpoints.

By sending the Authenticity JWT as part of your user authentication process or during an authenticated session, your backend can be assured that your user actually did scan a specific, authentic VivoKey enabled NFC device. The signed Auth JWT will contain specific claims relevant to securing your application or service.

Practical Security Aspects of JWTs

The important practical security aspects of JWTs include;

 

  1. They are signed. The VivoKey Auth JWT is signed during creation. You can and should always validate an Auth JWT's authenticity using our public key. Doing so ensures the JWT is legitimate (not faked), and unaltered - nobody will be able to send a faked or altered Auth JWT to your service or application.
  2. They contain an issue date (iat claim). This lets you know how recently the JWT was created and helps against replay attacks using old JWTs.
  3. They contain an expiration date (exp claim). Like the issue date, the expiration date is used by JWT validation libraries to easily determine if the JWT is considered expired by the issuer.
  4. They contain a unique  authenticated identifier (sub claim). Unlike using static data stored on an NFC chip, or the chip's serial number - both of which are just static data anyone can read and copy, the sub claim is part of the signed JWT payload. This identifier is considered safe to use if the JWT signature is verified and the JWT is not expired etc.
  5. They contain many other relevant claims. There are many other claims published within the VivoKey Auth JWT that can be very useful for making security decisions within your application or service.

VivoKey Authenticity JWT explained

The strength of a cryptographically signed Json Web Token (JWT) is that once issued, the contents can be trusted to be authentic and unaltered. The authenticity of the JWT can be validated by any server or service without needing to make any additional API calls by checking the JWT signature against a public key published by the issuer (VivoKey). By validating the JWT signature you can be assured of two things; the JWT was issued by VivoKey, and the contents has not been altered.

Authenticity JWT = Authenticated VivoKey Scan

The VivoKey Authenticity JWT is designed to be used as a certified assertion of a specific event. By properly evaluating the Auth JWT, you can know for sure that the a specific legitimately authenticated VivoKey powered device was authenticated by the VivoKey API at a specific moment in time. Considering the VivoKey Authenticity JWT in this way, your applications and services can consume a signature validated JWT to establish device contexts with user session contexts and / or user profile data in your backend.

JWT Format

A typical JWT is encoded as three Base64-URL strings separated by dots. The first section is called the header, the middle section is the payload, and the last section is the signature. Here is an example encoded authenticity token returned by the /session API endpoint.

eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkZ1VWoyMjZmajc1T3dVdW9rbW1vazZGdFVrUFJ5RmREUnhlR0Z3VFFqNU0ifQ.eyJkZXZfaWQiOiIwMmQxYTRhMS1hNDFkLTQ0MDYtYTJmOC1jYjhlNTk4NDdlNGYiLCJ0eXBlIjoyLCJwcm9kdWN0IjoyLCJhdHAiOiJtYXUiLCJjbGQiOiJ7XCJkYXRhXCI6XCJ0ZXN0aW5nXCJ9Iiwic3ViIjoiMWJhZTY4NGQzOWI5NDZlZTYxYmFkMjE2NTUzNTVmYzVlZmYwZWNjNzhjMjczMzQzZDRiMjA4OTQyMzQ2ZGYxYyIsImlhdCI6MTcwMzgzMjk3MCwiZXhwIjoxNzAzODMzMDAwLCJpc3MiOiJodHRwczovL2F1dGgudml2b2tleS5jb20iLCJqdGkiOiIwNmY4MGMwMzU4YTg3NDA3MGJlMTQwYjUyZGVlMDZmY2U4MzYwM2FmMmUzZjFhNzY2YmY0MzVkZTk1N2JhN2Q5In0.xJ-_qze8A0sX7WFaQyftTLrpy9XHsBkYiKw7Fb6aszbzZ3X0nyz46-VUmX6z0RBU_n5RRwR-gnG_d-MzWF-hmQ

You can view the authenticity token at jwt.io. As you can see, the decoded JWT has the following JSON structure;

{
    "typ": "JWT",
    "alg": "ES256",
    "kid": "jk3rW4HAVoGK9zAXlvusvs1u1KyYLELXDmt9yS9ubaI"
}
.{
"dev_id": "02d1a4a1-a41d-4406-a2f8-cb8e59847e4f",
"atp": "mau",
"cld": "{\"data\":\"testing\"}",
"sub": "1bae684d39b946ee61bad21655355fc5eff0ecc78c273343d4b208942346df1c",
"iat": 1703832970,
"exp": 1703833000,
"iss": "https://auth.vivokey.com",
"jti": "06f80c0358a874070be140b52dee06fce83603af2e3f1a766bf435de957ba7d9",
"type": 2,
"product": 2,
}
.[Signature]

JWT Header

The header contains typ, alg, and kid which mean, respectfully, type of token, signature algorithm used, and key ID of the private key used to sign with. The only real important value in the header is the algorithm used for signing the JWT as this will need to be the algorithm used validate it.

JWT Claims

The payload section contains the following "claims". Claims are assertions - bits of information the Authenticity JWT is claiming to be true, as they relate to the chip scan and authenticity event which produced the JWT.

  • dev_id (developer ID) is the unique identifier of the developer account that owns the API key used to generate the JWT. This allows applications that accept VivoKey Auth Json Web Tokens to discriminate as to which developer or developers it will accept generated JWTs from.
  • sub (subscriber) is the fully validated and authentic chip ID that can be stored in local service databases and used as a reliable secure identifier for this specific chip in this specific product. The same chip ID is returned for any and all API keys *associated with your developer account email.
  • iat (issued at) is a Unix timestamp representing the number of seconds which have passed since Jan 1, 1970. The iat timestamp represents the UTC date and time that the token was created.
  • exp (expiration) is a Unix timestamp representing the time the token expires, which is 30 seconds from the time the token was issued (iat). The token must be considered expired if the current time has surpassed the exp time.
  • cld (client data) is optionally included if cld data (up to 1024 bytes) was provided to the /session endpoint.
  • atp (authentication type) is the mechanism used to validate authenticity of the chip. Possible values are cmac for counter based signature validations, tam for tag auth mechanism, or mau for mutual authentication. It is not generally important to know which mechanism was used, however CMAC authenticated tokens cannot be renewed and are generally considered to be low security compared to other forms of authentication types. The atp claim can be used to help establish a level of trust consumers wish to grant the token.
  • iss (issuer) is a standard registered claim which indicates who or what issued the token.
  • jti (jwt id) is a random string unique identifier for this exact token. The intent is to easily enable one time use of the token and guard against replay attacks during the time between iat and exp.
  • type (chip type) means the actual type of chip inside the device being validated for authenticity. This is not necessarily all that useful outside of VivoKey internal services, but it's passed as part of the token so that VivoKey services need only consume the token itself, and not need to perform internal lookups or calls to determine authenticity of the contents.
  • product (product code) is another simple identifier to easily differentiate which type of product a particular chip type is in, be it a wearable, implant, or otherwise. (1) Spark 1, (2) Spark 2, (3) Demo Card, (4) Apex, (5) Licensed Signature.

*It is important to understand that the chip ID returned in the sub claim of the authenticity token is a hash based on a combination of values including internal VivoKey chip identifier, internal VivoKey developer account identifier (associated with the email address the API key was sent to), and some additional data elements. This results in a chip ID value that is the same for every API key associated with your developer email address. However, to help improve privacy, API keys for different developers will return different chip IDs for the same chip. This makes it more difficult for services to share databases and identify the same product / user / person across multiple services without their consent.

JWT Signature

The signature section is a hash signature of the header and payload sections, encrypted using a private key secured inside VivoKey servers. When used with the public key given below, you can validate the signature of the authenticity token. In turn, this validates that the contents of the token have not been altered, such as the chip value or exp timestamp.

Validating authenticity JWT signatures

After validating the authenticity of a VivoKey chip or product using our API, what happens if you want to communicate that information between servers, or mobile app and backend service? How does your backend know it's receiving legitimate data? How does it know it can even trust the authenticity JWT itself? It might be easy to assume you can trust it when you just received it from our API endpoint, but when you need to pass that information to a backend server to perform more functions, that chain of trust is lost. How does that server know someone isn't just passing bogus data into your server or service endpoint? The answer is JWT signature validation.

By using a JWT based authenticity token, we solve the trust problem by containing all of the critical information inside the JWT, including expiration time (after which the token is considered to be invalid). All of that data is then hashed and signed using the private key of a VivoKey public private key pair, and the signature is suffixed as part of the JWT structure. That means you can simply pass the complete authenticity token to your server, and it can validate the signature using a locally cached copy of the VivoKey public key to confirm the contents is valid and unaltered, without having to check with VivoKey APIs to ensure the token is valid.

The Json Web Key Set (JWKS)

The industry standard way to publish public keys for signature verification is by using a Json Web Key Set (JWKS). It is a array of one or more json keys, each containing cryptographic keys used to verify JWT signatures. The JWKS may contain multiple keys, so each key in the JWKS has a Key ID (kid), which is used to match the correct key with the kid value in the JWT header. Our jwks.json file is published using the standard "well known" URL;

https://auth.vivokey.com/.well-known/jwks.json

Employ jwks.json caching

Part of the point of signing a JWT is to ensure you don't have to make any calls to external servers for every single signature validation. Proper signature validation behavior is to keep a local copy of the jwks cached on your server and / or application. You should only be pulling down the jwks.json data on initial JWT signature validation, if the matching key ID for the JWT is not found in the cached jwks, or on a signature failure. In that case, pull down a fresh copy of the jwks and check again. You can also opt to refresh jwks.json periodically based on your own schedule.

JWT signature validation flow

Public key EC and PEM formats

Our authenticity JWTs are signed using the ES256 (EC) algorithm, so the public key inside the JWKS is formatted as elliptic curve points with x and y coordinates. However some JWT processing libraries require PEM format public keys. For your convenience we include a special element value inside called pem which contains the public key in PEM format.

Validate your tokens!

It is extremely important that you actually perform validation of the token signature and not ignore it in favor of focusing exclusively on the payload data. The exact process to do this will depend on which JWT library you use to parse the authenticity token. The rule of thumb in the cryptography industry is that you don't roll your own crypto. There are tons of JWT processing libraries for every kind of platform and language. Find a well supported one and use that to parse and validate authenticity tokens at every point along your application or service where the authenticity token is passed between systems or processes. This is especially important if your service has API endpoints accessible to the internet which anyone can take a stab at passing data to.

Unique token identification

There may be some situations where you want your endpoint or service consuming an authenticity token one time only. This is generally used to protect against replay attacks during the period of time between iat and exp. As long as you are honoring the exp claim and invalidating tokens after the exp time, you only have to store and compare unique jti values for that short window of time for which authenticity tokens are valid.

JWT aging and renewal

The value of a JWT is that it can be validated without doing anything other than a signature check, but that's only half of the trust mechanism. The other half is how you handle token aging. An old expired legitimate JWT that has not been altered can still be used if the issued date and expiration date is not being checked. Anyone with a copy of a valid signed JWT could supply it at anytime (replay attack) to your services or API endpoints. 

JWT expiration

To ensure the token is minty fresh, you will have to decide how to handle token aging. In the JWT payload, we supply two UTC timestamp claims; iat (issued at time) and exp (expiration time). The exp timestamp is 30 seconds after iat, so as far as VivoKey is concerned, tokens have a 30 second lifespan. VivoKey will not accept an expired token for any services processing or token renewal.

Typically, the JWT library you'd be using will be checking checking to see if current UTC timestamp > exp and if so, consider the token expired. If you decide that you want to trust the validity of a token for less or more time than 30 seconds, you are free to make your own calculation; expired after iat + N seconds. Just be aware that the longer a token's lifespan, the larger time window potential replay attacks have.

Leeway adjustment

The timestamps contained within the iat and exp claims work together to determine age and freshness of the JWT, but because clocks around the world are not exactly synchronized, almost every JWT processing library will allow for some "leeway" adjustment. This is typically just a number of seconds to add to the exp date to accommodate differences in system clocks that might be creating and processing JWTs. You can use this setting to tell your JWT library you'd like to accept JWTs for a longer period beyond the exp claim in the payload, but there are security risks involved with exceptionally long time periods.

Typically the best approach to token aging is to either;

  1. Use the short validity period of the JWT to establish a secure context within a user session, then let the JWT expire.
  2. Use the JWT renewal process to continually refresh the token for the life of the user session.

JWT renewal

VivoKey will soon have a renewal endpoint for unexpired tokens. This endpoint will allow you to submit an unexpired token to be renewed, which will update the exp timestamp for another 30 seconds (UTC + 30s), but retain the original iat timestamp, then sign and issue the new JWT. This will allow you to determine the original token's issue timestamp while ensuring the token is still considered "fresh". The renewal process will be necessary to continue to use the authenticity token with VivoKey services beyond the initial 30 second token lifespan. Of course you can also establish and maintain your own client service sessions using this same method.