Reputation: 373
I am building serverless application, and want to restrict only 1 url can access to the server.
I tried two ways on serverless.yml
login:
handler: login.login
events:
- http:
path: login
method: post
cors:
origins:
- 'https://admin.test.com'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- Startlower
- Text
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
And
login:
handler: login.login
events:
- http:
path: login
method: post
cors: true
on login function,
headers: {
"Access-Control-Allow-Credentials": true,
"Access-Control-Allow-Origin" : "https://admin.test.com",
"Content-Type": "application/json",
},
But it is open to public. Anyone has the serverless url can visit, and see the json output.
Which part should I change?
Upvotes: 0
Views: 723
Reputation: 16127
In Serverless offical document, APIGateway config only accept origin: 'value'
. I think you can retry again with "correct" setting and combined response header:
login:
handler: login.login
events:
- http:
path: login
method: post
cors:
origin: 'https://admin.test.com'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- Startlower
- Text
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
in login function (the same as your function)
headers: {
"Access-Control-Allow-Credentials": true,
"Access-Control-Allow-Origin" : "https://admin.test.com",
"Content-Type": "application/json",
},
Upvotes: 1
Reputation: 3496
CORS will not prevent your function being accessible to the world, it just means that a reputable browser will refuse to honour an async call the service if the domain's don't match.
What you probably want to do is create a custom authorizer, this can be set up to authorise your logged in admin.
functions:
customauth:
handler: customauth/index.handler
admin-thing:
handler: admin/dosomething.handler
events:
- http:
path: admin/dosomething
method: post
authorizer:
name: customauth
resultTtlInSeconds: 0
identitySource: method.request.header.Authorization
identityValidationExpression: ^Bearer [-0-9a-zA-z\.]*$
cors:
origins:
- 'https://admin.test.com'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
allowCredentials: true
You may be able to do this with the referrer headers too, though not as secure.
Upvotes: 1
Reputation: 11007
The Access-Control-Allow-Origin
header relates to (many types of) cross-origin AJAX requests. It is not a general access control mechanism.
By AJAX (kind of an outdated term?), I essentially mean a request originating from a browser via javascript.
This is kind of long, but it's worth reading the entire thing, at least twice.
So this header can prevent cross-origin AJAX requests, because all browsers respect it. It does nothing for "regular" requests (i.e. pasting the URL into your browser or Postman).
To allow requests of any type from only one IP, you could check the origin
or referrer
header in your lambda code, but headers can be spoofed. Using a WAF (Web Application Firewall) with a proper ACL (Access Control List) is probably a more robust solution.
Upvotes: 2