hey everyone, what is the best way to handle the a...
# sst
m
hey everyone, what is the best way to handle the authorization of a user based on the role he has in the db??
a
Use custom authorizer lambda.
I’ve use it for this purpose.
My authorization comes from DB + external API source.
My authorizer lambda handles it all.
m
mm ok great, thanks 😉
f
+1 for custom authorizer
o
I usually handle the authentication in the authorizer lambda, but do authorization inside the handler lambda, since it better knows what the user is trying to do
f
Right, if the logic is generic across all routes and if you don’t want to authorize on every request (ie. caching), custom authorizer makes sense. Otherwise, you can wrap the authorization logic around the Lambda handlers themselves.
o
Yeah if you’re able to make the authorization decision based on what the authorizor knows, better to do it there (e.g. based on route/method). Otherwise for something like graphql or authorising based on which entity is being operated on etc, has to go in the handler
j
@Adrián Mouly or @Frank any sample available?
j
Thx, I'll try!
@Frank Is it possible to send to the authorizer handler a different parameter depending on the endpoint?
I'll explain, I have an authorizer that queries if the user's role in the database is the one I pass by parameter, if it is true, the user can make the request to that endpoint, otherwise it must send a 403 response.
Well I see that I can send an authorizer per endpoint, but how can I send a parameter to the handler of that authorizer?
something for example:
Copy code
"GET /private": { function: "src/private.main", authorizer: authorizer(['admin', 'user']) },
j
@Manuel Villafañe If (1) your roles are static, that is you're not working with user-defined roles, (2) if you don't have tons of them, and (3) you're talking about resource authorization, the resource being what the API gateway has knowledge of like the endpoint + method, then you can also inject your roles as claims using the pre-token generation trigger from Cognito. The lambda attached to that trigger will look up your DB and shape the returned JWT accordingly. Then you simply use a JWT authorizer with the right authorizationScopes. Now, If (1) your roles are user-defined, then you'll have to use custom authorizers to fetch, inject, and authorize on the fly. You may, of course, have one single custom authorizer for your whole system, if you have a centralized role management sub-system. If (2) you have tons of roles, then by injecting them into your JWT tokens, you might be clogging all your API requests. If (3) you want to perform action or data access control, then you'll (also) need to perform fine-grained authorization in your lambda handler. You, of course, have one single custom "middleware" for authorization and have something like : *request > request validation > action authorization > data authorization > * model run * > data authorization > response validation > response* Finally, if may also want to embed some data-level access control into your model. For instance, for DynamoDB you may attach a dynamic permissions to your request to limit the access to attributes or entries : https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html
f
@Joel Corona does every route have unique parameters? (ie. [‘admin’, ‘user’])
j
yes @Frank, each route has the "roles" that are allowed for that route, i.e. they will not be repeated at that endpoint
ie. route1 ['admin'] route2 ['admin', 'user'] route3 ['client']
f
I see. the authorizer function has access to the full event object. The route is in there I think.
j
And how can I modify the event per endpoint?
f
What are u thinking to modify?
j
I don't think I have explained myself correctly
f
And in your API route, you can access the authorizer context
j
1 - I want to make some sort of middleware 2 - pass it an array of roles 3 - in the handler look for the user in the DB and check if it has any of the roles that I pass by argument 4 - in case it does, let it make the request, otherwise send a http 403