Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing OAuth Token in Python Library

I have a Python service which imports a library that talks to the PayPal API. There is a config file that is passed into the library __init__() which contains the PayPal API username and password.

Calling the PayPal API token endpoint with the username and password will return a token used to authenticate during the pay call. However, this token lasts for 90 minutes and should be reused.

There are multiple instances of this service running on different servers and they need to all share this one secret token.

What would the best way of storing this 9 minute token be?

like image 580
user7692855 Avatar asked Mar 17 '19 22:03

user7692855


People also ask

Where should OAuth tokens be stored?

Auth0 recommends storing tokens in browser memory as the most secure option. Using Web Workers to handle the transmission and storage of tokens is the best way to protect the tokens, as Web Workers run in a separate global scope than the rest of the application.

Where are tokens stored python?

The most common method of storing tokens and secrets is to store them in a . env file. This is a file which is used by the python-dotenv package to load environment variables from. This is the most common way of storing tokens and secrets in almost all programming projects.

How do you store authentication tokens?

To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server. It's never accessible (both for reading or writing) from JavaScript running in the browser.


2 Answers

While you could persist this in a database, since it's only valid for 90 minutes, you might consider using an in-memory data store like Redis. It's very simple to set up and there are various Python clients available.

Redis in particular supports expiration time when setting a value, so you can make sure it'll only be kept for a set amount of time. Of course, you should still have exception handling in place in case for some reason the key is invalidated early.

While this may introduce a software dependency if you're not already using a key-value store, it's not clear from your question how this library is intended to be used and thus whether this is an issue.

If installing other software is not an option, you could use a temporary file. However, because Python's tempfile doesn't seem to support directly setting a temporary file's name, you might have to handle file management manually. For example:

import os
import time
import tempfile


# 90 minutes in seconds. Setting this a little lower would 
# probably be better to account for network latency.
MAX_AGE = 90 * 60
# /tmp/libname/ needs to exist for this to work; creating it
# if necessary shouldn't give you much trouble.
TOKEN_PATH = os.path.join(
    tempfile.gettempdir(), 
    'libname', 
    'paypal.token',
)


def get_paypal_token():
    token = None

    if os.path.isfile(TOKEN_PATH):
        token_age = time.time() - os.path.getmtime(TOKEN_PATH)

        if token_age < MAX_AGE:
            with open(TOKEN_PATH, 'r') as infile:
                # You might consider a test API call to establish token validity here.
                token = infile.read()

    if not token:
        # Get a token from the PayPal API and write it to TOKEN_PATH.
        token = 'dummy'

        with open(TOKEN_PATH, 'w') as outfile:
            outfile.write(token)

    return token

Depending on the environment, you would probably want to look into restricting permissions on this temp file. Regardless of how you persist the token, though, this code should be a useful example. I wouldn't be thrilled about sticking something like this on the file system, but if you already have the PayPal credentials used to request a token on disk, writing the token to temporary storage probably won't be a big deal.

like image 75
kungphu Avatar answered Oct 25 '22 08:10

kungphu


You could store the token as a system variable.

import os

# Store token
os.environ['PAYPAL_API_TOKEN'] = <...>

# Retrieve token
token = os.environ['PAYPAL_API_TOKEN']

Be aware of the security implications though: Other processes could read the token.

like image 22
Elias Strehle Avatar answered Oct 25 '22 09:10

Elias Strehle