# Concept of Trusted Devices

## Overview

This page describes the concept of trusted devices that introduces an additional layer of authentication. The concept of trusted devices allows blocking the source of an attack without blocking legitimate users. To do so, an application issues a token that is tied to a user's account for each device from which there was a successful authentication. As a result, when authentication is blocked for a specific account during an attack, a legitimate user can still authenticate from trusted devices.

### Algorithm description

<details>

<summary>Legend</summary>

![](https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-475a05782b68a0cc5dcf6a9b1df381b7c7d90d29%2Fexit-icon.svg?alt=media) - End of the algorithm.

</details>

The entry point for an authentication request:

1. If an incoming request contains a device token:
   1. Validate a device token, see the [Device token validation](#device-token-validation) section.
   2. If token validation fails, proceed to step 2.
   3. If a device token is in a lockout list, reject authentication attempt ![](https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-475a05782b68a0cc5dcf6a9b1df381b7c7d90d29%2Fexit-icon.svg?alt=media)
   4. Authenticate a user, see the [User authentication](#user-authentication) section.
2. If authentication from untrusted clients is locked out for the account, reject authentication attempt ![](https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-475a05782b68a0cc5dcf6a9b1df381b7c7d90d29%2Fexit-icon.svg?alt=media)
3. Authenticate a user, see the [User authentication](#user-authentication) section ![](https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-475a05782b68a0cc5dcf6a9b1df381b7c7d90d29%2Fexit-icon.svg?alt=media)

#### User authentication

1. Check user credentials.
2. If credentials are valid:
   1. Issue a new device token to a user's client, see the [Issue new device token](#issue-new-device-token) section.
   2. Proceed with authenticated user.
3. Otherwise:
   1. Register failed authentication attempt.
   2. Reject authentication attempt ![](https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-475a05782b68a0cc5dcf6a9b1df381b7c7d90d29%2Fexit-icon.svg?alt=media)

#### Register failed authentication attempt

1. Register a failed authentication attempt with at least the following information:
   1. Account.
   2. Time.
   3. Device token (if present).
2. If a device token is presented:
   1. Count the number of unsuccessful authentication attempts in `K` minutes for this specific device token.
   2. If the number of unsuccessful attempts in `K` minutes is more than `M`, put the device token in a lockout list for `N` minutes.
3. Otherwise:
   1. Count the number of unsuccessful authentication attempts in `K` minutes for this specific device token.
   2. If the number of unsuccessful attempts in `K` minutes is more than `M`, lock out all authentication attempts to this specific account from untrusted clients for `N` minutes.

#### Issue new device token

1. Issue a device token using one of the following strategies:
   1. [Generate a random token and save it in a database](#random-token).
   2. [Use an HMAC-based token](#hmac-based-token).
   3. [Use a JWT](#json-web-token-jwt).
2. Set an expiration date for a device token:
   1. [Random token](#random-token): add an expiration date to a database.
   2. [HMAC-based token](#hmac-based-token): add an expiration date to a message for signing.
   3. [JWT](#json-web-token-jwt): add an expiration date to a payload.
3. Bind a device token with a specific user:
   1. [Random token](#random-token): connection with a user by user ID in a database.
   2. [HMAC-based token](#hmac-based-token): add a used ID to a message for signing.
   3. [JWT](#json-web-token-jwt): add a user ID to a payload.

#### Device token validation

If one of the following checks fails the **entire** validation fails:

1. Validate that a device token is valid:
   1. [Random token](#random-token): there is a record in a database with a device token value.
   2. [HMAC-based token](#hmac-based-token): the signature is valid.
   3. [JWT](#json-web-token-jwt): the signature is valid.
2. Validate that a device token has not expired:
   1. [Random token](#random-token): check out a record in a database.
   2. [HMAC-based token](#hmac-based-token): check out a signed message.
   3. [JWT](#json-web-token-jwt): check out a payload.
3. Validate that a device token corresponds to an account in which the authentication is attempted:
   1. [Random token](#random-token): check out a record in a database.
   2. [HMAC-based token](#hmac-based-token): check out a signed message.
   3. [JWT](#json-web-token-jwt): check out a payload.

## General

<div align="left"><img src="https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-b41291c03c4de901e1f0faa235c5ad68838b2947%2Ftype-base-icon.svg?alt=media" alt=""></div>

* If a client is a browser, store a device token in the `ultimate` cookie, see the [Cookie Security](https://0xn3va.gitbook.io/application-security-handbook/web-application/cookie-security) page.
* Set expiration date \~ 6 months.
* Bind a device token with a specific account.

## Random token

<div align="left"><img src="https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-b41291c03c4de901e1f0faa235c5ad68838b2947%2Ftype-base-icon.svg?alt=media" alt=""></div>

* Use a random token as a device token.
* Use a cryptographically strong generator to generate a device token, see the [Cryptography: Random Generators](https://0xn3va.gitbook.io/application-security-handbook/web-application/cryptography/random-generators) page.
* Use random tokens of length 16+ bytes.

## HMAC-based token

<div align="left"><img src="https://1795604890-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaH8j4W1MtabOUlUc8Trn%2Fuploads%2Fgit-blob-b41291c03c4de901e1f0faa235c5ad68838b2947%2Ftype-base-icon.svg?alt=media" alt=""></div>

* Use a message signed with HMAC as a device token. The message must contain at least:
  * User ID or username.
  * Expiration date.
  * Nonce.

<details>

<summary>Example</summary>

```
BASE64(USER_ID + EXPIRATION_DATE + NONCE + HMAC(USER_ID + EXPIRATION_DATE + NONCE, SECRET_KEY))
```

</details>

* Generate a unique nonce for each token.
* Use cryptographically strong generators to generate a nonce, see the [Cryptography: Random Generators](https://0xn3va.gitbook.io/application-security-handbook/web-application/cryptography/random-generators) page.
* Comply with the requirements from the [Cryptography: Hash-based Message Authentication Code (HMAC)](https://0xn3va.gitbook.io/application-security-handbook/web-application/cryptography/hash-based-message-authentication-code-hmac) page.

## JSON Web Token (JWT)

* Use a JSON Web Token (JWT) as a device token. The payload must contain at least:
  * User ID or username.
  * Expiration date.
  * Nonce.
* Generate a unique nonce for each token.
* Use cryptographically strong generators to generate a nonce, see the [Cryptography: Random Generators](https://0xn3va.gitbook.io/application-security-handbook/web-application/cryptography/random-generators) page.
* Comply with the requirements from the [JSON Web Token (JWT)](https://0xn3va.gitbook.io/application-security-handbook/web-application/json-web-token-jwt) page.

<details>

<summary>Example</summary>

```json
{
  "alg": "HS256",
  "typ": "JWT"
}
{
  "userid": 31337,
  "nonce": "GiOzXAwlZ17NsW4CkVV8MQXtiQN9cWiY",
  "exp": 1516239022
}
```

</details>

## References

* [OWASP: Slow Down Online Guessing Attacks with Device Cookies](https://owasp.org/www-community/Slow_Down_Online_Guessing_Attacks_with_Device_Cookies)
