问题
This is an issue we found on Github and are having the same issue:
We're using serverless and serverless-offline to run lambda locally. We have a local DynamoDB implementation. For Cognito however, serverless-offline mocks the authenticated user and cognitoIdentityId. The mocked user has permission to invoke the lambda but not to pass in the cognitoIdentityId to match what we save in DynamoDB for a user.
- This may be a serverless-offline problem, and there may be other, better solutions.
- Or there may be a way to run Cognito locally.
- Or we can hit Cognito from our local. But we don't know how to do this.
tldr; I'm not sure what the best practice is around developing labmdas locally when using Cognito with authorizer: aws_iam
回答1:
Though this may or may not help with your problem here's how to mock Cognito while running locally.
Every AWS service accepts a configuration. In this configuration you can pass an endpoint
parameter. You can pass a local server to this config and mock your desired response for every aws service.
export const getIdentityProvider = () => new CognitoIdentityServiceProvider({
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
endpoint: process.env.IS_TEST ? 'http://localhost:5001' : null
})
AWS services perform a POST call with the date you are sending as the body and the function name as part of the x=amz-target
header. For example the AdminGetUser
Cognito call has the header: 'x-amz-target': 'AWSCognitoIdentityProviderService.AdminGetUser'
You can create a basic server to handle this like this:
import http from 'http'
const getBody = async request => {
return new Promise((resolve, reject) => {
let body = ''
request.on('data', (data) => {
body += data
})
request.on('end', () => {
resolve(JSON.parse(body))
})
})
}
const server = http.createServer(async (req, res) => {
const body = await getBody(req)
const route = req.headers['x-amz-target']
let response
const status = 200
switch (route) {
case 'AWSCognitoIdentityProviderService.AdminGetUser':
response = { foo: 'bar' }
break
}
res.writeHead(response ? status : 404, { 'Content-Type': 'text/plain' })
res.write(response || 'No route found')
res.end()
})
server.listen(process.env.PORT || 5001, 'localhost', () => {
console.log(`Proxy server listening on port http://${server.address().address}:${server.address().port}`)
})
In order to know what to return I recommend doing some unit tests and capturing the response with nock. You can then extract the response body and use that in your mock server.
来源:https://stackoverflow.com/questions/52697264/aws-cognito-with-serverless-local-environment