Set up Lambda
#
1) Create a new lambda- Click "Create Function" in the AWS Lambda dashboard, enter the function name and runtime, and create your Lambda function.
- NodeJS
- Python
- Other Frameworks
Important
For other backend frameworks, you can follow our guide on how to spin up a separate server configured with the SuperTokens backend SDK to authenticate requests and issue session tokens.
#
2) Link lambda layer with the lambda functionScroll to the bottom and look for the
Layers
tab. Click onAdd a layer
Select
Custom Layer
and then select the layer we created in the first step:
- NodeJS
- Python
- Other Frameworks
Important
#
3) Create a backend config fileUsing the editor provided by AWS, create a new config file and write the following code:
- Single app setup
- Multi app setup
- NodeJS
- Python
- Other Frameworks
Important
import Passwordless from 'supertokens-node/recipe/passwordless';
import Session from 'supertokens-node/recipe/session'
export function getBackendConfig() {
return {
framework: "awsLambda",
supertokens: {
connectionURI: "",
apiKey: "",
},
appInfo: {
// learn more about this on https://supertokens.com/docs/passwordless/appinfo
appName: "<YOUR_APP_NAME>",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth",
apiGatewayPath: "/dev"
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE"
}),
Session.init(),
],
isInServerlessEnv: true,
}
}
from supertokens_python.recipe import session, passwordless
from supertokens_python import SupertokensConfig, InputAppInfo
from supertokens_python.recipe.passwordless import ContactPhoneOnlyConfig
supertokens_config=SupertokensConfig(
connection_uri="",
api_key=""
)
app_info=InputAppInfo(
# learn more about this on https://supertokens.com/docs/passwordless/appinfo
app_name="<YOUR_APP_NAME>",
api_domain="<YOUR_API_DOMAIN>",
website_domain="<YOUR_WEBSITE_DOMAIN>",
api_base_path="/auth",
website_base_path="/auth",
api_gateway_path="/dev",
)
framework="fastapi"
recipe_list=[
session.init(),
passwordless.init(
flow_type="USER_INPUT_CODE",
contact_config=ContactPhoneOnlyConfig()
),
]
- NodeJS
- Python
- Other Frameworks
Important
import Passwordless from 'supertokens-node/recipe/passwordless';
import Session from 'supertokens-node/recipe/session'
export function getBackendConfig() {
return {
framework: "awsLambda",
supertokens: {
connectionURI: "",
apiKey: "",
},
appInfo: {
// learn more about this on https://supertokens.com/docs/passwordless/appinfo
appName: "<YOUR_APP_NAME>",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth",
apiGatewayPath: "/dev"
},
recipeList: [
Passwordless.init({
flowType: "USER_INPUT_CODE",
contactMethod: "PHONE"
}),
Session.init(),
],
isInServerlessEnv: true,
}
}
from supertokens_python.recipe import session, passwordless
from supertokens_python import SupertokensConfig, InputAppInfo
from supertokens_python.recipe.passwordless import ContactPhoneOnlyConfig
supertokens_config=SupertokensConfig(
connection_uri="",
api_key=""
)
app_info=InputAppInfo(
# learn more about this on https://supertokens.com/docs/passwordless/appinfo
app_name="<YOUR_APP_NAME>",
api_domain="<YOUR_API_DOMAIN>",
website_domain="<YOUR_WEBSITE_DOMAIN>",
api_base_path="/auth",
website_base_path="/auth",
api_gateway_path="/dev",
)
framework="fastapi"
recipe_list=[
session.init(),
passwordless.init(
flow_type="USER_INPUT_CODE",
contact_config=ContactPhoneOnlyConfig()
),
]
important
In the above code, notice the extra config of apiGatewayPath
that was added to the appInfo
object. The value of this should be whatever you have set as the value of your AWS stage which scopes your API endpoints. For example, you may have a stage name per dev environment:
- One for development (
/dev
). - One for testing (
/test
). - One for prod (
/prod
).
So the value of apiGatewayPath
should be set according to the above based on the env it's running under.
You also need to change the apiBasePath
on the frontend config to append the stage to the path. For example, if the frontend is query the development stage and the value of apiBasePath
is /auth
, you should change it to /dev/auth
.
note
You may edit the apiBasePath
and apiGatewayPath
value later if you haven't setup the API Gateway yet.
#
4) Add the SuperTokens auth middlewareUsing the editor provided by AWS, create/replace the handler file contents with the following code:
- NodeJS
- Python
- Other Frameworks
Important
import supertokens from "supertokens-node";
import { middleware } from "supertokens-node/framework/awsLambda";
import { getBackendConfig } from "./config.mjs";
import middy from "@middy/core";
import cors from "@middy/http-cors";
supertokens.init(getBackendConfig());
export const handler = middy(
middleware((event) => {
// SuperTokens middleware didn't handle the route, return your custom response
return {
body: JSON.stringify({
msg: "Hello!",
}),
statusCode: 200,
};
})
)
.use(
cors({
origin: getBackendConfig().appInfo.websiteDomain,
credentials: true,
headers: ["Content-Type", ...supertokens.getAllCORSHeaders()].join(", "),
methods: "OPTIONS,POST,GET,PUT,DELETE",
})
)
.onError((request) => {
throw request.error;
});
important
Since, we are using esm imports, we will need to set NODE_OPTIONS="--experimental-specifier-resolution=node"
flag in the lambda environment variables. See the Node.js documentation for more information.
import nest_asyncio
nest_asyncio.apply()
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from mangum import Mangum
from supertokens_python import init, get_all_cors_headers
from supertokens_python.framework.fastapi import get_middleware
import config
init(
supertokens_config=config.supertokens_config,
app_info=config.app_info,
framework=config.framework,
recipe_list=config.recipe_list,
mode="asgi",
)
app = FastAPI(title="SuperTokens Example")
app.add_middleware(get_middleware())
app = CORSMiddleware(
app=app,
allow_origins=[
config.app_info.website_domain
],
allow_credentials=True,
allow_methods=["GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH"],
allow_headers=["Content-Type"] + get_all_cors_headers(),
)
handler = Mangum(app)