I have been using the API construct to define an a...
# sst
s
I have been using the API construct to define an api with two different types of authentication. For example, some endpoints have IAM, others require no auth. Is the API construct meant to enable this via
defaultAuthorizationType
?
Copy code
const api = new sst.Api(this, "Api", {
      defaultAuthorizationType: "AWS_IAM",
      routes: {
        "GET /private": "src/private.main",
        "GET /public": {
          authorizationType: "NONE",
          function: "src/public.main",
        },
      },
    });
s
OK, so my understanding of that construct is correct. If I change either
authorizationType
or
defaultAuthorizationType
, will I need to remove and re-deploy to see the changes?
Because right now, I'm not seeing the changes reflected in API gateway when i update the stack and re-start SST
perhaps that's expected behavior?
f
hmm.. it should update.. no need to remove and re-deploy
can you paste me the terminal output from the
start
command after u made the change?
s
The output certainly suggests the changes are picked up
This is how I'm defining my API:
Copy code
// Create the HTTP API
    this.api = new sst.Api(this, "api", {
      defaultAuthorizationType: sst.ApiAuthorizationType.NONE,
      defaultFunctionProps: {
        // Pass in the table name to our API
        environment: {
          tableName: table.tableName,
          region: table.env.region
        }
      },
      routes: {
        ...auth_routes,
        ...unauth_routes
      }
    });
I changed from
sst.ApiAuthorizationType.AWS_IAM
to
sst.ApiAuthorizationType.NONE
for the
defaultAuthorizationType
after doing so, i confirm the authorization is still in place by looking in the API Gateway console
f
i see.. and are u specifying
autorizationType
for auth_routes and unauth_routes?
s
Only for one route in
unauth_routes
, just to test out the concept
Copy code
const auth_routes = {
      "PUT  /races/{id}": "src/races/update.handler",
      "POST /races": "src/races/create.handler",
      "POST /races/{id}/register": "src/races/register.handler",
      "GET  /users/{user_id}/messages": "src/messages/list.handler",
      "PUT  /users/{user_id}/messages/{message_id}":
        "src/messages/mark_as_read.handler"
    };

    const unauth_routes = {
      "GET /races/featured": {
        function: {
          authorizationType: sst.ApiAuthorizationType.NONE,
          handler: "src/races/featured.handler"
        }
      },
      "GET /races/{id}": "src/races/get.handler",
      "GET /races/search": "src/races/list.handler",
      "GET /strava/webhook": "src/strava/validate_webhook.handler"
    };
f
lemme take a quick look.. 1 sec
Aight, got it to reproduce it
I think it’s a bug in CloudFormation.. when setting the authorizationType to
AWS_IAM
CloudFormation template looks something like:
Copy code
"Type": "AWS::ApiGatewayV2::Route",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        ...
      }
when u set it to
NONE
,
AuthorizationType
in the template is removed:
Copy code
"Type": "AWS::ApiGatewayV2::Route",
      "Properties": {
        ...
      }
but in reality CloudFormation didn’t change it
Let me put in a fix.. gimme 15min
s
Hmm, interesting. I wonder if it would work if I happened to change from NONE to AWS_IAM instead.
f
I just tested it… we need to explicitly set
AuthorizationType
to
NONE
in CloudFormation template
Copy code
"Type": "AWS::ApiGatewayV2::Route",
      "Properties": {
        "AuthorizationType": "NONE",
        ...
      }
Just merged the fix, cutting a release now
s
Thank you!
My goal is to support API endpoints for the general public (e.g. anyone who visits the website), and an additional set of endpoints for users that log into the app. Using the notes app as an example, imagine creating notes was public while only logged in users can delete notes. Since Cognito supports guest roles, I wonder if this use case couldn't be addressed differently. For example, the entire API could have a
defaultAuthorizationType
of AWS_IAM. Instead of defining authorization types of NONE, I could control what guest users see by assigning the API endpoints to the Cognito guest role (maybe this is what the API construct is doing under the covers?)
f
by guest role, do you mean the iam role for unauthenticated users?
s
correct
I see you have the
attachPermissionsForUnauthUsers
on the Auth construct
f
yeah off my head i think both approach should work
1. some routes are public, authorizationType
NONE
2. all routes are private, authorizationType
AWS_IAM
, and guest users also get IAM credentials, and you control which route they can call and not call in IAM
s
exactly
#2 seems like a best practice
f
yeah definitely more flexible, as in down the road u want guest users be able to upload something.. who knows
s
Right, and my app already leverages the difference between the two roles (auth and unauth). For example, only authenticated users can upload an image to S3, but all users can view that image.
f
if ur users are going to interact more than just ur api,
AWS_IAM
makes more snse
right
s
and besides, it just feels scary to set authorization type to NONE 🙂
f
aight, here u go v0.9.9
Copy code
npm install --save --save-exact @serverless-stack/cli@0.9.9 @serverless-stack/resources@0.9.9
s
Awesome, thank you!
f
Let me know if that fixes it
s
trying it now
Hmm, it doesn't look like the changes are taking effect.
after restarting SST, the output says "Status: no changes".
despite making changes to my stack
I'm gonna remove and re-deploy the stack
f
actually
can u send me ur CloudFormaiton template file
it’s inside
.build/cdk.out/xxxxx.template.json
for the api stack
s
sure thing
f
hmmm.. I see all routes have
AuthorizationType
set to
AWS_IAM
just checking your
defaultAuthorizationType
is set to
sst.ApiAuthorizationType.NONE
still?
s
Here's my API Stack
f
move
authorizationType: sst.ApiAuthorizationType.NONE
outside of the
function
ie.
Copy code
"GET /strava/webhook": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        function: {
          handler: "src/strava/validate_webhook.handler"
        }
      }
or just
Copy code
"GET /strava/webhook": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        function: "src/strava/validate_webhook.handler"
      }
s
hmm, didn't like that
I updated all the methods:
Copy code
const unauth_routes = {
      "GET /races/featured": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        handler: "src/races/featured.handler"
      },
      "GET /races/{id}": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        handler: "src/races/get.handler"
      },
      "GET /races/search": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        handler: "src/races/list.handler"
      },
      "GET /strava/webhook": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        handler: "src/strava/validate_webhook.handler"
      }
    };
f
not
handler
,
function
Copy code
const unauth_routes = {
      "GET /races/featured": {
        authorizationType: sst.ApiAuthorizationType.NONE,
        function: "src/races/featured.handler"
      },
      ...
    };
s
oops
ahh. that did it! 🍻
f
Nice!
s
Was I using
routes
incorrectly, or has the latest implementation outpaced the docs?
f
Oh nice catch
Doc is wrong
s
hmm, it looks like it's right in one spot
f
you are right!
s
haha, docs are hard, especially when the code is moving quickly
thanks for helping me get on track!
f
Updated the doc. Thanks for bringing it up 🙏