Louis Login Backend offers a comprehensive workflow that ensures a seamless Single Sign-On (SSO) experience. The system operates through a series of steps starting from the client application check to email verification and eventual redirection after verification.
For a detailed step-by-step breakdown and to understand how the API endpoints function within this process, please refer to the WORKFLOW documentation.
Note: If you're using a
devcontainer
, the steps involving virtual environments are not necessary. However, for developers not usingdevcontainer
, the virtual environment setup remains relevant.
Follow the instructions below to set up a Quart application in your environment:
Before you start, ensure you have pip
installed. Check its version with:
pip --version
It's a good practice to keep your tools updated. Run the following command:
python -m pip install --upgrade pip setuptools virtualenv
To create an isolated environment for your project, set up a virtual environment named venv
(or another name you prefer):
python -m venv venv
Before installing any packages, activate your virtual environment:
On Windows:
venv\Scripts\activate
Ensure you have a requirements.txt
file in your project directory. Install all dependencies with:
pip install -r requirements.txt
Now, you can proceed with running your Quart application or any other tasks. Always ensure that your virtual environment is activated when working on the project to maintain dependencies separately from your global Python environment.
To run the Quart application correctly, it requires some environment variables to be set. Follow the steps below to set them up:
- Navigate to the root directory of the project and create a new file named
.env
. - Open this
.env
file using your preferred text editor.
Now, define each of the following variables:
- Description: List of origins allowed for cross-origin requests (CORS).
- Format: Comma-separated list of origins.
- Example:
MEMBRANE_CORS_ALLOWED_ORIGINS=http://localhost:3000
- Reference: https://pypi.org/project/quart-cors/
- Description: Redirect URL leading users to the login frontend.
- Example:
MEMBRANE_FRONTEND=http://localhost:3000
- Description: The secret key used for creating encrypted tokens.
- Example:
MEMBRANE_SECRET_KEY=your_secret_key
- Reference: https://flask.palletsprojects.com/en/latest/config/#builtin-configuration-values
- Description: Path to the directory where client public keys are stored for JWT validation.
- Example:
MEMBRANE_CLIENT_PUBLIC_KEYS_DIRECTORY=keys/
- Description: Path to the server's private key file used for creating and signing tokens.
- Example:
MEMBRANE_SERVER_PRIVATE_KEY=keys/server_private_key.pem
- Description: Path to the server's public key file used for verifying tokens.
- Example:
MEMBRANE_SERVER_PUBLIC_KEY=keys/server_public_key.pem
- Description: Connection string for the Azure communication service.
- Example:
MEMBRANE_COMM_CONNECTION_STRING=your_azure_communication_service_connection_string
- Reference: https://learn.microsoft.com/en-us/python/api/azure-communication-email/azure.communication.email.emailclient?view=azure-python#azure-communication-email-emailclient-from-connection-string
- Description: Email address that will send emails.
- Example:
MEMBRANE_SENDER_EMAIL=DoNotReply@your_domain.com
- Reference: https://learn.microsoft.com/en-us/python/api/overview/azure/communication-email-readme?view=azure-python#send-an-email-message
- Description: Expiration time (in seconds) for the JWT access token.
- Example:
MEMBRANE_JWT_ACCESS_TOKEN_EXPIRE_SECONDS=300
- Description: General JWT expiration time in seconds.
- Example:
MEMBRANE_JWT_EXPIRE_SECONDS=300
- Description: Duration (in seconds) after which the session will expire.
- Example:
MEMBRANE_SESSION_LIFETIME_SECONDS=300
- Reference https://flask-session.readthedocs.io/en/latest/config.html
- Description: Indicates if the session cookie should be secure.
- Example:
MEMBRANE_SESSION_COOKIE_SECURE=true
- Reference https://flask-session.readthedocs.io/en/latest/config.html
- Description: Specifies the storage for session data. Options: 'filesystem', 'redis', 'memcached', etc.
- Example:
MEMBRANE_SESSION_TYPE=null
- Reference https://flask-session.readthedocs.io/en/latest/config.html
- Description: List of revoked tokens or sessions for security.
- Format: Comma-separated list of tokens.
- Example:
MEMBRANE_TOKEN_BLACKLIST=
- Description: Field name for the application ID in JWT.
- Example:
MEMBRANE_APP_ID_FIELD=app_id
- Description: Field name for data in JWT.
- Example:
MEMBRANE_DATA_FIELD=data
- Description: Field name for redirect URL in JWT.
- Example:
MEMBRANE_REDIRECT_URL_FIELD=redirect_url
- Description: Algorithm used for encoding JWT.
- Example:
MEMBRANE_ENCODE_ALGORITHM=RS256
- Reference: https://pyjwt.readthedocs.io/en/latest/algorithms.html#digital-signature-algorithms
- Description: Regex for the list of email domains accepted by the application.
- Example:
MEMBRANE_ALLOWED_EMAIL_DOMAINS_PATTERN=^[a-zA-Z0-9._+]+@(?:gc\.ca|canada\.ca|inspection\.gc\.ca)$
- Description: Subject line for outgoing emails.
- Example:
MEMBRANE_EMAIL_SUBJECT=Please Verify Your Email Address
- Reference: https://learn.microsoft.com/en-us/python/api/overview/azure/communication-email-readme?view=azure-python#send-an-email-message
- Description: HTML template for outgoing emails.
- Example:
MEMBRANE_EMAIL_SEND_HTML_TEMPLATE=<html><h1>{}</h1></html>
- Reference: https://learn.microsoft.com/en-us/python/api/overview/azure/communication-email-readme?view=azure-python#send-an-email-message
- Description: Time in seconds to wait for email sending.
- Example:
MEMBRANE_EMAIL_SEND_POLLER_WAIT_TIME=2
- Reference: https://learn.microsoft.com/en-us/python/api/azure-core/azure.core.polling.lropoller?view=azure-python#azure-core-polling-lropoller-wait
- Description: Time in seconds before email sending times out.
- Example:
MEMBRANE_EMAIL_SEND_TIMEOUT_SECONDS=30
- Description: Message when an email is successfully sent.
- Example:
MEMBRANE_EMAIL_SEND_SUCCESS=Valid email address, Email sent with JWT link
- Description: Field name for generic 500 errors.
- Example:
MEMBRANE_GENERIC_500_ERROR_FIELD=error
- Description: Generic error message for 500 status code.
- Example:
MEMBRANE_GENERIC_500_ERROR=An unexpected error occurred. Please try again later.
- Description: Specifies the logging level for the application.
- Example:
MEMBRANE_LOGGING_LEVEL=DEBUG
- Reference: https://docs.python.org/3/library/logging.html#logging-levels
- Description: Format for the log messages.
- Example:
MEMBRANE_LOGGING_FORMAT=[%(asctime)s] [%(levelname)s] [%(filename)s:%(lineno)d:%(funcName)s] - %(message)s
- Reference: https://docs.python.org/3/library/logging.html#logrecord-attributes
- Description: Health check message for the server.
- Example:
MEMBRANE_HEALTH_MESSAGE=ok
- Description: Number of hypercorn worker processes for the application.
- Example:
MEMBRANE_WORKERS=4
- Reference: https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.html
- Description: Hypercorn keep-alive timeout in seconds for the server.
- Example:
MEMBRANE_KEEP_ALIVE=5
- Reference: https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.html
Once you have defined all these variables, save and close the .env
file. The Quart application will now use these environment variable values when it runs.
With your virtual environment activated, start the main app.py
:
quart run
Open a separate terminal or command prompt. Make sure the virtual environment is activated and then run the testapp1.py
to simulate a client application:
quart --app testapp1.py run --port=4000
Ensure that the Membrane Frontend React application is running, ideally on localhost
. This application will serve as the frontend interface for users to provide their email addresses to Membrane Backend.
You can now interact with both the main Quart application and the client simulator to validate the entire authentication flow.
- OpenSSL installed on your machine (in WSL).
- An Azure Communication Service connection string
- An Azure MailFrom email address connected to the Azure Communication Service resource
-
Navigate to the project's root directory.
-
Run the initialization script:
./init_project.sh <your-test-app-id>
This script will:
- Generate keys in a
keys
folder for both the server and the specified app id. - Copy
.env.template
to.env
. - Copy
.env.tests.template
to.env.tests
.
- Generate keys in a
- If the keys or environment files already exist, the script will overwrite them.
- Logs are written to
init.log
.
-
Open the
.env
file generated in the project's root directory. -
Generate a secret key:
openssl rand -hex 32
-
Populate the following variables in the
.env
file. Example for tests and dev:# Mandatory MEMBRANE_CORS_ALLOWED_ORIGINS=http://localhost:3000 MEMBRANE_FRONTEND=http://localhost:3000 MEMBRANE_SECRET_KEY=your_secret_key MEMBRANE_CLIENT_PUBLIC_KEYS_DIRECTORY=keys/ MEMBRANE_SERVER_PRIVATE_KEY=keys/server_private_key.pem MEMBRANE_SERVER_PUBLIC_KEY=keys/server_public_key.pem MEMBRANE_COMM_CONNECTION_STRING=your_azure_communication_service_connection_string MEMBRANE_SENDER_EMAIL=DoNotReply@your_domain.com # Optional # MEMBRANE_JWT_ACCESS_TOKEN_EXPIRE_SECONDS= # MEMBRANE_JWT_EXPIRE_SECONDS= # MEMBRANE_SESSION_LIFETIME_SECONDS= # MEMBRANE_SESSION_COOKIE_SECURE= # MEMBRANE_SESSION_TYPE= # MEMBRANE_TOKEN_BLACKLIST= # MEMBRANE_APP_ID_FIELD= # MEMBRANE_DATA_FIELD= # MEMBRANE_REDIRECT_URL_FIELD= # MEMBRANE_ENCODE_ALGORITHM= # MEMBRANE_ALLOWED_EMAIL_DOMAINS_PATTERN= # MEMBRANE_EMAIL_SUBJECT= # MEMBRANE_EMAIL_SEND_SUCCESS= # MEMBRANE_EMAIL_SEND_POLLER_WAIT_TIME= # MEMBRANE_EMAIL_SEND_TIMEOUT_SECONDS= # MEMBRANE_EMAIL_SEND_HTML_TEMPLATE= # MEMBRANE_GENERIC_500_ERROR_FIELD= # MEMBRANE_GENERIC_500_ERROR= # MEMBRANE_LOGGING_LEVEL= # MEMBRANE_LOGGING_FORMAT= # MEMBRANE_HEALTH_MESSAGE= # MEMBRANE_WORKERS= # MEMBRANE_KEEP_ALIVE=
-
Build the Docker image:
docker build -t your_app_name .
-
Set your desired port number:
export PORT=<your_port_here>
-
Run the Docker container:
docker run -v $(pwd)/keys:/app/keys -p $PORT:$PORT -e PORT=$PORT --env-file .env your_app_name