This AWS Lambda function generates and temporarily stores Box API access tokens using OAuth2 client credentials flow. The access tokens are stored in DynamoDB with the folder ID as the key and have a TTL (Time To Live) for automatic cleanup.
- ✅ Generates Box API access tokens using OAuth2 client credentials flow
- ✅ Temporarily stores access tokens in DynamoDB with folder ID as key
- ✅ Automatic token expiration and cleanup via TTL
- ✅ Secure credential management using AWS Secrets Manager
- ✅ Comprehensive error handling and logging
- ✅ API Gateway integration for HTTP endpoints
- ✅ CORS support for web applications
API Gateway → Lambda Function → Box API (OAuth2)
↓
DynamoDB (Token Storage)
↓
Secrets Manager (Credentials)
- AWS Account with appropriate permissions
- Box Developer Account with API access
- AWS CLI configured with credentials
- Node.js 18.x or higher
- Terraform (optional, for infrastructure deployment)
- Go to Box Developer Console
- Create a new app or use an existing one
- Configure the app with OAuth2 settings
- Note down the Client ID, Client Secret, and Enterprise ID
- For enterprise authentication, you'll need:
client_id
: Your Box app's client IDclient_secret
: Your Box app's client secretbox_subject_type
: Usually "enterprise"box_subject_id
: Your Box enterprise ID (e.g., "281779040")
-
Configure variables:
cd terraform cp terraform.tfvars.example terraform.tfvars # Edit terraform.tfvars with your values
-
Deploy infrastructure:
terraform init terraform plan terraform apply
-
Deploy Lambda function:
cd .. chmod +x deploy.sh ./deploy.sh
-
Install Serverless:
npm install -g serverless
-
Deploy:
serverless deploy
-
Create DynamoDB Table:
- Table name:
box-lambda-function-dev-tokens
- Partition key:
folderId
(String) - Enable TTL with attribute name:
ttl
- Table name:
-
Create Secrets Manager Secret:
- Secret name:
box-lambda-function-dev-box-credentials
- Secret value:
{ "clientId": "your-box-client-id", "clientSecret": "your-box-client-secret", "boxSubjectType": "enterprise", "boxSubjectId": "your-enterprise-id" }
- Secret name:
-
Create Lambda Function:
- Runtime: Node.js 18.x
- Handler:
index.handler
- Environment variables:
TOKEN_TABLE_NAME
:box-lambda-function-dev-tokens
BOX_SECRET_NAME
:box-lambda-function-dev-box-credentials
Variable | Description | Default |
---|---|---|
TOKEN_TABLE_NAME |
DynamoDB table name for token storage | box-lambda-function-dev-tokens |
BOX_SECRET_NAME |
Secrets Manager secret name | box-lambda-function-dev-box-credentials |
The Lambda execution role needs the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": "arn:aws:secretsmanager:*:*:secret:box-lambda-function-*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:Query",
"dynamodb:Scan"
],
"Resource": "arn:aws:dynamodb:*:*:table/box-lambda-function-*"
}
]
}
Creates a new access token for the provided folder ID.
Request Body:
{
"folder-id": "your-folder-id"
}
Response:
{
"success": true,
"folderId": "your-folder-id",
"message": "Access token generated and stored successfully",
"expiresAt": "2024-01-15T10:30:00.000Z"
}
Retrieves an existing access token for the folder ID.
Response:
{
"success": true,
"folderId": "your-folder-id",
"accessToken": "your-access-token",
"expiresAt": "2024-01-15T10:30:00.000Z"
}
const AWS = require('aws-sdk');
const lambda = new AWS.Lambda({ region: 'us-east-1' });
const params = {
FunctionName: 'box-access-token-handler-dev',
Payload: JSON.stringify({
'folder-id': 'your-folder-id'
})
};
lambda.invoke(params, (err, data) => {
if (err) console.error(err);
else console.log(JSON.parse(data.Payload));
});
Run the test script to verify the function works correctly:
node test-function.js
The function handles various error scenarios:
- 400 Bad Request: Missing or invalid folder ID
- 500 Internal Server Error: Box API errors, credential issues, or DynamoDB errors
Example error response:
{
"error": "folder-id is required",
"message": "Please provide a valid folder-id in the request"
}
- TTL: Access tokens expire after 1 hour (3600 seconds)
- Storage: Tokens are stored in DynamoDB with automatic cleanup
- Security: Credentials are stored securely in AWS Secrets Manager
- Uniqueness: Each folder ID can have only one active token
- CloudWatch Logs: All function executions are logged
- Error Tracking: Detailed error messages for debugging
- Performance: Function timeout set to 30 seconds
- Memory: 256 MB allocated by default
- Credentials: Never hardcode Box API credentials in the code
- IAM: Use least privilege principle for IAM roles
- Encryption: DynamoDB and Secrets Manager provide encryption at rest
- Network: Use VPC endpoints if needed for additional security
- Monitoring: Enable CloudTrail for API call auditing
-
"Failed to retrieve Box API credentials"
- Check if the secret exists in Secrets Manager
- Verify the secret contains valid JSON with
clientId
andclientSecret
- Ensure Lambda has permission to access the secret
-
"Box API error"
- Verify Box API credentials are correct
- Check if the Box app is properly configured
- Ensure the Box API endpoint is accessible
- Verify enterprise ID is correct for your Box organization
- Check if the app has enterprise-level permissions
-
"Failed to store access token"
- Check if the DynamoDB table exists
- Verify Lambda has DynamoDB permissions
- Ensure the table has the correct schema
Enable debug logging by adding this environment variable:
DEBUG=true
- DynamoDB: Uses on-demand billing, pay only for what you use
- Lambda: Pay per invocation, with free tier available
- Secrets Manager: $0.40 per secret per month
- API Gateway: Pay per API call
For issues or questions:
- Check CloudWatch logs for detailed error messages
- Verify all prerequisites are met
- Test with the provided test script
- Review the troubleshooting section
MIT License - see LICENSE file for details.