- Newest
- Most votes
- Most comments
I think that you're hitting a problem where the annotations you're adding to make the custom VTL resolvers work with AppSync causes Amplify to take over resolver generation. You can perhaps work around this by:
- Keep your custom query in schema.graphql without any auth directives
- Use your CDK custom resource to create the resolver with VTL templates
- Add an $util.unauthorized() check in your VTL request template to handle auth manually:
## Query.getComponentFiltered.req.vtl
## Allow both Cognito UserPools and Lambda auth
#set($authMode = $ctx.identity)
#if($util.isNullOrEmpty($ctx.identity))
$util.unauthorized()
#end
## If using Lambda auth, $ctx.identity.resolverContext will be populated
## If using Cognito, $ctx.identity.sub will be populated
#if($util.isNullOrEmpty($ctx.identity.sub) && $util.isNullOrEmpty($ctx.identity.resolverContext))
$util.unauthorized()
#end
## Your actual resolver logic
{
"version": "2017-02-28",
"operation": "GetItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($ctx.args.id)
}
}
-
Configure the AppSync API to accept Lambda auth requests by ensuring AWS_LAMBDA is set as an additional auth mode (via amplify update api → select additional auth types → add Lambda)
-
When calling from the client, specify the auth mode:
import { API } from 'aws-amplify';
// Using Lambda auth
const result = await API.graphql({
query: getComponentFiltered,
variables: { id: '123', organizationID: 'org1' },
authMode: 'AWS_LAMBDA',
authToken: 'your-lambda-auth-token'
});
// Using Cognito auth (default)
const result = await API.graphql({
query: getComponentFiltered,
variables: { id: '123', organizationID: 'org1' },
authMode: 'AMAZON_COGNITO_USER_POOLS'
});
Hi, thanks for your fast reply. In my case i cannot use authMode: 'AWS_LAMBDA' as I am using Java client to generate graphql query for one of my important use-cases. In my java query i use "Authorization" header and set it either to my custom PAT-token or to "Bearer + {Cognito Acess Token}" depending on auth method a user selects, like this:
DynamicGraphQLClientBuilder clientBuilder = DynamicGraphQLClientBuilder.newBuilder() .url(appsyncEndpoint); clientBuilder.header("Authorization", accessToken);
I guess the actual problem is not my VTL resolver, but rather the fact that appsync doesn't call my Authorization lambda at all. I can see in CloudWatch logs that my Lambda Authorizer function is not even triggered (no logs produced). It means resolverContext object will be absent and VTL resolver will always fail as unauthorized. VTL template is called after auth step, isn't it?
Question#1 is it a bug or feature that Appsync doesn't use not primary auth methods if these are not explicitly specified in graphql query (as authMode: 'AWS_LAMBDA')?
Question #2 how to simulate amplify js authMode: 'AWS_LAMBDA' in other graphql clients? I deep searched with AI and was advised that appsync seems using 'Bearer' prefix of 'Authorization' header to switch auth mode between userpool and lambda. Is it true?
I spend a few days trying to find the solution. I don't want to change my Appsync API primary auth method to 'AWS_LAMBDA' as 90% of traffic goes from web users authorized via Cognito UserPool. I want to find a way to tell Appsync to use 'AWS_LAMBDA' auth for this specific query. I am currently thinking in the direction of creation an override logic in cdk-stacks.ts file to force appsync to use specific auth modes for specific queries without any graphql.schema directive, like this:
import { Resolver, AuthorizationType } from 'aws-cdk-lib/aws-appsync'; const getComponentFilteredResolver = new Resolver(this, 'GetComponentFilteredResolver', { api: graphqlApi, typeName: 'Query', fieldName: 'getComponentFiltered', dataSource: componentTableDataSource, requestMappingTemplate: MappingTemplate.fromFile( path.join(__dirname, 'Query.getComponentFiltered.req.vtl') ), // Primary authorization (Lambda) authorizationConfig: { authorizationType: AuthorizationType.AWS_LAMBDA, lambdaAuthorizerConfig: { handler: Function.fromFunctionArn(this, 'LambdaAuth', lambdaAuthorizerArn), resultsCacheTtl: cdk.Duration.minutes(5) } }, // Additional authorization modes additionalAuthorizationModes: [ { authorizationType: AuthorizationType.USER_POOL, userPoolConfig: { userPool: userPool, defaultAction: UserPoolDefaultAction.ALLOW } } ] });
Question#3 is it possible to use cdk-stack.ts to override auth mode per method/query and if yes, can you give correct example or documentation link?
Relevant content
- asked 4 years ago
- asked 6 months ago
- AWS OFFICIALUpdated 4 years ago
- AWS OFFICIALUpdated 4 years ago
