Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ An example SPA demonstrating the code and deployment to integrate with token han

The example deployment requires the following components:

- Node.js 20+
- Node.js 22+
- Docker
- jq
- OpenSSL 3
Expand All @@ -24,12 +24,6 @@ Use the [Curity developer portal](https://developer.curity.io/releases/token-han
- [OpenResty OAuth Proxy 2.0.1+](https://developer.curity.io/releases/token-handler?proxy=openresty)
- [NGINX OAuth Proxy 2.0.0+](https://developer.curity.io/releases/token-handler?proxy=nginx)

Also, ensure that your computer's Curity Docker image is up to date (9.5.0 or later):

```bash
docker pull curity.azurecr.io/curity/idsvr
```

## Deploy the System

Two example deployments are provided, to explain the moving parts of the end-to-end solution.
Expand Down Expand Up @@ -91,6 +85,13 @@ Browse to the SPA at `http://www.product.example`.\
Log in as the pre-shipped account `demouser` / `Password1`.\
Test all OAuth lifecycle operations against token handler components running at `http://bff.product.example`.

## Adapt the Deployment

Once you understand the deployment you can adapt and redeploy in various ways:

- [Run in Development Mode](https://curity.io/resources/learn/token-handler-deployment-example/#spa-developer-setup) to understand the pure SPA developer experience.
- [Change Domain Names](https://curity.io/resources/learn/token-handler-deployment-example/#change-external-urls) and [Upgrade to HTTPS URLs](https://curity.io/resources/learn/token-handler-deployment-example/#https-setup) to rehearse real deployments.

## Clean Up

When finished testing, teardown any local Docker-deployed components like this:
Expand Down
2 changes: 1 addition & 1 deletion api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:20-bookworm-slim
FROM node:22-bookworm-slim

RUN groupadd --gid 10000 apiuser \
&& useradd --uid 10001 --gid apiuser --shell /bin/bash --create-home apiuser
Expand Down
282 changes: 142 additions & 140 deletions api/package-lock.json

Large diffs are not rendered by default.

13 changes: 6 additions & 7 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@
"description": "An example API to validate JWTs and return data to the SPA",
"author": "Curity AB",
"license": "Apache-2.0",
"main": "server.ts",
"type": "module",
"engines": {
"node": ">=20"
"node": ">=22"
},
"scripts": {
"build": "rm -rf dist && tsc",
"start": "npm run build && node dist/server.js"
},
"dependencies": {
"express": "^5.1.0",
"jose": "^6.0.10"
"express": "^5.2.1",
"jose": "^6.1.3"
},
"devDependencies": {
"@types/express": "^5.0.1",
"@types/node": "^20.11.30",
"typescript": "^5.8.3"
"@types/express": "^5.0.6",
"@types/node": "^22.13.14",
"typescript": "^5.9.3"
}
}
4 changes: 2 additions & 2 deletions api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"target": "ES2022",
"strict": true,
"lib": ["ES2022"],
"module": "ES2022",
"moduleResolution": "Node",
"module": "Node18",
"moduleResolution": "Node16",
"allowSyntheticDefaultImports": true,
"outDir": "dist"
},
Expand Down
5 changes: 5 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ if [ $? -ne 0 ]; then
exit 1
fi

#
# Pull the latest image for the Curity Token Handler
#
docker pull curity.azurecr.io/curity/idsvr

#
# Run the deployment for this scenario
#
Expand Down
2 changes: 1 addition & 1 deletion deployments/curity/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ services:
# The SQL database used by the Curity Identity Server
#
curity-data:
image: postgres:17.4
image: postgres:18.1
hostname: dbserver
volumes:
- ./idsvr/data-backup.sql:/docker-entrypoint-initdb.d/data-backup.sql
Expand Down
34 changes: 32 additions & 2 deletions deployments/curity/idsvr/data-backup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE delegations (
id VARCHAR(40) PRIMARY KEY,
tenant_id VARCHAR(64) NULL,
owner VARCHAR(128) NOT NULL,
created BIGINT NOT NULL,
expires BIGINT NOT NULL,
Expand All @@ -31,6 +32,7 @@ CREATE INDEX IDX_DELEGATIONS_OWNER ON delegations (owner ASC);
CREATE INDEX IDX_DELEGATIONS_AUTHORIZATION_CODE_HASH ON delegations (authorization_code_hash ASC);

COMMENT ON COLUMN delegations.id IS 'Unique identifier';
COMMENT ON COLUMN delegations.tenant_id IS 'The tenant ID of this delegation';
COMMENT ON COLUMN delegations.owner IS 'Subject for whom the delegation is issued';
COMMENT ON COLUMN delegations.expires IS 'Moment when delegation expires, as measured in number of seconds since epoch';
COMMENT ON COLUMN delegations.scope IS 'Space delimited list of scope values';
Expand Down Expand Up @@ -360,14 +362,42 @@ COMMENT ON COLUMN buckets.attributes IS 'All attributes stored for this subject/
COMMENT ON COLUMN buckets.created IS 'When this bucket was created';
COMMENT ON COLUMN buckets.updated IS 'When this bucket was last updated';

CREATE TABLE IF NOT EXISTS database_service_providers
(
id VARCHAR(64) NOT NULL,
profile_id VARCHAR(64) NOT NULL,
service_provider_name VARCHAR(128) NULL,
created TIMESTAMP NOT NULL,
updated TIMESTAMP NOT NULL,
owner VARCHAR(128) NOT NULL,
enabled VARCHAR(16) NOT NULL DEFAULT 'enabled',
service_provider_metadata JSONB NOT NULL DEFAULT '{}',
configuration_references JSONB NOT NULL DEFAULT '{}',
attributes JSONB NOT NULL DEFAULT '{}',

PRIMARY KEY (id, profile_id)
);

COMMENT ON COLUMN database_service_providers.id IS 'The service provider ID of this service provider instance';
COMMENT ON COLUMN database_service_providers.profile_id IS 'The profile ID owning this service provider instance';
COMMENT ON COLUMN database_service_providers.service_provider_name IS 'The optional database service provider display name';
COMMENT ON COLUMN database_service_providers.created IS 'When this service provider was originally created (in UTC time)';
COMMENT ON COLUMN database_service_providers.updated IS 'When this service provider was last updated (in UTC time)';
COMMENT ON COLUMN database_service_providers.owner IS 'The owner of the database service provider. This is the user or service provider who has administrative rights on the database service provider';
COMMENT ON COLUMN database_service_providers.service_provider_metadata IS 'Metadata, as a JSON document, tied to this service provider, especially tags categorizing it';
COMMENT ON COLUMN database_service_providers.configuration_references IS 'JSON document with all attributes referencing an item in the configuration';
COMMENT ON COLUMN database_service_providers.attributes IS 'Canonical object representing this service provider';

CREATE INDEX IF NOT EXISTS IDX_DBSP_PROFILE_ID ON database_service_providers (profile_id);
CREATE INDEX IF NOT EXISTS IDX_DBSP_SERVICE_PROVIDER_NAME ON database_service_providers (service_provider_name);
CREATE INDEX IF NOT EXISTS IDX_DBSP_OWNER ON database_service_providers (owner);

--
-- Restore the test user account and its password credential
--

COPY accounts (account_id, username, password, email, phone, attributes, active, created, updated) FROM stdin;
79b6852c-8062-403b-b0a9-3b19d7175233 demouser \N demo@user.com 07711 {"name": {"givenName": "Demo", "familyName": "User"}, "emails": [{"value": "demo@user.com", "primary": true}], "agreeToTerms": "on", "phoneNumbers": [{"value": "07711", "primary": true}], "urn:se:curity:scim:2.0:Devices": []} 1 1708008810 1708008810
\.

COPY credentials (id, subject, password, attributes, created, updated) FROM stdin;
6a273e20-6015-4243-8117-44379cadf582 demouser $5$rounds=20000$p32Fp4ecezzC0BSk$kaqe1ol1ShkqespXd9QiX.NNRasd0nOOQiC6ES1wOiB {} 2024-02-15 14:53:30.623009 2024-02-15 14:53:30.623009
\.
6 changes: 2 additions & 4 deletions deployments/external/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ services:
# Keycloak is used as the external authorization server
#
keycloak:
image: quay.io/keycloak/keycloak:25.0.1
image: quay.io/keycloak/keycloak:26.4.7
hostname: login-internal
ports:
- 8080:8080
Expand All @@ -108,8 +108,6 @@ services:
KC_HTTP_ENABLED: 'true'
KC_HTTPS_ENABLED: 'false'
KC_HEALTH_ENABLED: 'true'
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: Password1
KC_LOG_LEVEL: INFO
KC_DB: postgres
KC_DB_URL_HOST: keycloak-dbserver
Expand All @@ -129,7 +127,7 @@ services:
# Keycloak's data includes preshipped user accounts
#
keycloakdata:
image: postgres:17.4
image: postgres:18.1
hostname: keycloak-dbserver
environment:
POSTGRES_USER: postgres
Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions spa/css/bootstrap.min.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions spa/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'>
<title>Demo Web Client</title>

<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css' rel='stylesheet' integrity='sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC' crossorigin='anonymous' />
<link href='bootstrap.min.css' rel='stylesheet' />
<link href='app.css' rel='stylesheet' />
</head>
<body>
<div id='root'></div>
<script type='module' async src='vendor.bundle.js'></script>
<script type='module' async src='app.bundle.js'></script>
</body>
</html>
</html>
Loading