AnomalyInnovations / serverless-stack-demo-client

Source for the demo app client in the Serverless Stack Guide
https://demo2.serverless-stack.com
MIT License
635 stars 204 forks source link

[question] how to manage the api gateway paths without define them one by one in Routes.js #22

Closed ozbillwang closed 6 years ago

ozbillwang commented 6 years ago

Very thanks to create this demo that I can easily start a Cognito UI in 5 minutes (the only change is to replace src/config.js with my cognito details)

But when go through src/Routes.js, I realised that I need define api gateway paths individually

In this demo, you made paths Notes and Notes/{id} with backend serverless API

  create:
    handler: create.main
    events:
      - http:
          path: notes
          method: post
          cors: true
          authorizer: aws_iam

  get:
    handler: get.main
    events:
      - http:
          path: notes/{id}
          method: get
          cors: true
          authorizer: aws_iam

But I have a lot of paths in api gateway events, do I have to write routes for each path? I don't want to do that.

So how to manage the api gateway paths without define them one by one in src/Routes.js? After cognito login, it should redirects the access to backend API gateway, let API gateway takes over the rest.

jayair commented 6 years ago

@ozbillwang I'm not sure I understand what you mean by let the backend take over the rest. Can you give me an example of the flow?

ozbillwang commented 6 years ago

Sure, let me explain.

The codes in src/containers has login/signup modules to help end users to login with Cognito user pool accounts

After successfully login, the Routes.js gives two options: /notes/new and /notes/:id which are mapped to two js files: src/containers/NewNote.js and src/containers/Note.js

These options are mapped to API Gateway event path with different methods:

  # apig path: https://<apigateway_url>/notes, method `POST`
  createNote(note) {
    return invokeApig({
      path: "/notes",
      method: "POST",
      body: note
    });
  }

  # apig path: https://<apigateway_url>/notes/{id}, method `GET`
  getNote() {
    return invokeApig({ path: `/notes/${this.props.match.params.id}` });
  }

  # apig path: https://<apigateway_url>/notes/{id}, method `DELETE`
  deleteNote() {
    return invokeApig({
      path: `/notes/${this.props.match.params.id}`,
      method: "DELETE"
    });
  }

  # apig path: https://<apigateway_url>/notes/{id}, method `PUT`
  saveNote(note) {
    return invokeApig({
      path: `/notes/${this.props.match.params.id}`,
      method: "PUT",
      body: note
    });
  }

1) If I have 50 endpoints (/note is an endpoint for me). Do I have to write 50 * 2 js files to handles these endpoints?

2) Are there any ways to accept endpoints as variables, so if the endpoint name is changed, I needn't change the codes in Notes.js

3) How to support {proxy+} in path, such as notes/{proxy+}?

4) I used http-proxy integration in serverless framework for some endpoints with custom authorizer, for example:

  path:
    handler: authorizer/profile.profile
    events:
      - http:
          path: notes/{proxy+}
          method: GET
          integration: http-proxy
          request:
            uri: ${self:custom.notes_url}/{proxy}
            parameters:
              paths:
                proxy: true
          authorizer:
            name: authorizer
            resultTtlInSeconds: ${self:custom.ttl}
            identitySource: method.request.header.Authorization
            type: token

How to change it to use Cognito user pool as custom authorizer? How this github repo can help to handle it?

events:
  - http:
      path: notes/{proxy+}
      method: GET
      integration: http-proxy
      request:
        uri: ${self:custom.private_url} 
        parameters:
          paths:
            proxy: true
      authorizer:
        arn: ${self:provider.environment.UserPoolIdARN}  or aws_iam ???
jayair commented 6 years ago

@ozbillwang So you are looking for a way to handle multiple endpoints in your React app? This is effectively that we are doing here - https://github.com/AnomalyInnovations/serverless-stack-demo-client/blob/master/src/Routes.js#L21

As for the authorizers, it should work just as before. We use aws_iam.

ozbillwang commented 6 years ago

Thanks, @jayair

Yes, I saw the codes, do you mean if deal with multiple endpoints, I have to write .js for each endpoint?

ozbillwang commented 6 years ago

Another questions is, how do you set the permission to cognito groups to control which endpoints the group can access?

For example,

Group#1: endpoint1
userlist: tom, george.

Group#2: endpoint2
userlist: tom, john
jayair commented 6 years ago

@ozbillwang Say for example you want /notes, /pages, /chapters, etc.; you can add those routes as /:object and link to just one JS file.

Role based access is a bit trickier but here is a good article on setting this up - https://aws.amazon.com/blogs/aws/new-amazon-cognito-groups-and-fine-grained-role-based-access-control-2/

With the above setup each user group can be assigned a different IAM role and that can restrict access to the necessary endpoints. In this chapter we create the roles - https://serverless-stack.com/chapters/create-a-cognito-identity-pool.html. So your role would not be "arn:aws:execute-api:YOUR_API_GATEWAY_REGION:*:YOUR_API_GATEWAY_ID/*" but "arn:aws:execute-api:YOUR_API_GATEWAY_REGION:*:YOUR_API_GATEWAY_ID/endpoint1*". Or something along those lines.

ozbillwang commented 6 years ago

thanks, @jayair

"arn:aws:execute-api:YOUR_API_GATEWAY_REGION::YOUR_API_GATEWAY_ID/<group1>" makes sense for me ( I will use group name as endpoint name)