Lee
Lee

Reputation: 373

Serverless aws Cors setting

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

Answers (3)

hoangdv
hoangdv

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

Matt D
Matt D

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

Mike Patrick
Mike Patrick

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

Related Questions