docs: add integration guide for AWS Cognito (#4822)

This commit is contained in:
gautambt 2020-05-21 13:48:46 +00:00 committed by GitHub
parent d184497685
commit 642c421cc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 175 additions and 5 deletions

View File

@ -73,6 +73,7 @@ Read more about the session argument for computed fields in the [docs](https://h
- docs: add docs page on query performance (close #2316) (#3693)
- docs: add a sample Caddyfile for Caddy 2 in enable-https section (#4710)
- docs: add disabling dev mode to production checklist (#4715)
- docs: add integration guide for AWS Cognito (#4822)
- docs: update troubleshooting section with reference on debugging errors (close #4052) (#4825)
- docs: add page for procuring custom docker images and binaries (#4828)

View File

@ -1,6 +1,6 @@
.. meta::
:description: Use AWS Cognito for authentication with Hasura
:keywords: hasura, docs, guide, authentication, auth, integration
:description: Using AWS Cognito for authentication with Hasura
:keywords: hasura, docs, guide, authentication, auth, jwt, integration
.. _guides_aws_cognito:
@ -12,7 +12,176 @@ Using AWS Cognito for authentication
:depth: 1
:local:
Cognito can be used in both :ref:`JWT mode <auth_jwt>` and :ref:`webhook mode <auth_webhooks>`.
Introduction
------------
- For JWT, `this blog post <https://hasura.io/blog/hasura-authentication-explained/#cognito>`__ contains detailed instructions.
- For webhook, a thin wrapper/webhook that implements `this spec <https://hasura.io/docs/1.0/graphql/manual/auth/authentication/webhook.html#spec-for-the-webhook>`__ needs to be written. Boilerplates to write this webhook can be found `here <https://github.com/hasura/graphql-engine/tree/master/community/boilerplates/auth-webhooks>`__.
In this guide, we will walk through how to set up AWS Cognito to work with the Hasura GraphQL engine.
Set up user pools and hosted web UI
-----------------------------------
Follow `these instructions <https://docs.aws.amazon.com/cognito/latest/developerguide/getting-started-with-cognito-user-pools.html>`__
to set up a user pool, add an app and enable the hosted web UI in AWS cognito. While enabling the hosted web UI, you need to select the checkbox ``Implicit Grant``.
.. thumbnail:: /img/graphql/manual/guides/cognito-app-client-settings.png
:alt: Cognito App Client Settings
Create a lambda function to add claims to the JWT
-------------------------------------------------
To add custom claims to the JWT, we need to create a lambda function and configure AWS cognito to invoke this lambda function before generating a token.
- Go to `AWS Lambda home <https://console.aws.amazon.com/lambda/home>`__ and click on the ``Create Function`` button to create a new lambda function
- Add the following code for the ``Function Code``
.. code-block:: javascript
exports.handler = (event, context, callback) => {
event.response = {
"claimsOverrideDetails": {
"claimsToAddOrOverride": {
"https://hasura.io/jwt/claims": JSON.stringify({
"x-hasura-user-id": event.request.userAttributes.sub,
"x-hasura-default-role": "user",
// do some custom logic to decide allowed roles
"x-hasura-allowed-roles": ["user"],
})
}
}
}
callback(null, event)
}
.. thumbnail:: /img/graphql/manual/guides/cognito-lambda.png
:alt: Cognito Lambda function to add claims to the JWT
Configure Cognito to trigger the lambda function
------------------------------------------------
In cognito, select ``Triggers`` -> ``Pre Token Generation`` and choose the lambda function created above:
.. thumbnail:: /img/graphql/manual/guides/cognito-triggers-1.png
:alt: Select lambda for the trigger
.. thumbnail:: /img/graphql/manual/guides/cognito-triggers-2.png
:alt: Select lambda for the trigger
Test the Cognito login and generate sample JWTs for testing
-----------------------------------------------------------
You don't need to integrate your UI with Cognito for testing. You can follow the steps below:
1. Launch the hosted UI from AWS Cognito.
.. thumbnail:: /img/graphql/manual/guides/cognito-launch-hosted-ui.png
:alt: Launch Cognito Login UI
2. You should see the Cognito login page where you can log in or sign up.
.. thumbnail:: /img/graphql/manual/guides/cognito-login.png
:alt: Cognito Login Page
3. After successfully logging in, you will be redirected to ``https://localhost:3000/cognito-callback#id_token=xxxxxx&yyyyyy``.
This page may be a 404 if you don't have a UI running on localhost:3000. Extract the ``id_token`` value from this URL.
.. thumbnail:: /img/graphql/manual/guides/cognito-redirect.png
:alt: JWT from id_token query param
4. To test this JWT, and to see if all the Hasura claims are added as per the sections above, let's test this out with `jwt.io <https://jwt.io>`__!
.. thumbnail:: /img/graphql/manual/guides/cognito-jwt.png
:alt: JWT debug on jwt.io
**Save this JWT token value so that we can use it later to test the authorization using the Hasura console.**
Configure Hasura to use Auth0 keys
----------------------------------
Cognito publishes their JWK under:
``https://cognito-idp.<aws-region>.amazonaws.com/<userPoolId>/.well-known/jwks.json``
While starting Hasura, set the environmental variable ``HASURA_GRAPHQL_JWT_SECRET`` or the flag ``--jwt-secret`` to the below JSON:
.. code-block:: javascript
{
"type":"RS256",
"jwk_url": "https://cognito-idp.<aws-region>.amazonaws.com/<userPoolId>/.well-known/jwks.json",
"claims_format": "stringified_json"
}
Add access control rules via the Hasura console
-----------------------------------------------
Cognito is configured and ready to be used in the application. You can now set up access control rules that
will automatically get applied whenever a client makes a GraphQL query with the Auth0 token.
Refer to :ref:`auth_basics` for more information.
To test this out, add an access control rule that uses ``x-hasura-user-id`` for the role ``user``.
Then make a GraphQL query or a mutation, with the authorization token from the :ref:`previous step <test-auth0>`
where we generated an Auth0 token.
.. image:: https://graphql-engine-cdn.hasura.io/img/jwt-header-auth-hasura.png
:class: no-shadow
:alt: JWT token used as bearer token on hasura console
You can also use the env variable ``HASURA_GRAPHQL_UNAUTHORIZED_ROLE`` or ``--unauthorized-role`` flag to set a role
for **unauthorized users** (e.g. ``anonymous``). This will allow you to set permissions for users that are not
logged in.
The configured unauthorized role will be used whenever an access token is not present in a request to the GraphQL API.
This can be useful for data that you would like anyone to be able to access and can be configured and restricted
just like any other role.
Sync users from Cognito
-----------------------
Now that you can sign up/log in using Cognito, you will need a way to sync your users in Postgres as well.
All you really need is the Auth0 ``user_id`` in something like a ``users`` table.
This can be done creating a lambda function and configuring it as the ``Post Authentication Trigger``.
The parameters available for this trigger are described `here <https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-post-authentication.html>`__
. Here is a sample lambda function:
.. code-block:: javascript
function (event, context, callback) {
const userId = event.userName;
const hasuraAdminSecret = "xxxx";
const url = "https://my-hasura-app.herokuapp.com/v1/graphql";
const upsertUserQuery = `
mutation($userId: String!){
insert_users(objects: [{ id: $userId }], on_conflict: { constraint: users_pkey, update_columns: [] }) {
affected_rows
}
}`
const graphqlReq = { "query": upsertUserQuery, "variables": { "userId": userId } }
request.post({
headers: {'content-type' : 'application/json', 'x-hasura-admin-secret': hasuraAdminSecret},
url: url,
body: JSON.stringify(graphqlReq)
}, function(error, response, body){
console.log(body);
callback(null, user, context);
});
}
Thats it! This lambda function will be triggered on every successful sign up/log in and sync your Auth0 user into your Postgres database.
.. note::
We need to use an ``upsert`` operation here because social logins do not distinguish between sign up and login. Hence, we need to run this rule every time a successful login is made and do nothing if the user already exists.
.. admonition:: Local dev with Auth0 rules
The sync step will require a reachable endpoint to Hasura and this is not possible in localhost. You can use `ngrok <https://ngrok.com/>`__ or similar services to expose your locally running Hasura with a public endpoint temporarily.

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB