Skip to content

Commit

Permalink
feat(wallet): add Liquid Auth provider (#215)
Browse files Browse the repository at this point in the history
* feat: adds Liquid as a Wallet/Provider

* chore: adds liquid-auth-js as dependency

* chore: updates lock file

* feat: adds Liquid Auth to vanilla-js example

* chore: todos

* feat: adds docker-compose

* chore: debug info

* chore: get session

* feat: local development possible using nginx

* fix: removes http-server, uses only Nginx

* docs: clarify troubleshooting and spin up

* feat: working connect

* feat: adds disconnect

* feat: defined resumeSession, message passing

* feat: Working e2e Use-Wallet Liquid-Auth integration

* chore: removes fluff

* feat: adds working examples

* fix: breaking up of concerns

* chore: whitespaces

* chore: pnpm-lock

* chore: fix

* chore: remove from nextjs

* feat: separate out Liquid Auth Use-Wallet Client

* chore: update pnpm-lock

* fix: ngrok example file port

* test: test

* chore: update pnpm

* chore: adds tests

* lint: remove unused import

* chore: pretier

* chore: prettier and linter

* chore: prettier and linter

* chore: prettier

* chore: make LiquidAuthClient public and fix option

* fix: use npm package

* chore: update package version

* chore: sync versions
  • Loading branch information
HashMapsData2Value authored Oct 20, 2024
1 parent 85700c0 commit abf22d8
Show file tree
Hide file tree
Showing 20 changed files with 1,825 additions and 898 deletions.
25 changes: 25 additions & 0 deletions examples/liquid-auth-backend/.env.docker.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Application
NODE_ENV=production
SENTRY_DNS=
PORT=5173

# Database
DB_HOST=mongo:27017
DB_USERNAME=algorand
DB_PASSWORD=algorand
DB_NAME=fido
DB_ATLAS=false

# Events
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_USERNAME=default
REDIS_PASSWORD=

# FIDO2
RP_NAME=Algorand Foundation FIDO2 Server
HOSTNAME=<NGROK_STATIC_DOMAIN>
ORIGIN=https://<NGROK_STATIC_DOMAIN>

ANDROID_SHA256HASH=47:CC:4E:EE:B9:50:59:A5:8B:E0:19:45:CA:0A:6D:59:16:F9:A9:C2:96:75:F8:F3:64:86:92:46:2B:7D:5D:5C
ANDROID_PACKAGENAME=foundation.algorand.demo
2 changes: 2 additions & 0 deletions examples/liquid-auth-backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env.docker
ngrok.yml
147 changes: 147 additions & 0 deletions examples/liquid-auth-backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Liquid Auth Backend

In order to use the Liquid Auth use-wallet wallet/provider it is necessary to run the Liquid Auth backend.

When a user engages in the _connect_ flow for the "Liquid" use-wallet option, it will generate a request-id presented through a QR code. When the QR code is scanned by a Liquid Auth-powered wallet (such as the [Liquid Auth Android demo mobile wallet app](https://github.com/algorandfoundation/liquid-auth-android/tree/develop)), the wallet app will read the request-id, acquire the origin and proceed to follow normal WebAuthn/FIDO2 flows such as generating and registering pass key credentials specific for that origin. It will then make a post request to the Liquid Auth backend it expects to be located at the origin.

To achieve this flow when developing locally, we make use of ngrok. Ngrok tunnels requests from the Internet (from the static domain provided for you) into our local computer, allow you to expose your local port HTTP to the world.

For more information on Liquid Auth, please [refer to the documentation](https://liquidauth.com).

## Liquid Auth Backend

The Liquid Auth backend is composed of the following components:

- NestJS: a headless NestJS API server.
- MongoDB: for maintaining sessions and persisting certain user data, like passkeys.
- Redis: for Web Sockets. Once a connection has been established communication happens peer-to-peer over WebRTC, but for the initial handshake Web Sockets are needed.
- CoTurn: to run your own TURN server. (Nodely.io kindly also offers TURN servers as public infrastructure.)
- Ngrok: creates the traffic tunnel to ngrok.com.

Refer to the `docker-compose.yaml` file for the specific images and additional specification.

Additionally, the following services:

- Frontend: An Nginx server that runs the Frontend part, e.g. by serving static files produced by the vanilla-ts example, as well as routing API calls to the NestJS API server.

## Setup

### 1. Install Docker

If you do not have it already, install [Docker](https://www.docker.com).

### 2. Sign Up for Ngrok

Navigate to [ngrok.com](https://ngrok.com) and sign up.

Follow all the steps.

Collect your **_Authtoken_** and **_Static Domain_**. You will need them in the next steps.

### 3. Create the YAML files

In this folder (liquid-auth-backend), the following YAML files must be created:

- .env.docker
- ngrok.yaml

Example files have been created and are checked in, but they need to be updated with your Ngrok authtoken and static domain.

Create `.env.docker` as follows, replacing <NGROK_STATIC_DOMAIN> with the static domain:

```YAML
# Application
NODE_ENV=production
SENTRY_DNS=
PORT=5173

# Database
DB_HOST=mongo:27017
DB_USERNAME=algorand
DB_PASSWORD=algorand
DB_NAME=fido
DB_ATLAS=false

# Events
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_USERNAME=default
REDIS_PASSWORD=

# FIDO2
RP_NAME=Algorand Foundation FIDO2 Server
HOSTNAME=<NGROK_STATIC_DOMAIN>
ORIGIN=https://<NGROK_STATIC_DOMAIN>

ANDROID_SHA256HASH=47:CC:4E:EE:B9:50:59:A5:8B:E0:19:45:CA:0A:6D:59:16:F9:A9:C2:96:75:F8:F3:64:86:92:46:2B:7D:5D:5C
ANDROID_PACKAGENAME=foundation.algorand.demo
```

For example it might look like this:

```YAML
HOSTNAME=different-precisely-worm.ngrok-free.app
ORIGIN=https://different-precisely-worm.ngrok-free.app
```

Similarly, create `ngrok.yml`as follows, replacing <NGROK_STATIC_DOMAIN> and <NGROK_AUTH_TOKEN>:

```YAML
version: 2
authtoken: <NGROK_AUTH_TOKEN>
tunnels:
website:
addr: frontend:80
proto: http
domain: <NGROK_STATIC_DOMAIN>
```
### 4. Build the static files
Follow the instructions to build the frontend example of your choice.
E.g., build `packages/use-wallet` and then build `examples/vanilla-ts`.

By default we set `FRONTEND_BUILD_FOLDER=../vanilla-ts/dist`, i.e. the vanilla-ts example, but you are free to change the path to the build-folder name in the docker-compose folder, or set the env variable explicitly.

The key thing is to ensure that Nginx has static files to serve.

### 5. Spin up the services

Run `docker-compose up -d` from this directory.

This will start up the docker services and detach the output (logs) from the terminal window.

Navigate to your static domain. You should be met with the frontend, e.g. examples/vanilla-ts. Additionally, navigate to `<static domain>/auth/session` and check that you get a valid JSON response (with user being set or simply being null) to confirm that the API server is running.

## Troubleshooting

#### Ngrok & VPNs

Ngrok sometimes does not play well with VPNs, so you might need to disable it.

#### Platform Error

You might get the following error:

> ! liquid-auth The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested 0.0s

Or a similar. In this case, this error appears on MacBook Pros that are running Apple Silicon.

To fix this, we can force Docker to emulate linux/amd64, by adding `platform: linux/amd64` to the service in `docker-compose.yml`:

```YAML
// ...
liquid-auth:
image: ghcr.io/algorandfoundation/liquid-auth:develop
platform: linux/amd64
restart: no
env_file:
- .env.docker
ports:
- "5173:5173"
depends_on:
- redis
- mongo
// ...
```
75 changes: 75 additions & 0 deletions examples/liquid-auth-backend/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
services:
liquid-auth:
image: ghcr.io/algorandfoundation/liquid-auth:develop
restart: no
env_file:
- .env.docker
ports:
- '5173:5173'
depends_on:
- redis
- mongo

frontend:
image: nginx:latest
volumes:
- ${FRONTEND_BUILD_FOLDER:-../vanilla-ts/dist}:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- '80:80'
depends_on:
- liquid-auth

ngrok:
image: ngrok/ngrok:latest
restart: no
command:
- 'start'
- '--all'
- '--config'
- '/etc/ngrok.yml'
volumes:
- ./ngrok.yml:/etc/ngrok.yml
ports:
- 4040:4040
depends_on:
- frontend

redis:
image: redis
restart: always
ports:
- '6379:6379'

mongo:
image: mongo:7.0
restart: no
environment:
- MONGO_INITDB_DATABASE=${DB_NAME:-fido}
- MONGO_INITDB_ROOT_USERNAME=${DB_USERNAME:-algorand}
- MONGO_INITDB_ROOT_PASSWORD=${DB_PASSWORD:-algorand}
ports:
- '27017:27017'
volumes:
- mongo:/data/db

turn:
image: coturn/coturn
restart: no
deploy:
replicas: 0 # Not in use, relying instead on Nodely's TURN server
depends_on:
- mongo
ports:
- '3478:3478'
- '3478:3478/udp'
- '5349:5349'
- '5349:5349/udp'
command:
- '--no-auth'
- '--mongo-userdb'
- 'mongodb://${DB_USERNAME:-algorand}:${DB_PASSWORD:-algorand}@mongo:27017/${DB_NAME:-coturn}?authSource=admin&retryWrites=true&w=majority'
- '--redis-userdb'
- 'ip=redis dbname=0'
volumes:
mongo:
28 changes: 28 additions & 0 deletions examples/liquid-auth-backend/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
server {
listen 80;

location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}

location ~ ^/(auth|.well-known|connect|attestation|assertion)/ {
proxy_pass http://liquid-auth:5173;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /socket.io {
proxy_pass http://liquid-auth:5173;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
7 changes: 7 additions & 0 deletions examples/liquid-auth-backend/ngrok.yml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 2
authtoken: <NGROK_AUTH_TOKEN>
tunnels:
website:
addr: frontend:80
proto: http
domain: <NGROK_STATIC_DOMAIN>
3 changes: 3 additions & 0 deletions examples/nuxt/plugins/walletManager.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export default defineNuxtPlugin((nuxtApp) => {
},
WalletId.KMD,
WalletId.KIBISIS,
{
id: WalletId.LIQUID
},
{
id: WalletId.LUTE,
options: { siteName: 'Example Site' }
Expand Down
3 changes: 3 additions & 0 deletions examples/react-ts/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const walletManager = new WalletManager({
},
WalletId.KMD,
WalletId.KIBISIS,
{
id: WalletId.LIQUID
},
{
id: WalletId.LUTE,
options: { siteName: 'Example Site' }
Expand Down
3 changes: 3 additions & 0 deletions examples/solid-ts/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const walletManager = new WalletManager({
},
WalletId.KMD,
WalletId.KIBISIS,
{
id: WalletId.LIQUID
},
{
id: WalletId.LUTE,
options: { siteName: 'Example Site' }
Expand Down
3 changes: 3 additions & 0 deletions examples/vanilla-ts/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const walletManager = new WalletManager({
},
WalletId.KMD,
WalletId.KIBISIS,
{
id: WalletId.LIQUID
},
{
id: WalletId.LUTE,
options: { siteName: 'Example Site' }
Expand Down
3 changes: 3 additions & 0 deletions examples/vue-ts/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ app.use(WalletManagerPlugin, {
},
WalletId.KMD,
WalletId.KIBISIS,
{
id: WalletId.LIQUID
},
{
id: WalletId.LUTE,
options: { siteName: 'Example Site' }
Expand Down
5 changes: 5 additions & 0 deletions packages/use-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
},
"devDependencies": {
"@agoralabs-sh/avm-web-provider": "1.7.0",
"@algorandfoundation/liquid-auth-use-wallet-client": "1.1.0",
"@blockshake/defly-connect": "1.1.6",
"@magic-ext/algorand": "23.11.0",
"@magic-sdk/provider": "28.11.0",
Expand All @@ -59,6 +60,7 @@
},
"peerDependencies": {
"@agoralabs-sh/avm-web-provider": "^1.7.0",
"@algorandfoundation/liquid-auth-use-wallet-client": "1.1.0",
"@blockshake/defly-connect": "^1.1.6",
"@perawallet/connect": "^1.3.4",
"@perawallet/connect-beta": "^2.0.21",
Expand All @@ -71,6 +73,9 @@
"@agoralabs-sh/avm-web-provider": {
"optional": true
},
"@algorandfoundation/liquid-auth-use-wallet-client": {
"optional": true
},
"@blockshake/defly-connect": {
"optional": true
},
Expand Down
3 changes: 3 additions & 0 deletions packages/use-wallet/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Define `self` to avoid ReferenceError in Node.js environment
// eslint-disable-next-line no-extra-semi
;(global as any).self = global
Loading

0 comments on commit abf22d8

Please sign in to comment.