mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
237 lines
No EOL
9.6 KiB
Markdown
237 lines
No EOL
9.6 KiB
Markdown
# Backend
|
|
|
|
This is the api service that will supply the frontend with the insights that are driven by the machine
|
|
learning and data modelling services.
|
|
|
|
# Usage
|
|
|
|
## Prerequisites
|
|
|
|
Python 3.8+
|
|
Poetry for managing project dependencies and virtual environment.
|
|
|
|
## Installation and setup
|
|
|
|
1. Clone this directory and navigate into the project directory.
|
|
|
|
```commandline
|
|
git clone https://github.com/Hestia-Homes/Model.git
|
|
cd backend
|
|
```
|
|
|
|
2. For environment management, I'm using conda with pycharm which is a convenient setup for development
|
|
on a mac M1 however using tools such as poetry or pipenv is also fine.
|
|
|
|
For example, to install conda and create a virtual environment for this project, run the following commands:
|
|
|
|
```commandline
|
|
conda create -n backend python=3.10
|
|
conda activate backend
|
|
```
|
|
|
|
then enter the virtual environment and install the dependencies using conda.
|
|
|
|
```commandline
|
|
conda install --file requirements/base.txt
|
|
```
|
|
|
|
3. Duplicate .env.example and rename it to .env
|
|
|
|
```commandline
|
|
cp .env.example .env
|
|
```
|
|
|
|
4. Open .env and fill in the required environment variables.
|
|
|
|
## Running the Application
|
|
|
|
from within the application you can run with the following command:
|
|
|
|
```commandline
|
|
uvicorn app.main:app --reload
|
|
```
|
|
|
|
You application will be available at the designated url
|
|
|
|
## API Documentation
|
|
|
|
FastAPI automatically generates interactive API documentation for your application. To access the docs, start your
|
|
server and visit <yourlocalurl>/docs in your browser. Alternatively, you can go to
|
|
<yourlocalurl>/redoc to view the documentation in the ReDoc format.
|
|
|
|
## Testing
|
|
|
|
To run tests, run the following command from the root of the project directory:
|
|
|
|
```commandline
|
|
pytest
|
|
```
|
|
|
|
## Local Development
|
|
|
|
During local development, you may need to generate and use a dummy JWT to
|
|
test protected endpoints of the application.
|
|
|
|
# Generating a Dummy JWT
|
|
|
|
FastAPI provides a convenient way to generate a dummy JWT for testing.
|
|
To generate a dummy JWT, follow the steps below:
|
|
|
|
Make sure your application is running in a local environment.
|
|
The dummy token endpoint is only available in a local environment.
|
|
|
|
While your application is running, visit the /dummy-token endpoint using a tool
|
|
like curl or any HTTP client like Postman.
|
|
|
|
For instance, if your server is running locally on port 8000, you can use curl
|
|
to get a dummy token:
|
|
|
|
```commandline
|
|
curl http://localhost:8000/dummy-token
|
|
```
|
|
|
|
You will receive a response containing the dummy JWT
|
|
|
|
```json
|
|
{
|
|
"dummy_token": "<Your Dummy Token>"
|
|
}
|
|
```
|
|
|
|
### Using the Dummy JWT
|
|
|
|
Once you've obtained a dummy JWT, you can use it to make requests to
|
|
protected endpoints in your application:
|
|
|
|
1. When making a request, include an Authorization header with the value Bearer
|
|
<Your Dummy Token>. Replace <Your Dummy Token> with the token you
|
|
received from the /dummy-token endpoint.
|
|
|
|
2. Now you can make requests to the protected endpoints of the application.
|
|
|
|
Remember, the dummy JWT is meant for testing purposes only and should not be
|
|
used in production environments. The /dummy-token endpoint is not available
|
|
in non-local environments.
|
|
|
|
# Custom Domain Setup for AWS API Gateway
|
|
|
|
Before you deploy your Serverless application for the first time, you need to set up a custom domain for AWS API
|
|
Gateway. This is done using the sls create_domain command, which creates a custom domain in API Gateway that your
|
|
services can use.
|
|
|
|
To set up a custom domain, use the following command:
|
|
|
|
```bash
|
|
sls create_domain --stage dev --aws-profile DevAdmin --verbose
|
|
```
|
|
|
|
Replace dev with the name of the stage you're deploying to. This command only needs to be run once per custom domain,
|
|
and not every time you deploy your application. After running this command,
|
|
you can associate your AWS Lambda functions with this domain using the customDomain
|
|
configuration in your serverless.yml file.
|
|
|
|
This command requires the Serverless Domain Manager plugin,
|
|
so make sure you have it installed and properly configured in your serverless.yml file.
|
|
|
|
Please note that the process of creating and associating a custom domain can take up to 40 minutes.
|
|
Once the custom domain is created, it's immediately available for use in your Serverless applications.
|
|
|
|
Remember to replace DevAdmin with the profile that has appropriate permissions in your AWS account.
|
|
The `--verbose` flag is optional and is used to print detailed logs to the console.
|
|
|
|
# Creating a CNAME Record in Google Domains
|
|
|
|
After deploying the AWS Lambda function for the first time, you need to set up a
|
|
CNAME record in Google Domains to route traffic from your custom domain to
|
|
the CloudFront distribution created by API Gateway. This will re-route traffic from
|
|
your custom domain to the CloudFront distribution created by API Gateway, and
|
|
therefore to your lambda.
|
|
See [here](https://docs.aws.amazon.com/amplify/latest/userguide/to-add-a-custom-domain-managed-by-google-domains.html)
|
|
for AWS' documentation on this.
|
|
|
|
You can find the CloudFront
|
|
domain by going to the API Gateway console and clicking on Custom Domain Names.
|
|
|
|
Here are the steps to create a CNAME record:
|
|
|
|
1. Log in to Google Domains.
|
|
2. Select the name of your domain.
|
|
3. Open the menu, if it's not already open.
|
|
4. Click "DNS."
|
|
5. Scroll down to the "Custom resource records" section.
|
|
6. In the "Name" field, enter your subdomain (e.g., api if your API is available at api.example.com).
|
|
7. In the "Type" dropdown menu, select "CNAME."
|
|
8. In the "TTL" field, enter 1H to set it to 1 hour (or another suitable value).
|
|
9. In the "Data" field, enter the CloudFront domain that was created by API Gateway (you can find this in the API
|
|
Gateway console, under Custom Domain Names).
|
|
10. Click "Add."
|
|
|
|
This will direct any traffic from your custom domain to your AWS CloudFront
|
|
distribution. Please note that DNS changes might take some time (up to 24-48
|
|
hours in some cases) to propagate across the internet.
|
|
|
|
Also, please make sure that your CloudFront distribution is configured to
|
|
accept your custom domain as a valid domain name. In AWS API Gateway,
|
|
under Custom Domain Names, make sure that your custom domain is listed and
|
|
mapped to the appropriate API stage.
|
|
|
|
Remember to replace api and the CloudFront domain with your actual subdomain
|
|
and CloudFront domain.
|
|
|
|
### Thoughts for authenticating the frontend with the backend
|
|
|
|
To provide secure communication between your frontend Next.js application and your backend FastAPI service, you have
|
|
several options. Here are a few popular approaches:
|
|
|
|
- JWT (JSON Web Tokens): Since you're already using JWT for authentication in the frontend, you can also use this to
|
|
authenticate requests to your FastAPI backend. This involves passing the JWT token in the Authorization header of the
|
|
request from your frontend to the backend. Then, you can use a JWT decoder on the backend to validate the token. This
|
|
can be done using libraries such as PyJWT in your FastAPI application.
|
|
|
|
- API Keys: This is another common approach where you issue unique keys for each user/service that needs to access the
|
|
backend API. Each API call then includes this key in the request header. FastAPI can easily validate these keys. While
|
|
this approach is simpler than JWT, it provides less flexibility and security, as it doesn't allow for claims or
|
|
scopes.
|
|
|
|
- OAuth2.0: OAuth2 is a protocol that allows applications to request authorization to access resources on behalf of a
|
|
user. FastAPI has direct support for OAuth2 using the OAuth2PasswordBearer class, which can be used for issuing access
|
|
tokens to clients. Note that this could be overkill if you're already using JWT and the calls to your backend are not
|
|
on behalf of a user.
|
|
|
|
- Mutual TLS (mTLS): Mutual TLS is a method of two-way communication encryption where both client and server
|
|
authenticate each other. This can be more complex to setup but can provide an additional layer of security in some
|
|
scenarios.
|
|
|
|
No matter which method we choose, you should always serve your applications over HTTPS to ensure that all data,
|
|
including tokens or keys, is encrypted during transmission.
|
|
Also, ensure that you handle the JWT tokens carefully, especially if they are stored in the client's browser, as they
|
|
could be vulnerable to Cross-Site Scripting (XSS) or Cross-Site Request Forgery (CSRF) attacks. Consider httpOnly
|
|
cookies for storing tokens if your use case allows it.
|
|
|
|
### I think that we could use both JWT + API Key.
|
|
|
|
# Notes:
|
|
|
|
Using both JWT and API keys can provide an additional layer of security and
|
|
could be a good approach for our requirements.
|
|
|
|
1. JSON Web Tokens (JWT) are useful for carrying user context between services. With JWT, you can embed user-specific
|
|
data (like user ID, roles, permissions, etc.) in a secure, tamper-proof token. This can be validated by your FastAPI
|
|
backend to authenticate and authorize the user.
|
|
2.
|
|
3. API Keys can serve as an identifier for the client application (in this case, your Next.js frontend). It can provide
|
|
a straightforward way to track and control how the client application is calling the backend API.
|
|
|
|
Here's a rough workflow of how these can be used together:
|
|
|
|
A user logs in to the Next.js frontend using NextAuth and receives a JWT.
|
|
This JWT is stored securely in the client's browser.
|
|
For each request from the frontend to the backend, the JWT is included in the Authorization header.
|
|
In addition to the JWT, an API key unique to the frontend application is included in each request (possibly in a custom
|
|
header like X-API-Key).
|
|
The backend service validates both the JWT (for user authentication and authorization) and the API key (for client
|
|
application validation).
|
|
This approach provides a double check for each request:
|
|
|
|
The JWT verifies that the request comes from a legitimate, authenticated user.
|
|
The API key verifies that the request comes from a trusted client application. |