The backend for the para mobile app
Key parts:
app/expenses_api/views.py
- the endpoints which the clients of this API use. Seeapp/expenses_api/README.md
for documentation of the APIapp/db_facade/facade.py
- singleton facade. Interface to the underlying db (currently DynamoDB)app/auth/firebase.py
- given a id tokens, extract the user uid from it, on each request to protected endpoints
- Install pipenv
$ pipenv install
$ pipenv shell
- make an
.env_dev
file at the root of the repo with the following structure
APP_STAGE=development
SECRET_KEY=not-that-secret
SHORT_CIRCUIT_FIREBASE=0 # see the Note below
FIREBASE_CONFIG_JSON_BASE64=<firebase admin sdk config, base64-ed> # see the note below
ROLLBAR_CLIENT_TOKEN=<rollbar client token here> # required only for staging and production APP_STAGE
- Set the following environmental variables
DOT_ENV_FILE=.env_dev
FLASK_APP=manage.py # the "new" way flask discovers apps
FLASK_DEBUG=0 # otherwise python signals don't work
- To run the API (see below the Note for PyCharm users)
$ flask run --host=0.0.0.0
Client of this API authenticate by sending the x-firebase-auth-token
header.
The header's content is a firebase id token, generated client-side (by a firebase client sdk).
The app.auth.FirebaseTokenValidator.validate_id_token_and_get_uid()
is called on each request to protected routes and
uses the header to extract the user uid
from the id token
. This way it's ensured that the request comes from an authenticated user of the correct firebase app.
To set the value of FIREBASE_CONFIG_JSON_BASE64
, you need to get the admin sdk credentials file of a valid Firebase project.
It should be the same Firease project, used for the para mobile app, if the instance
of the API will configured as the backend of a para mobile app.
base64 the contents of the credentials file and use the
result as a value for the environmental variable.
This way, this API can decode id tokens
sent from the mobile app
During the development of the api or if you don't want to create Firebase project, it can be handy to skip the process of extraction of a firebase user uid from an id token and just send an user uid directly.
I.e., setting FIREBASE_CONFIG_JSON_BASE64
can be omitted if:
- the
SHORT_CIRCUIT_FIREBASE
is set to'1'
- the
APP_STAGE
isdevelopment
/testing
- the
x-firebase-auth-token
header contains a valid firebaseuser uid
(and not a firebaseid token
).
This way Firebase user uid extraction is "short-circuited" in the sense that the contents of the x-firebase-auth-token
header won't be treated as a
id token and validate_id_token_and_get_uid() will be
effectively be the identity function. Thus, when short-circuited, the header can contain just an user uid.
When running via PyCharm and assuming that pipenv is used, you need to select the correct python interpreter.
$ pipenv shell
(para_api-tKuPD0ya) $ which python
/home/georgi/.local/share/virtualenvs/para_api-tKuPD0ya/bin/python
unittest
is used for the tests.
To run them via PyCharm
- You need the '.env_test' file placed in the repo root with
APP_STAGE=testing
SECRET_KEY=not-that-secret
DB_PING_LAZY=True
- Create a new Python test run configuration with the
/tests
as the Path target and the root of the repo as a working directory - Run the configuration
How to generate a valid firebase id token without using the para mobile app
- Use the firebase-sample, set up a firebase project (
firebase use
). $ cd auth && firebase serve
- use the server webpage to login - the returned object has
accessToken
, which can be used as the value of thex-firebase-auth-token
header when making requests to thepara_api
from curl/postman/etc.