Closed aliatsis closed 8 years ago
Please PR ^^ Thanks!
Has anyone started work on this? I'd be happy to contribute a pull request.
Just going over what needs to be done (looking at src). For each endpoint that had a authorizationType
or CUSTOM
, a hapi auth strategy would be set on the route. The strategy would be linked to the hapi auth scheme that exists for the authorizerFunction
(if none exists it would be created).
The authorization function takes event
and context
parameters. The event
parameter needs authorizationToken
property set, but I can't find clear docs on what all the properties are. The context
argument can be created with createLambdaContext
.
Am I missing anything?
@johncmckim I was planning to at some point, but had to de-prioritize it for now.
Here's an example: https://aws.amazon.com/blogs/compute/introducing-custom-authorizers-in-amazon-api-gateway/
the event object:
{
"type":"TOKEN",
"authorizationToken":"<Incoming bearer token>",
"methodArn":"arn:aws:execute-api:<Region id>:<Account id>:<API id>/<Stage>/<Method>/<Resource path>"
}
I'm not exactly sure how serverless determines the authorizationToken
. The API Gateway docs allow this to be configurable (e.g. method.request.header.Authorization
).
The only other requirement I can think of is to return an AuthPolicy with the principalId
(which really is the lambda functions responsibility but could be nice to have some validation).
Thanks @aliatsis. I'll see if I get some time to put something together this week.
Also, what's the easiest way to test this? Can this be run as a CLI from outside a serverless project?
Testing this project has always been a pain. I tried several times to write tests but its intrication with serverless raises testing issues. If you find something better than calling functions for the browser/terminal/postman please tell me!
@dherault I have been using API Easy to test the endpoints on my serverless project. See this test file.
If you were willing to have a test serverless project in this repo, you could have a script to do the npm linking, run the sls offline start --debugOffline
command and then run vows index.js
to test all the endpoints in that test project. This is an idea for another issue, but if you like it I'm happy to create another issue and work on a pull request for it.
How far should this go in validating the result of the Authorization function? So far with the pull request I've created it check checks for err
and data
. Is it worth going into checking wether or not the endpoint matches the resources specified in the policy document?
The methodArn
on the event
object requires a <Account id>
and <API id>
(API Gateway ID). Any idea of ways to deal with those? Will dummy values be enough?
For my purposes right now, I don't need to validate the policy document or use the Account ID and API ID. Though I'm not doing anything complicated. @aliatsis what do you think?
@johncmckim I think validating that the principalId
exists is worth it.
Validating the policy would definitely be nice, but probably not required.
Thanks to @johncmckim, please try the new v2.5.0
:)
@dherault with some more testing I've realised there's a few differences between how this work and how API Gateway works. I'll send a PR with fixes soon.
@johncmckim Ok sure np
I haven't had a chance to do it yet, I'll try soon. But the main issue is that the plugin splits the Authorization header when it should pass in the whole header.
The other issue is that it returns 403. However, it should return 401 when context.fail("Unauthorized")
is used and 403 when the policy denies the resource.
It seems that the implementation for custom authorizer support cannot handle promises being returned. Returning a promise works when deployed but the offline plugin expects an immediate value with a principalId.
@edclement I've just added support for promises, along with some other fixes.
Merged! v2.5.1
Hi @johncmckim , great work here. Thank you for the efforts to make this work. I can't seem to use environment variables set in s-function.json for authorization function. I had a look at the code. I think the auth function is invoked before any environment variables is set on process.env. Is this the case? or Am I missing anything?
@johncmckim I just tried out the authorizer flow and it works but I can't seem to get the principalId
in the handler. I have a request mapping set up for $context.authorizer.principalId
is this supported? How have you successfully retrieved the principalId
from with the handler lambda?
@shineli1984 the env variables are something I missed. The file that would need to be updated would be createAuthScheme.js and it would need to populate the env variables as in index.js line 353. Abstracting that could be a good idea.
@aliatsis I missed that property on the context, it doesn't seem to be in the docs. It shouldn't be too hard to add. The principalId
is set on the request
object, request.auth.credentials.user
(auth and credentials may be null). You would then need to update createLambdaContext.js to include the principalId
on the context if it existed.
I'm not sure I'll have time this week to add PR's for those issues this week. If you need them soon maybe you could write a PR yourselves? Otherwise, let me know and I can try do it on the weekend.
@johncmckim I'll try to do a PR myself.
@aliatsis A workaround for you I think would be setting PRINCIPAL_ID
in your auth function in dev environment.
For example:
const decoded = verify(
last(event.authorizationToken.split(' ')),
JWT_SECRET
);
// this line below is for development env to put user id into event for lambda function invoked afterwards
process.env.PRINCIPAL_ID = decoded.user_id;
@shineli1984 I merged your PR, see version 2.5.2!
Guys thank you all for your good work. There are still a few bugs in the plugin (see other issues), I intend to solve them all in August, unless you do it first of course. Thanks again!
It would be great to add support for customer authorizer functions so I can simulate authorization/authentication locally.