amplify-js: Graphql's custom-auth lambda function is not invoked.
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
GraphQL API
Amplify Categories
auth
Environment information
System:
OS: macOS 12.1
CPU: (8) arm64 Apple M1
Memory: 135.39 MB / 8.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.13.2 - ~/.nvm/versions/node/v16.13.2/bin/node
Yarn: 1.22.17 - ~/.nvm/versions/node/v16.13.2/bin/yarn
npm: 8.1.2 - ~/.nvm/versions/node/v16.13.2/bin/npm
Browsers:
Chrome: 97.0.4692.99
Safari: 15.2
npmGlobalPackages:
@aws-amplify/cli: 7.6.9
corepack: 0.10.0
npm: 8.1.2
yarn: 1.22.17
Describe the bug
i have setup the custom authentication with amplify on a model
type Module
@model
@auth(
rules: [{ allow: custom }]
) {
id: ID!
name: String
}
I have also setup a lambda for this ,for verification of the token.
Am getting my jwt from cognito. It seems lambda (custom auth) is not trigged. When the header is (this is the default auth header from amplify)
Authorization: {jwt}
But when i change header
Authorization: Bearer {jwt}
Lambda is triggered when auth header used as above with Bearer.
Why is not getting trigged in the first pattern?
Amplify lib is using this Authorization: {jwt} by default for network calls.
This is a problem when we are using different types of auths like
This auth only work when auth header is Authorization: {jwt}
Expected behavior
Custom auth lambda should be invoked for Authorization: {jwt} header type.
It’s only invoked for Authorization: Bearer {jwt}.
Reproduction steps
- Add auth with cognito
- Create a schema as below
type Module
@model
@auth(
rules: [{ allow: custom }]
) {
id: ID!
name: String
}
- Follow these steps to add a custom auth function.
- Making a graphql call to the respective model.
Code Snippet
query{
listModules{
items{
id
name
}
}
}
Log output
{
"data": {
"listModules": null
},
"errors": [
{
"path": [
"listModules"
],
"data": null,
"errorType": "Unauthorized",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Not Authorized to access listModules on type ModelModuleConnection"
}
]
}
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 21 (10 by maintainers)
Hey @imdhanush sorry for the delay. Just to want to make sure I understand your use case.
Is there a reason why you’re using a Lambda to verify Cognito tokens instead of utilizing the
privateorgroupauth rules instead for both models?If you need that much control over the authorization model, you could potentially manage all of the logic from within the lambda and set both models to
customauth.For example, I changed my schema to this
Using only the custom lambda to authorize the calls, I can verify that a cognito user is making the call, check what groups they belong to, and restrict what fields, queries, mutations, etc each user can access accordingly using the
deniedFieldspart of the responseLambda example:
listPermissions ( valid Cognito access token )
createPermission ( user does not belong to any group)
createPermission (user belongs to enterprise-admins group)
Let me know if this helps
@arundna Just a heads up: we had “Bearer” in front of our OIDC tokens for lambda auth for the last 2 months as a workaround but it randomly stopped working today and started to return the error “Not authorized to perform x on type Query”. Changing the prefix to anything else caused it to start working again. Is “Bearer” a reserved word for something else now in AppSync or Amplify? I don’t see this documented anywhere but Bearer no longer works for us.
@thegoliathgeek Apologies for the delayed response on this one. @chrisbonifacio worked with our AppSync team and we’ve made changes to our AppSync documentation to clarify the scenario and also added the workaround section - Circumventing SigV4 and OIDC token authorization limitations
https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-lambda-authorization
I’ll go ahead and close this out, but feel free to open a new issue if you have further questions.
Hey @chrisbonifacio , Yes I’ll move all models to
customauth. Thank you 😃.Hey @chrisbonifacio Thank you for this. But can this be fixed? So that we don’t have to use
Bearerin the auth header for custom-auth.For the above schema i’ll make a nested query like this
As both models have different authorization rules.
Permissionmodel requiresAuthorization: {jwt}Modulemodel (custom-auth) requiresAuthorization: Bearer {jwt}output
Now only
Permissionmodule is accessible. If we pass auth header withBearer {jwt}The whole query fails.
So, after digging into this further. It seems you were right - the requests without
Bearerin the auth header are being auto-rejected by AppSync. Had to turn on my AppSync logs too see that (which I don’t recommend, as it can have unexpected increases on your bill).So, I’m not quite sure why a jwt without
Bearergets auto-rejected when a regular string like"test12345"doesn’t - still trying to figure that out.But, I also found that not including an auth token in your
API.graphqlcall with an authMode ofAWS_LAMBDAwill result in an error.So, Amplify wouldn’t have automatically made the request with its usual auth header anyway. So, I don’t think this is an issue or bug, at least not with the JS library.
You’ll have to adjust your lambda to remove the
Bearerpart of the auth header before verifying it but once you do that, just include it in your call and the lambda should work like you’d expect.My lambda logic
Client-side API GraphQL query
Result:
🙌