Security design for token authenticates
2023-10-01 / modified at 2024-02-13 / 1.4k words / 8 mins

This article describes how to choose appreciated tokens in security design.

This article is for security demonstrating purposes only, and the author is not a full-time security researcher. API Tokens are not designing for critical environment such as TLS-breaking eavesdropper or compromised ROOT passwords. Any examples provided here are without warranty.

Alternatives

If we lack confidence in the security design for a particular job or project, leveraging third-party SaaS services such as Auth0, Hashicorp Vault, or cloud KMS can provide an effective solution. By utilizing these services, we can alleviate concerns regarding security design and focus on other critical aspects of our work, such as developing business-related applications or systems.

Threat Modeling

It’s critical to follow threat modeling before designing tokens in the system, which consists of confidentiality, integrity, availability, accountability, and authentication. Here are some key processes. Have a look at

Security premises of token design

Internal Design

Have a look inside the application binary

  • User case diagrams such as login, authentication, or forward-auth.
  • Data flow diagrams (DFDs) inside the application. Analyse high-value asserts that the hacker might be interested in.
  • Vulnerabilities in third-party libraries embedded in the application.
  • ACL, scops, rate limits, and expiration.

External Dependencies

Enumerates the potential risks precaution against external components being compromised.

  • Data flow diagrams (DFDs) that are external to the application, such as hard disks, S3, database, hashicorp vault, KMS services, and even storage chips.

  • Deployment diagrams including VPC, WAF, Linux, containers, Kubernetes, or physical machines. The underlying components should be hardened periodically.

  • Http router configurations for Nginx, traefik, or consul.

Types of tokens

Designs for tokens can be classified via authenticates flow.

User-to-server token

User-to-server token is used for users speaking to a machine such as a news iOS App fetches data from the server via tokens owned by the current user.

TypeDescriptionInputScopesExpiration
PasswordThe password held by users.User-inputFor login onlyOn-demand
SessionRandomly generated after user login.Server-GeneratedFullHours
Access TokenImpersonates users for API calls.Server-GeneratedOn-demandOn-demand

Sessions can be implemented with a custom header name such as x-authn-token or custom cookie names. For instance, SpringBoot will use SessionResolver to generate and resolve sessions from HTTP requests sent from users.

It’s considered unsafe to store plain tokens in a phone or web page, which can be unrevealed with MITM, self-signed HTTPS certs, or by a debugger/disassembler.

Server-to-server

Server-to-server token is a static token used for servers speaking directly to another server such as a database password, LDAP password, or AKSK in S3 Storage.

It’s considered more important than the user-side tokens. SRE experts will secure the deployment behind a VPC & WAF and must encrypt, rotate, and monitor the tokens periodically.

In the recent Aliyun Cloud global service failure, it was allegedly a single point of AKSK authentication failure that caused the the S3 storage failed to connect.

OAuth Token

OAuth Token is primarily used in SaaS services such as a hotel reservation website that connects customers, a hotel reservation server, and a payment SaaS service together. Once customers agree on the OAuth authentication, the hotel can charge the bill without further confirmation.

Client-side storage security

Browser session

The best way is to use in-memory storage with ServerWorkers as a proxy to handle the transmission.

As an alternative, in-browser storage such as local storage, session storage, and cookies are okay as long as we minimize the attack surface (XSS/CSRF). Here are some tips

  • Enable subresource Integrity (SRI) that can check integrity from CDNs or local servers
  • Disable IFrame embedding with the X-Frame-Options header.
  • Restrict contents via the header Content-Security-Policy to enumerate trusting resources.
  • Sanitize HTML before rendering the page.

In-App session

Besides in-memory storage, leveraging key storage to a hardware-based key manager such as Keychain is also considered secure.

As for the transmission, consider enabling HTTPS & SSL Pinning to prevent MITM.

Server-side storage security

There are a few approaches including KMS, file, or database to store secrets. The simplest way is to store secrets in a database.

Before all

  • The hard disk and database should be encrypted transparently.
  • The connections between applications (such as a SpringBoot application) and databases should be encrypted with TLS.

Plaintext storage

It’s not allowed to store secrects in plaintext format in the database duo to it’s vulnerable to data leak when

  • The database is compromised or the hard disk is stolen.
  • The employee is malicious
  • Junior programmers might print select * from token in the log – I’ve seen the code a lot.

Password derivation

The key derivations function(PDF), aka slow hashed/hierarchical keys, are used for generating irreversible passwords, such as PBKDF2, scrypt and bcrypt.

Usecase

In a user’s registration process, the function is used for generating the hash text that will be stored in the database. The hashed key derived from human inputs can strengthen the randomness and length as user-provided passwords (such as 6 digits of PIN code) are vulnerable to dictionary attacks.

Additionally, as a password derivation, it can generate one or more secrets.

  • 1->1: In PBEWITHHMACSHA512ANDAES_256 encryption, it works as an encryption key (DEK) for AES GCM encryption.
  • 2->1: In Two Secret Key Derivation (2SKD) , it involves in combining a new password from two passwords.
  • 1->2: The hand input password will be splitted into two parts, one for login, another for password synchronization. See details
Should I provide an additional encryption layer for PBKDF2?

There is a scenario if someone has the database terminal in hand, he can bypass the authentication via privilege escalation such as

  • Replacing the existing PBKDF2 hash in the database with a pre-calculated hash. It’s similar to replacing the password of a root user by modifying the file /etc/passwd.
  • Grant a user access by modifying relationships between users and tokens, such as updating the references of the user_token_id to a pre-generated token that you known.

To mitigate potential risks, one approach involves adding an extra layer, such as 2SKD or nested encryption, to encrypt sensitive columns representing user_token_id as well as encrypted tokens. However, implementing such protections may be unnecessary since securing an extra encryption key requires exclusive and critical infrastructure beyond current needs. Furthermore, a compromised database could still expose digital asserts directly.

Should I use client-side hash for a password?

Client-side hash just replaces the password with hash(password, salt, iteration), for backend servers they are considered the same, hackers can still impersonate users with the hashed password.

You needn’t to create your own HTTPS protocol. Hashing is only designed for preventing brute-force attacks, which don’t resolve MITM nor replay attacks issues.

Nonetheless, It’s okay to create a hash at a client level if you fail to persuade your leaders.

Symmetric encryption

Algorithm: Such as AESGCM256 with 96 nouces(IV).

Storage: The encrypted text can be directly stored in the database. However, the symmetric key requires isolated storage separating from the database and codebase.

Asymmetric encryption

Asymmetric encryption is primarily utilized for secure exchange of information, as examplified by SSL, saved logins, and license key generation. Tokens storage are rarely used duo to the slow performance.

Algorithm: Such as RSA4046

Storage: Same as above.

How to log requests safely?

See my another blog.

Where to store reversible encryption key?

Technically it’s a problem of chained trust storage, even if using cloud KMS or Hardware KMS as underlying storage, you have to provide at least one reversible key (aka master key, pin code, phrases, alias or seal key) inside the application for cryptography operations. Once the key is breached, the data may be potentially exposed.

As an application developer, leveraging third-party storage rather than self-implementation is the best known method.

  • Never hard-code secrets in the source code, it can be considered as a backdoor by customers.
  • Segregate the roles of the reversible key holders and the application developers.
  • Deploy applications on PaaS orchestrators, as exemplified kubernetes or nomad, which both can inject secrets into files or environment variables within isolated namespaces via chroot jail.
  • Use JCA Provider in Java, which uses PKCS internally.

As we have talked above, we can’t omit all threats from skilled attackers but make it more difficult to be compromised.