Influxdb: Support for username:password authentication tokens for v1 APIs

Created on 15 Oct 2020  ·  5Comments  ·  Source: influxdata/influxdb

What

When a user upgrades from InfluxDB 1.x to InfluxDB 2.x, we would like to avoid requiring the operator to update the configuration of their clients. Therefore, it is a requirement that InfluxDB 2.x can authenticate v1 requests using BASIC auth with existing username and password tokens. The 1.x to 2.x upgrade dictates that users will be migrated to a single admin user and will be issued tokens with fine-grained permissions. Importantly, these V2 tokens must be derived from username and password.

To summarize,

  • an InfluxDB 1.x client will continue to issue requests to a v1 compatible HTTP API;
  • provide existing username and password credentials via an Authorization header using the BASIC schema or via the u (username) and p (password) query parameters; and
  • the InfluxDB 2.x server must authenticate the request using those credentials.

How

  1. Server receives request with username and password credentials specified as an Authorization header or via the u and p query parameters.
  2. Server combines username and password as username:password and passed the value through a 1-way cryptographically secure hash function
  3. Server performs an existing lookup of this token using a new service which manages V1 tokens
  4. If found, processing of the request continues identically to the behavior of using existing tokens

Generating username:password tokens

Create a V1 authorizations service and API

  • Create a V1 authorizations service API to permit supplying a token key. This key would be username:password
  • When this key is provided, it must be passed through a 1-way cryptographically secure hashing function before being stored

HTTP API:

  • V1 tokens can be managed via the /authorizations API

Create influx v1 auth command

Create an v1 auth subcommand to create, list and delete V1 authorization tokens using the private HTTP API

For the 1.x -> 2.x upgrade, the authentication token key will be formatted as username:password with a description set to the username.

Authorizing a V1 request

  1. A HTTP request to /write or /query will provide a username and password via a BASIC authorization header or the u and p query parameters
  2. username:password will be passed through the matching cryptographically secure hash function, such as SHA256
  3. Resulting token will be used as a lookup key in the V1Authorizations service:
are2.x epic teacompute

Most helpful comment

Seems ok, but I'd like to have other people take a look to see if they find any issue with the approach. I'm not close enough to this code to be able to validate it.

All 5 comments

Seems ok, but I'd like to have other people take a look to see if they find any issue with the approach. I'm not close enough to this code to be able to validate it.

👍 The primary goal of this proposal is to

  • provide a solution for GA without pushing the date;
  • avoid widespread changes to the existing system; and
  • not introduce new vulnerabilities to existing code.

By hashing the passwords with sha256 do you mean salt + hash the passwords? A sha256 by itself is a message digest and needs to be used in combination with other mathematical operations for sensitive data storage. Without salting, all hashes of the same password will result in the same output. I also seem to recall that sha hashes are not good for passwords because they are considered fast hashes? For passwords you want something slow so that it takes more time to crack if someone gets the string. I am not sure if this is still the standard but the recommendation a few years ago was bcrypt. Here is an example with go https://medium.com/@jcox250/password-hash-salt-using-golang-b041dc94cb72. OWASP recommendations for secure password storage https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

saltedBytes := []byte(s)
hashedBytes, err := bcrypt.GenerateFromPassword(saltedBytes, bcrypt.DefaultCost)

I recommend against sha256 for password hashing, PBKDF2, bcrypt or scrypt should be used with a salt. The password library in influxdb1.x or kapacitor does this properly

@derektamsen and @docmerlin – I am absolutely in agreement that _passwords_ should not be SHA256 hashed; my previous implementations also use bcrypt. One can argue that authorization tokens are also passwords (and I agree, they are), but in most cases they should have limited permissions, particularly for this use case.

It may not be clear in the original issue, but this is a nuanced problem and these are not passwords stored in a User object users with full permissions.

This proposal is to be able to generate authorization tokens with a predetermined key. The primary use case will be creating tokens for 1.x users against the operator account with limited access to specific buckets in a 2.0 instance.

Specifically, this expands the existing authorizations system with a new, one-way token, which stores the tokens keyed only by their SHA256 hash and therefore they are not recoverable except by brute force. Two users using the same password will also not hash to the same value, as effectively the username: is a form of salt. If users are using strong passwords, these should be no less secure that generating tokens using cryptographically random bytes, except now we are only storing the hash.

Was this page helpful?
0 / 5 - 0 ratings