Developer¶
Before Committing¶
Before you push your code to the remote repository, install commitizen.
Then, install the pre-commit hooks using:
Now you can add your changes with git add <filename.py> to stage them for committing.
When ready to push the commit, run:
Respository Structure¶
The chime-frb-api has four major distinctive components:
- core manages the authentication and the HTTP query to the backend.
- modules are individual sets of API calls, generally mapping to a sanic blueprint.
- backends are a collection of modules. They offer a singular object with all services availaible through a backend.
- tests can be both for a backend or an individual module.
JWT Tokens¶
Access Tokens¶
Simply put, an ACCESS_TOKEN is a string with a bunch of characters that are used as credentials, to grant access to resources. More generally they are JSON Web Tokens.
ACCESS_TOKEN is
- Just a
JWT! - Disposable, i.e. they can be generated on-demand and in unlimited quantities.
- Valid for only a short period, ~30 minutes.
- Unrevokable, i.e. if you have an access token, and it is valid - the CHIME/FRB backend will process your request
Example
On closer inspection, ACCESS_TOKEN consists of three parts separated by a period:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9eyJ1c2VyX2lkIjoiZGVidWciLCJleHAiOjE1NzQ0NjE2ODcsImlhdCI6MTU3NDQ1OTg4N30wHVjUpZRINR0wLaxhLNOPMX3rJbVaicI4J-vNkJOGDM
In order of appearance, these parts are the Header, Payload, and the Signature.
Header
Contains information on how the JWT was encoded and is used to decode the payload.
Payload
contains key/value pairs of information. Each one of these is called a claim.
In this example, there are four claims passed through the JWT:
user_id- Name of the user who the token was issued toexp- ctime at which this token will expireiat- ctime at which the token was issued atiss- Issuer of the token, i.e.frb-master
In the future, backends will support more complex claims as well, e.g. scopes, rate or audiences for requests.
Signature
Contains some hot mess of characters that can only be decoded by the server which issued the token. The server uses a secret passphrase and the payload to create the signature, thus ensuring that the payload cannot be maliciously altered.
Refresh Tokens¶
Refresh tokens are simply an encrypted alphanumeric keys, generated by the CHIME/FRB backends. Every time an ACCESS_TOKEN expires, the client needs to re-authenticate with the username/password to create a new ACCESS_TOKEN. But requiring the user to insert username/password each time an ACCESS_TOKEN expires or asking them to save credentials in code or as environment variables, is neither safe or convenient. REFRESH_TOKEN solve this problem.
REFRESH_TOKEN is
- NOT a
JWT, rather its just a universally unique identifiers - Stored by the backend on a per
userbasis - Used to generate a new
ACCESS_TOKENwhen sent along with active or expiredACCESS_TOKEN.
Note
When you generate a new ACCESS_TOKEN using your credentials, it invalidates the currently issued tokens.
Generate Tokens¶
Generating a new set tokens requires CHIME credentials. When successfull, the backend responds with an ACCESS_TOKEN and REFRESH_TOKEN. Here is a code agnostic example,
Request
Response
Validate Tokens¶
REFRESH_TOKEN and ACCESS_TOKEN work together to provide a friendly, yet secure and authentication environment. To check, whether an ACCESS_TOKEN is valid, you can use the verify endpoint,
Request
Response
Refresh Tokens¶
In order acquire a new ACCESS_TOKEN given an existing REFRESH_TOKEN and ACCESS_TOKEN you can use the refresh endpoint,
Request
Use Tokens¶
To authenticate, all you need to do is attach the authorization header to a HTTP Request
Request
Response
Example¶
Complete example in Python, using the requests package.
Code
import requests
base_url = "https://frb.chimenet.ca/frb-master"
payload = {"username": "<USERNAME>", "password": "<PASSWORD>"}
# Acquire tokens from frb-master
response = requests.post(url=base_url + "/auth", json=payload)
response.raise_for_status()
tokens = response.json()
access_token = response.json().get("access_token")
refresh_token = response.json().get("refresh_token")
# Verify access token
authorization = {"Authorization": access_token}
response = requests.get(url=base_url + "/auth/verify", headers=authorization)
response.raise_for_status()
print(response.json())
# Refresh access_token
refresh_payload = {"refresh_token": refresh_token}
response = requests.post(
url=base_url + "/auth/refresh", headers=authorization, json=refresh_payload
)
response.raise_for_status
access_token = response.json().get("access_token")