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

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.

Related

Keycloak Resource Server authorization flow

I'm new to Keycloak and trying to find out if authorization services (Resource Server) can fit my requirements.
I have the following scenario: A client app is trying to access my API endpoints which are behind the API gateway. I want to authenticate (using id and secret) the app and if it's App A allow it access to the endpoint /credits, if it's App B allow it access to the endpoint /debits.
I assume that API gateway should verify if a call should be rejected or not.
Could you please tell me what should my workflow look like and what Keycloak functionality should I use?
I'd add roles CREDITS_CLIENT and DEBITS_CLIENT to the API_SERVICE realm in keycloak.
Then, I'd create app-a-service-account and app-b-service-account in that realm, the former with CREDITS_CLIENT role and the later with DEBITS_CLIENT role.
In the gateway or API controller, endpoint /credits requires role CREDITS_CLIENT and endpoint /debits requires role DEBITS_CLIENT.
On each call, check if the details in the jwt include the role that authorizes the account/user to access the endpoint.

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

How to create base authentication in kubernetes?

I want to create base authentication in kubernetes. every document say that I should create CSV or file then enter the username and password in it. but I do not want to use file I want to some database or kubernetes handle it.
what can I do for base authentication?
You can based your authentication on tokens if you don't want to use static pasword file.
First option:
Service Account Tokens
A service account is an automatically enabled authenticator that uses signed bearer tokens to verify requests.
The plugin uses two flags(which are optional):
Service accounts are usually created automatically by the API server and associated with pods running in the cluster through the ServiceAccount Admission Controller. Bearer tokens are mounted into pods at well-known locations, and allow in-cluster processes to talk to the API server. Accounts may be explicitly associated with pods using the serviceAccountName field of a PodSpec.
Service account bearer tokens are perfectly valid to use outside the cluster and can be used to create identities for long standing jobs that wish to talk to the Kubernetes API. To manually create a service account, simply use the kubectl create serviceaccount (NAME) command. This creates a service account in the current namespace and an associated secret.
The created secret holds the public CA of the API server and a signed JSON Web Token (JWT).
The signed JWT can be used as a bearer token to authenticate as the given service account. See above for how the token is included in a request. Normally these secrets are mounted into pods for in-cluster access to the API server, but can be used from outside the cluster as well.
There is some drawbacks because service account tokens are stored in secrets, any user with read access to those secrets can authenticate as the service account. Be careful when granting permissions to service accounts and read capabilities for secrets.
Second:
Install OpenID Connect (full documentation you can find here: oidc).
OpenID Connect (OIDC) is a superset of OAuth2 supported by some service providers, notably Azure Active Directory, Salesforce, and Google. The protocol’s main addition on top of OAuth2 is a field returned with the access token called an ID Token. This token is a JSON Web Token (JWT) with well known fields, such as a user’s email, signed by the server.
To identify the user, the authenticator uses the id_token (not the access_token) from the OAuth2 token response as a bearer token.
Since all of the data needed to validate who you are is in the id_token, Kubernetes doesn’t need to “phone home” to the identity provider. In a model where every request is stateless this provides a very scalable solution for authentication.
Kubernetes has no “web interface” to trigger the authentication process. There is no browser or interface to collect credentials which is why you need to authenticate to your identity provider first.
There’s no easy way to authenticate to the Kubernetes dashboard without using the kubectl proxy command or a reverse proxy that injects the id_token.
More information you can find here: kubernetes-authentication.

How to authenticate Lambda generated mutations when AWS AppSync using Cognito

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.