How to authenticate Lambda generated mutations when AWS AppSync using Cognito - aws-appsync

At present AWS AppSync can only subscribe to mutations, and this is the only way to get realtime updates. But if changes are made to the backing data outside of AppSync (like a DynamoDB update from a Lambda function) then how can we notify the clients?
The only solution I can see is to create a mutation with a "Local" resolver and have the Lambda that updates DynamoDB call this mutation. But my problem then is AppSync authentication which is set to Cognito in my case.
I tried granting IAM access to appsync:GraphQL in my Lambda role but that didn't work until I changed the auth type in AppSync from Cognito to IAM. But then of course Cognito authentication doesn't work for the web clients.
Does my Lambda function have to authenticate with a username and password through Cognito to be able to fire the mutation? Or is there another way I can notify the clients from Lambda?

You need to set the AppSync auth type to IAM and grab AWS Credentials via a Cognito Federated Identity service associated with your Cognito User Pool with an appropriately configured authenticated identity policy. You should then be able to use those credentials for IAM access to AppSync.

Related

Will Amplify automatically sigv4 sign an AppSync request if I use OPENID_CONNECT authentication type and Identity Pool Federation?

I want to use the Amplify client to connect to an AppSync service. I want to use IAM_AUTH for AppSync and to federate login with my OIDC to a Cognito Identity Pool (I set up a trust relationship from the pool to the OIDC provider).
The Amplify the docs mention how you can skip the user pool, and go directly to an identity pool. It doesn't mention if the request will be automatically SigV4 signed, however.
Elsewhere the Amplify docs mention that requests will automatically be sigv4 signed if you use a Cognito user pool AND an identity pool.
If you skip the user pool, will Amplify still sigv4 sign the request automatically? If not, how would you configure Amplify to sign the request?
Thanks
Looks like Amplify will automatically sigv4 sign the GraphQL request if AWS credentials are available.
Looks like some kind of header gets set in the request:
https://github.com/aws-amplify/amplify-js/blob/main/packages/api-graphql/src/GraphQLAPI.ts#L218
https://github.com/aws-amplify/amplify-js/blob/main/packages/api-graphql/src/GraphQLAPI.ts#L269
https://github.com/aws-amplify/amplify-js/blob/main/packages/api-graphql/src/GraphQLAPI.ts#L141
If you set auth type to AWS_IAM then _ensureCredentials is called:
https://github.com/aws-amplify/amplify-js/blob/main/packages/api-graphql/src/GraphQLAPI.ts#L141
which checks credentials with this.Credentials.get()
https://github.com/aws-amplify/amplify-js/blob/main/packages/api-graphql/src/GraphQLAPI.ts#L141
The Auth class uses the Credentials module, and the currentCredentials() function will call credentials.get():
https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/Auth.ts#L1920
If you check the Amplify Auth0 example, Auth.currentCredentials() will return current AWS credentials I think.

Can't use AWS IAM Roles with KMS Providers for MongoDB Client Side Field Level Encryption?

I am using EC2 Instance profile credentials for allowing the AWS EC2 instance to access other AWS services.
Recently, I implemented MongoDB Client-Side Field-Level Encryption for which the AWS KMS has been used as KMS Providers. The MongoDB Documentation for CSFLE mentions that the KMS Provider should have secret key and access key that maps to an IAM User.
This way I will have to create another IAM User and then maintain those credentials separately. A simpler way (and more secure) would have been to use the DefaultCredentialsProvider from software.amazon.awssdk:auth and that could have used the credentials from the instance profile that could have given access to the KMS. But this does not work for me and MongoClient fails as KMS rejects the security token used.
Is there any reason behind not allowing this way of accessing KMS?
As all projects, initial implementation of CSFLE had a scope. This scope did not include the ability to use instance roles for credential identification.
I suggest you submit your request to https://feedback.mongodb.com/ for consideration.

sign request to AWS API gateway with Signature v4 from using AWS Cognito token

