403Webshell
Server IP : 65.108.144.40  /  Your IP : 216.73.217.165
Web Server : Apache/2.4.52 (Ubuntu)
System : Linux ubuntu-8gb-hel1-1 5.15.0-173-generic #183-Ubuntu SMP Fri Mar 6 13:29:34 UTC 2026 x86_64
User : dev ( 1000)
PHP Version : 8.2.30
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/dev/webapps/fivewishes-bridge/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/dev/webapps/fivewishes-bridge/README.md
# Keycloak → Shopify Multipass (D2C + B2B)

NestJS server that implements:
- D2C: Keycloak OIDC login → Shopify customer upsert → Multipass redirect
- B2B (optional): if `ENABLE_B2B=true` and Keycloak provides company claims, link the user into Shopify B2B Companies and assign roles

## Endpoints

- `GET /health` → `{ ok: true }`
- `GET /auth/login?return_to=/account` → redirects to Keycloak
- `GET /auth/forgot-password?return_to=/account` → redirects to Keycloak reset-password screen, then returns to `/auth/login`
- `GET /auth/callback?code=...&state=...` → validates Keycloak token, upserts customer, redirects to Shopify Multipass

## Required env

Copy `.env.example` to `.env` and fill values.

Key env vars:
- `BASE_URL` must be the public URL of this server (used for redirect URIs)
- `SHOPIFY_MULTIPASS_SECRET` comes from Shopify Plus Multipass settings
- `SHOPIFY_API_KEY` / `SHOPIFY_API_SECRET` come from your Partner (public) app
- `SHOPIFY_SCOPES` must include customers read/write (and B2B requires companies read/write)
- `TOKEN_ENCRYPTION_KEY` is used to encrypt per-shop access tokens at rest
- `KEYCLOAK_ISSUER` is your realm issuer URL

## Keycloak claims expected

Minimum (D2C):
- `email`
- `sub` (used as `external_id`)
- `given_name` / `family_name` (optional)

Optional (B2B):
- `company_id` (either `gid://shopify/Company/...` or your company external id)
- `company_location_id` (optional: `gid://shopify/CompanyLocation/...`)
- roles in `realm_access.roles` or `resource_access[client_id].roles`

Role mapping implemented:
- `b2b_admin` → `Company Admin`
- `b2b_buyer` → `Buyer`
- `finance` → `Buyer`

## Run locally

```zsh
npm i
npm run start:dev
```

## Install OAuth token (required once per shop)

This app stores the per-shop Admin API token encrypted on disk (default: `.local/shopify-tokens.enc.json`).

1) Start the server
2) Open in browser:

```text
http://localhost:3000/shopify/auth?shop=YOUR_SHOP.myshopify.com
```

3) Approve install in Shopify Admin → you should see a success message.

After that, `/auth/login` can upsert customers using the stored token.

## Shopify theme login link

Point your storefront login button to your server:

```liquid
<a href="https://YOUR_APP_DOMAIN/auth/login?return_to={{ request.path | url_encode }}">
  Log in
</a>
```

## Option A (JIT) + Reset Password

Recommended for large existing customer bases: customers activate their Keycloak account on first login.

Storefront reset password link (sends the customer to Keycloak “Forgot password” / reset credentials):

```liquid
<a href="https://YOUR_APP_DOMAIN/auth/forgot-password?return_to={{ request.path | url_encode }}">
  Forgot password
</a>
```

Keycloak client note (dev): allow redirect URIs for both `/auth/callback` and `/auth/login` (or `http://localhost:3000/*`).

## Notes

- State/nonce is signed and expires in 10 minutes.
- Customer external id is persisted as a metafield: namespace `keycloak`, key `external_id`.

## B2B flow (existing + new)

When `ENABLE_B2B=true` and Keycloak provides `company_id`, the callback will:

- Ensure a Shopify Customer exists (D2C upsert step)
- Link that Customer to the Shopify Company using `companyAssignCustomerAsContact`
- Assign a Company Contact role at the Company Location

Existing B2B customers:
- If the customer/contact already exists, the code is idempotent: it will look up the existing Company Contact and continue.

New B2B customers:
- Customer is created/updated from Keycloak login, then linked into the Company on first login.

Youez - 2016 - github.com/yon3zu
LinuXploit