We use a backend data layer (Hasura) to connect to a postgresql database and expose graphQL APIs.
There are two types of install of this depending on the kind of auth desired.
- Custom authentication, via keycloak
- Using OAuth providers such as Google etc
We use Hasura Backend Plus here which supports integration with Google, GitHub, Facebook, Apple, Twitter, Microsoft Live, Linkedin, and Spotify.
Pass env variables, update .env
:
PGPASSWORD="generate-a-password-for-postgres"
PGUSER="postgres-username"
ADMIN_SECRET="generate-an-admin-password"
REGION="aws s3 region"
S3_BUCKET_NAME="aws s3 bucket name"
AWS_ACCESS_KEY_ID="aws access key"
S3_SECRET_ACCESS_KEY="aws secret"
source .env
Build and start the backend:
docker volume create --name=hasura-data
docker-compose up
Cleanup afterward:
docker volume rm hasura-data
Deploy openresty for token introspection before hasura. Generate the openresty introspection script:
export AUTH_SERVER="keycloak:8000"
export CLIENT_ID="god"
export SECRET="<keycloak-secret-here>"
export REALM="master"
cat openresty.lua.template | \
awk '{gsub("{{AUTH_SERVER}}", ENVIRON["AUTH_SERVER"], $0); print}' | \
awk '{gsub("{{CLIENT_ID}}", ENVIRON["CLIENT_ID"], $0); print}' | \
awk '{gsub("{{REALM}}", ENVIRON["REALM"], $0); print}' | \
awk '{gsub("{{SECRET}}", ENVIRON["SECRET"], $0); print}' \
> openresty.lua
Build container:
Pass env variables, update .env
:
PGPASSWORD="generate-a-password-for-postgres"
PGUSER="postgres-username"
ADMIN_SECRET="generate-an-admin-password"
KEYCLOAK_USER="main keycloak client name"
KEYCLOAK_PASSWORD="keycloak master key"
AUTH_SERVER="keycloak:8080"
REALM="master"
CLIENT_ID=${KEYCLOAK_USER}
SECRET="secret for the main keycloak client"
source .env
docker volume create --name=hasura-data
docker-compose -f docker-compose-auth.yaml build --no-cache
docker-compose -f docker-compose-auth.yaml up
- Choose an appropriate realm or create a realm
- Create a client with:
- Client Protocol:
openid-connect
- Access Type:
Confidential
- Client ID
whatsapp-openresty-nginx
- Standard Flow Enabled:
Off
- Implicit Flow Enabled:
Off
- Direct Access Grants Enabled:
Off
- Service Accounts Enabled:
On
- Authorization Enabled:
Off
- Roles
- Add a new role with name
user
- Add a new role with name
- Client Protocol:
- Add role mappers (ends up in JWT auth tokens)
x-hasura-allowed-roles
:- Token Claim Name:
https://hasura\.io/jwt/claims.x-hasura-allowed-roles
- Mapper Type:
User Client Role
- Client ID:
god
- Claim JSON Type:
String
- Multivalued:
ON
- Name:
x-hasura-allowed-roles
- Token Claim Name:
x-hasura-default-role
:- Token Claim Name:
https://hasura\.io/jwt/claims.x-hasura-default-role
- Claim Value:
user
- Token Claim Name:
x-hasura-user-id
:- Token Claim Name:
https://hasura\.io/jwt/claims.x-hasura-user-id
- Claim Value:
1
- Token Claim Name:
x-hasura-org-id
: 0 [Optional]x-hasura-custom
: "" [Optional]
Verify settings are correct:
- Fetch a token
RESULT=`/usr/bin/curl --data "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${SECRET}" https://${AUTH_SERVER}/auth/realms/${REALM}/protocol/openid-connect/token`
TOKEN=`echo $RESULT | sed 's/.*access_token":"\([^"]*\).*/\1/'
- Check it on jwt.io
Ensure this part exists and conforms to the specs here:
"https://hasura.io/jwt/claims": {
"x-hasura-default-role": "user",
"x-hasura-user-id": 32,
"x-hasura-allowed-roles": ["user"]
},
Go to the Hasura dashboard. Under "Request Headers", you can now add an authorization Header with the value "Bearer " followed by the JWT you copied earlier:
RESULT=`/usr/bin/curl --data "grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${SECRET}" https://${AUTH_SERVER}/auth/realms/${REALM}/protocol/openid-connect/token`
TOKEN=`echo $RESULT | sed 's/.*access_token":"\([^"]*\).*/\1/'`