I created a AWS API Gateway set with authentication = AWS_IAM to call a Lambda function. Now, to call this API I understand that I need to sign the request and as stated in the AWS documentation the correct way is to add the Authorization header calculated using AWS Signature V4 which need an access_key and a secret_key.
On my client side the user authenticate with AWS Cognito first and receive the JWT tokens (id token access token and refresh token) but I cannot find the access_key/secret
_key in them. How can I calculate the AWS Signature V4 from the tokens received from AWS Cognito?
I believe you can't (with 99,99999 of certainty)!
Please confirm that you are authenticating your users with AWS Cognito User Pool. You probably are because Cognito User Pool is the service that provides JWT. In this case, the token will assure the service that receives it (API Gateway) that your user is registered in a specific identity directory (User Pool). Your service should evaluate if it will provide access or not to its resources for users registered in this specific directory with the provided claims (groups, roles, etc).
When you secure your API Gateway endpoints with AWS_IAM you are saying that only identities that AWS can recognize inside its own identity directory (Users or Roles) are allowed to perform actions on the resource. In general, users registered in Cognito User Pools are not considered by AWS as valid identities.
For a Cognito User Pool user to be considered a valid AWS identity, you have two options:
1 - Configure your AWS account to use external Identity Providers and Federation. Not a simple thing and a solution to a different use case. In summary, don't choose this one.
2 - Use another AWS product (with a name that creates a lot of confusion) called Cognito Identity Pool. This service evaluates if the JWT token is allowed in that context (you configure it inside the Identity Pool). If is a valid token from a registered identity directory, Cognito Identity Pool will exchange your JWT token for a AWS Access Key, AWS Secret Key and AWS Session Token associated with a specific IAM Role. You can then use these keys to sign your request. But keep in mind that with this change you will lose your capacity to identity the specific user in API Gateway and in the downstream services called by API Gateway.
If you need to have the JWT token in your downstream services, you can do it with a little bit of additional effort. You can't find a way here: https://stackoverflow.com/a/57961207/6471284

AWS Cognito Session Tokens and API Gateway Templates

I am using AWS Cognito Federated Identities to map tokens from arbitrary identity providers to Session Tokens and Temporary Credentials. But it is critical that we obtain the issuer and subject claims for each of these identities within either the API Gateway or our target micro services.
To this end, I am trying to extract the issuer and subject claims from an AWS Session Token using API Gateway Mapping Templates. All APIs are signed with AWS Signature Version 4. But to be clear, very few of our identities are coming from AWS Cognito User Pools, but from various trusted identity providers we have configured in AWS Cognito Federated Identities.
I am referring to the following page for instruction:
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
What I have seen thus far:
$context.authorizer.claims.property: only useful for identities from Cognito User Pools
$context.identity.cognitoIdentityId: gets the Cognito Federated Identities key for an identity
Am I missing something?
Is it possible to extract issuer/subject from Mapping Template Context for an arbitrary identity?
Alternatively, is it possible to query Cognito Federated Identities for issuer/subject using a CognitoIdentity obtained via $context.identity.cognitoIdentityId
Feedback is much appreciated,
Thanks,
Randy

Google Cloud storage: Grant permission to OAuth 2.0 client

I try to download a file from a google cloud drive bucket via the REST. But if I use the access_token of the oAuth 2.0 client which I have created I get "Insufficient Permission" as an error (It works with the access toke of my googel account).
So, where in the cloud platform I can grant the oAuth2 client access to the bucket from where I want to download the file?
Thx
TL;DR - You're most likely missing the step where you request the right scopes when requesting your OAuth2.0 access token. Please look at the supported scopes with Google Cloud Storage APIs. Access tokens typically expire in 60 minutes and you will need to use a refresh token to get a new access token when it expires.
Please read the Google Cloud Storage Authentication page for detailed information.
Scopes
Authorization is the process of determining what permissions an
authenticated identity has on a set of specified resources. OAuth uses
scopes to determine if an authenticated identity is authorized.
Applications use a credential (obtained from a user-centric or
server-centric authentication flow) together with one or more scopes
to request an access token from a Google authorization server to
access protected resources.
For example, application A with an access
token with read-only scope can only read, while application B with an
access token with read-write scope can read and modify data. Neither
application can read or modify access control lists on objects and
buckets; only an application with full-control scope can do so.
Authentication in Google Cloud
Google Cloud services generally provides 3 main modes of authentication:
End User Account credentials - here you authenticate as the end user directly using their google account or an OAuth 2.0 access token. When requesting an access token, you will need to provide the scopes which determine which APIs are accessible to the client using that access token.
OAuth2.0 credentials - if granted the right scope, can access the user's private data. In addition, Cloud IAM lets you control fine grained permissions by granting roles to this user account.
Service Accounts - here you create a service account which is associated with a specific GCP project (and billed to that project thereby). These are mainly used for automated use from your code or any of the Google Cloud services like Compute Engine, App Engine, Cloud Functions, etc. You can create service accounts using Google Cloud IAM.
Each service account has an associated email address (you specify when creating the service account) and you will need to grant appropriate roles for this email address for your Cloud Storage buckets/objects. These credentials if granted the right roles can access the user's private data.
API keys - here you get an encrypted string which is associated with a GCP project. It is supported only by very few Google Cloud APIs and it is not possible to restrict the scope of API keys (unlike service accounts or OAuth2.0 access tokens).