0

I'm writing a RESTful API for a website I'm building and it has methods that use user permissions. For example, I have a method called removeResource(resource_id: int, user: string). The larger pipeline is the user logs in which called an API method that checks their username and password, then if their password is correct returns an encrypted string with their user id. The encryption and decryption is done with Fernet symmetric encryption (https://cryptography.io/en/latest/fernet.html) on the API side. Users have permissions set for what they're allowed to do.

I'm worried about the case when someone tries to make an API call they don't have permission to, so I'm also sending the encrypted user id with every API call that requires permissions. Then I'm decrypting their id on the API side and checking the user's permissions from a database to decide if they actually have permissions for the API they're trying to make.

Is this a safe way to do authentication and be sure a user can't spoof a different user id in API calls since they won't be able to encrypt to a different user id without the key for Fernet that's saved on the API side?

2 Answers 2

1

Many types of encryption don't provide integrity guarantees. However, Fernet appears to:

encrypt() Encrypts data passed. The result of this encryption is known as a “Fernet token” and has strong privacy and authenticity guarantees.

Parameters: data (bytes) – The message you would like to encrypt. Returns bytes: A secure message that cannot be read or altered without the key. It is URL-safe base64-encoded. This is referred to as a “Fernet token”.

So as long as the secret key remains secret, you are good.

1

Your approach generally seems ok to me; it is conceptually similar to the well-used approach of issuing an encrypted JWT session token (aka "JWE") which contains all the user's metadata, but in encrypted so the user cannot read it.

One thing to consider is session fixation: once you issue one of these encrypted tokens, does that mean the user can continue to make API calls forever, or do you have a way to expire or invalidate the token and force the user to log in again? Common approaches are to put an expiry timestamp inside the token (typically ~15 mins - several hours after it was issued), or tie the token to a login session for example by embedding the sessionID inside the encrypted token and only accept the token for as long as that session is active.

I see in your fernet link that it stores the generation time in the ciphertext, and that its decrypt() has a time-to-live param, so I guess putting an expiry time on the tokens is trivial to do with fernet :)

 decrypt(token, ttl=None)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .