AWS Cognito Health Check - javascript

I have an NodeJs application that uses Cognito to manage the users and auth operations (design choice).
I am using 'amazon-cognito-identity-js' to communicate with Cognito but i'm having some trouble in making a simple health check api.
Since Cognito doesn't provide any API for that i thought of making a test user, pass the credentials to my app via env vars and try to login. If the result was a success it means that cognito is up and running.
Before i implement my solution i wanted to ask if there may be a better alternative to check if cognito is working.

You can subscribe to events from the Health Service in CloudWatch Event Rules. You can then either send an email, SMS or even trigger lambda to perform an action if Cognito service is down.

The solution to this was quite simple. I just needed to check if i can reach Cognito's GET /login endpoint.
You can find the documentation about the endpoint here

Related

What is the authentication flow for SPA (React) + Amplify + Cognito + Backend? Is Amplify Cognito integration only for serverless apps?

What I have?
A client (React) and a backend (PHP) with a simple authentication flow: the client exchanges the id token with the back-end and keeps it in localStorage.
What I want to do?
I want to change the above approach to authentication with Cognito, to support Google Sign In and a sign-in against the user pool.
Important: I do not want to use Cognito Hosted UI or Amplify pre-built auth components. I already have UI for the authentication pages on my client, and I want to hook up the authentication with Cognito to that UI.
How am I doing it?
On the client, I am using Amplify library to implement the authentication against Cognito, as it provides all the functionality I need.
In the process of signing in on the client, the Amplify library gets all the tokens from Cognito in the following form:
{
AuthenticationResult: ""
AccessToken: "…"
ExpiresIn: 3600
IdToken: "..."
RefreshToken: "..."
TokenType: "Bearer"
ChallengeParameters: {}
}
Apart from that, the client receives a user object from the user pool with all the attributes.
Now this is a step I have questions about - what should be done next?
I realize that the client is already logged in to Cognito. However, the client still needs to call my own backend API for accessing the required resources.
I came up with the following options:
After signing in, the client could send the access token to the back-end, where the token can be verified, and, if valid, the back-end will respond with some kind of a flag that indicates to the client that it can call the API now.
After signing in, the client could send the access token to the back-end, back-end verifies the token, and issues a new token to access the back-end API only, which the client then stores and uses it against back-end endpoints.
I really got lost in Amplify documentation, and not even sure if I got everything right here. Is Amplify actually intended to be used only for serverless apps, or my case is also a valid scenario? If so, please let me know what would be the best practice here, and which approach should I take.
Thank you!

How to authenticate as Google service account without a client library but only with HTTP Post?

I want to trigger my Cloud Function via HTTP but also authenticated with IAM and a service account auth0-hook I created therefore.
I generated a private key like this:
gcloud iam service-accounts keys create ~/.gcp-keys/auth0-hook-sa.key.json --iam-account=auth0-hooks#my-platform.iam.gserviceaccount.com
and applied this service-account to my cloud function.
On the outside - in the Auth0 Hook code - I know need to fetch the credentials first and send the fetched token with the POST request to the Cloud Function endpoint.
My problem here is that I can not use any of the Google Auth client libraries (Node.js in this case) because Auth0 Hooks can not import any fancy libraries as it seems.
I am hereby stuck with only using var request = require('request#2.56.0'); to make this all work.
I'd like to ask how I can manage this? There is some authentication service I can call right? But what is the API for that one? In the docs I could not find the manual way but only the client library documentations.
I am hereby stuck with only using var request =
require('request#2.56.0'); to make this all work. I'd like to ask how
I can manage this? There is some authentication service I can call
right?
Google does not provide a simple HTTP endpoint that you can call. If you think thru the process, you need the authorization to call an endpoint that generates authorization credentials. Chicken and Egg situation.
Google does not yet accept Auth0 credentials at an endpoint to exchange for Google credentials. However, keep reading for more information about Workload Identity Federation, which can/might provide that ability eventually.
There is no simple answer for your goal of creating an Auth0 hook that can generate a Google Access or Identity Token. Below are details to help understand what is possible.
To go from a Google Cloud service account JSON key file to an Access Token requires libraries also. The process is to create a JWT, sign the JWT, exchange the JWT for an access token. I wrote an article that shows how to do this in Python. The process for Node.js is similar. Your issue is that the process is too complicated for an Auth0 hook.
Google Cloud – Creating OAuth Access Tokens for REST API Calls
Google has recently introduced Google Workload Identity Federation which supports exchanging OIDC tokens for a Google OAuth access token via federation and service account impersonation. The process is just a series of HTTP method calls. I am authoring several articles on how to do this, but I am not finished at this time.
Accessing resources from an OIDC identity provider
One possibility is to create another Cloud Function or Cloud Run service that you can call in a single HTTP GET that creates the tokens for you. That way you can use Google Client libraries. Your Function/Run code would receive an HTTP GET request, interface with the client libraries to create the access token and return the token as the HTTP GET response.
However, that creates the Chicken and Egg situation. You need to authorize the request to the Function/Run code to get an access token.
You may want to change strategies and instead disable Cloud Functions authorization and verify the Auth0 Identity Token within your code and skip Google-based authorization.
Auth0: Validate ID Tokens
Auth0: Validate JSON Web Tokens
Pay attention to whatever process you choose as getting authorization correct and secure is not easy.
Note: Your question states "I want to trigger my Cloud Function via HTTP". I am not sure what method you plan to use. If you are using Cloud Functions Authorization, that requires an OAuth Identity Token. That adds more steps to the process. I have not figured out how to do that with Workload Identity Federation, but the Functions/Run code can easily handle that for you.
In summary, Cloud Functions are intended for small, light-weight code in a serverless framework. Once you add authorization, complexity grows. Provided you stick with Google Cloud authorization, everything is easy. Once you try to go from one identity system (Auth0) to another (Google Cloud IAM) the complexity jumps dramatically.

AWS: Authorize users to specific clients

So I have the following setup on AWS Cognito:
AWS Cognito User Pool: UserPool_1
Under this User Pool I have 3 users defined: Mike, Sarah, John
I have 3 App Clients under thhis user pool:
WebClient_1
WebClient_2
WebClient_3
I want Mike to be able to access: WebClient_1, WebClient_2, and WebClient_3
I want Sarah to have access only to: WebClient_3
And John to have access only to WebClient_2
Currently all users are able to access all 3 web apps defined under this user pool, that's not what I want.
How do I restrict users in the user pool to have access to specific app clients?
So let's say Sarah tries to access WebClient_1, I want her to get a message saying: "User not authorized"
How do I achieve this?
The way I would solve this is with the Cognito Pre Authentication Lambda. When a user requests authentication, the Cognito trigger runs a custom Lambda script. In your Lambda script you will receive an event with some common parameters. You can take the parameters callerContext.clientId and userName and do some processing. For a few users you could just keep the user-client mapping in the script, but more likely you will want to look up the mapping in a database like DynamoDB.
Edit: To accept the authentication you do callback(null, event); and to reject it you do callback("you are not coming in", null);
I was able to solve this by utilising multiple pieces:
User Migration Trigger
Pre Authentication Trigger
Attempting to utilise just the Pre-Authentication trigger results in an incomplete and insecure solution. The trigger only runs when a user attempts to authenticate against the user pool. This means that after a user has been authenticated for an app client they have permissions for, given the URL for any other app client, the user will be able to access it.
As a workaround, I decided to go for a different setup where I have a separate user pool for each app client and one general pool to store all my users. This obviously can get annoying when it comes to creating the same accounts in each user pool, so I mitigated that by using a migration trigger.
For example, on Sarah's first sign-in attempt to WebClient3, the migration trigger runs and imports her data to the new user pool while also preserving her password. You can combine the functionality for the pre-authentication trigger into the migration trigger such that if a user shouldn't have access to that app client then the migration fails.
A caveat here is that if the user is created by an admin with a temporary password, then they would need to first reset the password using the first pool's client before the migration can work. Also, after the migration process, the user's account is now independent of the general pool which may lead to inconsistencies if not managed properly.

Is there a way for Firebase Functions to protect an HTTP Endpoint using domain verification?

This is what I am trying to accomplish: I have a static website hosted with Firebase Hosting and it has a Google Forms Form. Upon clicking the submit button, I want to also send the user an email confirming that we received the form. I have written a Firebase function using an HTTP endpoint. However, that endpoint is exposed to the public. Is there any way I can protect this function? I know that we can do an auth verification with a logged-in user but I don't need the visitor to create an account to submit the form.
Thank you!
HTTP triggers deployed by the Firebase CLI are always accessible to anyone with an internet connection. The only access control is provided by Google Cloud to restrict access by IAM, which is not going to be helpful to you here.
What you should do instead is protect the endpoint to be accessible only by users signed in with Firebase Authentication. There are plenty of examples of this.
How to protect firebase Cloud Function HTTP endpoint to allow only Firebase authenticated users?
Callable functions also make it easy to check if the end user is authenticated at the time of the call.
Another possibility might be, to use req.headers["x-forwarded-for"] in order to compare the request's source IP address. It's not exactly a domain-check, because TCP/IP does not know about the DNS, but it still could be combined with a reverse lookup (or simply a list of IP address/es). It depends on the scenario (what the function actually does), because this would also work while not being authenticated. It is from where vs. who ...be aware the another Firebase hosting on the same IP address could not be told apart, but it would rule out direct access from the client-side .

AWS Cognito - invite user from browser application (adminCreateUser)

In AWS cognito there is an option in admin panel to create a new user by sending him an invitation with temporary password. It works good, but I need to implement exactly the same feature inside my application (react spa).
I am using aws-amplify-js but I can't see there any method which do that. In aws-sdk documentation I see adminCreateUser what is a function I need, but it requires developer credentials so I suppose I shouldn't use it in browser.
Any ideas how to implement this feature in proper way?
You can create a lambda and API endpoint to send the invitation. Of course, you should protect the API endpoint access using custom authorization to prevent non-authorized users to call this endpoint.
Visit the following for more info about the SDK:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#adminCreateUser-property

Categories

Resources