A token vending machine (TVM) is a piece of server-side code responsible for creating short-lived, limited-scope auth tokens. These tokens are intended to be used in the front-end of an application. Since the tokens will be sent to an end user’s browsing session, there is potential for the token to be intercepted and the session could be compromised. We set the tokens to expire automatically after a short time, limiting the exposure and improving our security.
Once again, we need to implement a new Lambda function. This process will be identical to how we implemented the stream handler function, and the directory “token-vending-machine” with index.js file already exists. We’re just going to need to uncomment the relevant sections in template.yaml.
Like last time, we’ll walk through the actual code and explain it on the next page. But for now, edit template.yaml and uncomment the sections as documented below.
We need make an update to the template.yaml
file to include our new function. This time though, our Lambda function is backing two API endpoints, so our structure looks a little different than it did with the stream handler.
TokenVendingMachineFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: functions/token-vending-machine
Policies:
- AWSLambdaBasicExecutionRole
- Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Ref MomentoSecret
Events:
AdminApi:
Type: Api
Properties:
RestApiId: !Ref AdminApi
Path: /tokens
Method: GET
OrderApi:
Type: Api
Properties:
RestApiId: !Ref OrderApi
Path: /tokens
Method: GET
The code above should be pasted into the Resources section of the template.yaml
file.
You see here there are two events listed in this resource definition. This means that if someone hits the GET /tokens
endpoint in either the Admin Api or the Order Api, our function will be triggered.
Our Apis are defined in Open API Specification files. The Admin Api is located at /api/admin-openapi.yaml
and the Order AApi is at /api/order-openapi.yaml
. We need to make the following change to both specifications - note that these lines are already present - just edit the files and uncomment as necessary.
/tokens:
get:
summary: Gets a temporary, limited-scope token for use in a browser
tags:
- Auth
responses:
200:
description: A token was generated and returned to the caller
content:
application/json:
schema:
type: object
properties:
token:
type: string
exp:
type: Number
500:
$ref: '#/components/responses/UnknownError'
x-amazon-apigateway-request-validator: Validate All
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${TokenVendingMachineFunction.Arn}/invocations
httpMethod: POST
type: aws_proxy
This entire code block is found inside the paths
block in both files.
This definition is enabling SAM to create the necessary permissions and connections for API Gateway to our Lambda function. A cool note here - if we were defining a POST endpoint with a request body, SAM would automatically generate validation models and check schemas for us at API Gateway, freeing our function code up from doing manual validations!
With these changes in place, it’s time to deploy our changes and verify we can get a short-lived token. Run the following commands in a terminal at the /api
directory:
sam build
sam deploy
To test, we need to take the base urls from the output of our deployment and run them through a curl command via the terminal (or something like Postman, if that’s your preference). Remember the URLs from the deployment output? They looked a bit like this…
curl '<OrderApiEndpoint>/tokens'
curl '<AdminApiEndpoint>/tokens'
If all goes to plan, you should recieve a response like this:
Now we’re good to go! Let’s take a step back for a minute and go through the function code on the next page so we know what we just built 👉