Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ad751ecba | |||
| a24b0d8be7 | |||
| 02c700e44d | |||
| e9f1b5dac9 |
@@ -1,5 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-12-15 - 1.13.0 - feat(oidc)
|
||||
feat(oidc): add OIDC provider (OidcManager, endpoints, and interfaces)
|
||||
|
||||
- Add OidcManager class implementing OpenID Connect / OAuth2 server functionality (authorization codes, access/refresh tokens, user consents, PKCE support, JWKS, ID token generation, token revocation, cleanup task).
|
||||
- Expose OIDC endpoints on the website server: /.well-known/openid-configuration, /.well-known/jwks.json, /oauth/authorize, /oauth/token, /oauth/userinfo (GET/POST), and /oauth/revoke.
|
||||
- Integrate OidcManager into Reception: add oidcManager property and instantiate it from ts/index.ts so routes can reference it.
|
||||
- Add TypeScript interfaces for OIDC data structures (ts_interfaces/data/loint-reception.oidc.ts) and export them from the data index.
|
||||
|
||||
## 2025-12-15 - 1.12.1 - fix(dependencies)
|
||||
fix(deps): bump @uptime.link/webwidget to ^1.2.6
|
||||
|
||||
- Updated dependency @uptime.link/webwidget from ^1.2.5 to ^1.2.6 in package.json
|
||||
- No other files changed; this is a dependency patch update
|
||||
|
||||
## 2025-12-15 - 1.12.0 - feat(interfaces)
|
||||
Add JWT public-key and blocklist request interfaces, publish ordering files, and update dependencies
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@idp.global/idp.global",
|
||||
"version": "1.12.0",
|
||||
"version": "1.13.0",
|
||||
"description": "An identity provider software managing user authentications, registrations, and sessions.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
@@ -50,7 +50,7 @@
|
||||
"@push.rocks/webstore": "^2.0.20",
|
||||
"@serve.zone/platformclient": "^1.1.2",
|
||||
"@tsclass/tsclass": "^9.3.0",
|
||||
"@uptime.link/webwidget": "^1.2.5"
|
||||
"@uptime.link/webwidget": "^1.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^4.0.2",
|
||||
|
||||
Generated
+171
-250
@@ -111,8 +111,8 @@ importers:
|
||||
specifier: ^9.3.0
|
||||
version: 9.3.0
|
||||
'@uptime.link/webwidget':
|
||||
specifier: ^1.2.5
|
||||
version: 1.2.5(@tiptap/pm@2.27.1)
|
||||
specifier: ^1.2.6
|
||||
version: 1.2.6(@tiptap/pm@2.27.1)
|
||||
devDependencies:
|
||||
'@git.zone/tsbuild':
|
||||
specifier: ^4.0.2
|
||||
@@ -131,7 +131,7 @@ importers:
|
||||
version: 5.0.2
|
||||
'@types/node':
|
||||
specifier: ^24.10.1
|
||||
version: 24.10.1
|
||||
version: 24.10.4
|
||||
|
||||
packages:
|
||||
|
||||
@@ -332,9 +332,6 @@ packages:
|
||||
'@cfworker/json-schema@4.1.1':
|
||||
resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==}
|
||||
|
||||
'@cloudflare/workers-types@4.20251202.0':
|
||||
resolution: {integrity: sha512-Q7m1Ivu2fbKalOPm00KLpu6GfRaq4TlrPknqugvZgp/gDH96OYKINO4x7jvCIBvCz/aK9vVoOj8tlbSQBervVA==}
|
||||
|
||||
'@cloudflare/workers-types@4.20251213.0':
|
||||
resolution: {integrity: sha512-PJAGdKfU7hs39C2YOFNLTdrfdqG6rbaVj5UuI306zS+TPokiskRLEgUXKqS6avN9Uu9Nyuf2a0hqoumLQCnJlQ==}
|
||||
|
||||
@@ -350,15 +347,9 @@ packages:
|
||||
'@consent.software/webclient@1.1.0':
|
||||
resolution: {integrity: sha512-VX7e8ygZwgU8WEzn22fdvvEytLYl4kfp/u40GusaBU4iFtjrCY2hxDy9Z1FTKicpGcRxf3t13lM0Jaugq7Jj/w==}
|
||||
|
||||
'@design.estate/dees-catalog@2.0.7':
|
||||
resolution: {integrity: sha512-rshv71LqA2PXaEEf6C1/hv6Yu2ovRuWaZhdnUznCDpjdYgxBq7PHkiHCNvg/m6wJ9Ue/03HcuuPqtj2bksgAag==}
|
||||
|
||||
'@design.estate/dees-catalog@3.3.1':
|
||||
resolution: {integrity: sha512-QNIjAElIMm04Jz7VZTY/F1NjBIXCEYJ0VGK/wHE8ppzsSpSw93uLV47GFyAoEnwFp665IJpfS4HzRh7epwIArA==}
|
||||
|
||||
'@design.estate/dees-comms@1.0.27':
|
||||
resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==}
|
||||
|
||||
'@design.estate/dees-comms@1.0.30':
|
||||
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
||||
|
||||
@@ -368,9 +359,6 @@ packages:
|
||||
'@design.estate/dees-element@2.1.3':
|
||||
resolution: {integrity: sha512-TjXWxVcdSPaT1IOk31ckfxvAZnJLuTxhFGsNCKoh63/UE2FVf6slp8//UFvN+ADigiA9ZsY0azkY99XbJCwDDA==}
|
||||
|
||||
'@design.estate/dees-wcctools@1.2.1':
|
||||
resolution: {integrity: sha512-ESFas1MPPwDUcXRssyHRsc63XPTBJSTBA+5RhYXDZx8mbV6HxEKiJR8Oz1Mv7DBdW+ZSuUTD/fA6Aa/fCxGYTQ==}
|
||||
|
||||
'@design.estate/dees-wcctools@2.0.1':
|
||||
resolution: {integrity: sha512-1DaQtvoMmD+uH9cjSrL4szk7h0nbBlT/ZBmz+qvWCOqzZXE3wPOAdgASZ73NeQlehLx4KGbfJTCG15DSB0W3LQ==}
|
||||
|
||||
@@ -681,71 +669,71 @@ packages:
|
||||
'@module-federation/webpack-bundler-runtime@0.21.6':
|
||||
resolution: {integrity: sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ==}
|
||||
|
||||
'@mongodb-js/saslprep@1.3.2':
|
||||
resolution: {integrity: sha512-QgA5AySqB27cGTXBFmnpifAi7HxoGUeezwo6p9dI03MuDB6Pp33zgclqVb6oVK3j6I9Vesg0+oojW2XxB59SGg==}
|
||||
'@mongodb-js/saslprep@1.4.0':
|
||||
resolution: {integrity: sha512-ZHzx7Z3rdlWL1mECydvpryWN/ETXJiCxdgQKTAH+djzIPe77HdnSizKBDi1TVDXZjXyOj2IqEG/vPw71ULF06w==}
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.83':
|
||||
resolution: {integrity: sha512-TbKM2fh9zXjqFIU8bgMfzG7rkrIYdLKMafgPhFoPwKrpWk1glGbWP7LEu8Y/WrMDqTGFdRqUmuX89yQEzZbkiw==}
|
||||
'@napi-rs/canvas-android-arm64@0.1.84':
|
||||
resolution: {integrity: sha512-pdvuqvj3qtwVryqgpAGornJLV6Ezpk39V6wT4JCnRVGy8I3Tk1au8qOalFGrx/r0Ig87hWslysPpHBxVpBMIww==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.83':
|
||||
resolution: {integrity: sha512-gp8IDVUloPUmkepHly4xRUOfUJSFNvA4jR7ZRF5nk3YcGzegSFGeICiT4PnYyPgSKEhYAFe1Y2XNy0Mp6Tu8mQ==}
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.84':
|
||||
resolution: {integrity: sha512-A8IND3Hnv0R6abc6qCcCaOCujTLMmGxtucMTZ5vbQUrEN/scxi378MyTLtyWg+MRr6bwQJ6v/orqMS9datIcww==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.83':
|
||||
resolution: {integrity: sha512-r4ZJxiP9OgUbdGZhPDEXD3hQ0aIPcVaywtcTXvamYxTU/SWKAbKVhFNTtpRe1J30oQ25gWyxTkUKSBgUkNzdnw==}
|
||||
'@napi-rs/canvas-darwin-x64@0.1.84':
|
||||
resolution: {integrity: sha512-AUW45lJhYWwnA74LaNeqhvqYKK/2hNnBBBl03KRdqeCD4tKneUSrxUqIv8d22CBweOvrAASyKN3W87WO2zEr/A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.83':
|
||||
resolution: {integrity: sha512-Uc6aSB05qH1r+9GUDxIE6F5ZF7L0nTFyyzq8ublWUZhw8fEGK8iy931ff1ByGFT04+xHJad1kBcL4R1ZEV8z7Q==}
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.84':
|
||||
resolution: {integrity: sha512-8zs5ZqOrdgs4FioTxSBrkl/wHZB56bJNBqaIsfPL4ZkEQCinOkrFF7xIcXiHiKp93J3wUtbIzeVrhTIaWwqk+A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.83':
|
||||
resolution: {integrity: sha512-eEeaJA7V5KOFq7W0GtoRVbd3ak8UZpK+XLkCgUiFGtlunNw+ZZW9Cr/92MXflGe7o3SqqMUg+f975LPxO/vsOQ==}
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.84':
|
||||
resolution: {integrity: sha512-i204vtowOglJUpbAFWU5mqsJgH0lVpNk/Ml4mQtB4Lndd86oF+Otr6Mr5KQnZHqYGhlSIKiU2SYnUbhO28zGQA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.83':
|
||||
resolution: {integrity: sha512-cAvonp5XpbatVGegF9lMQNchs3z5RH6EtamRVnQvtoRtwbzOMcdzwuLBqDBQxQF79MFbuZNkWj3YRJjZCjHVzw==}
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.84':
|
||||
resolution: {integrity: sha512-VyZq0EEw+OILnWk7G3ZgLLPaz1ERaPP++jLjeyLMbFOF+Tr4zHzWKiKDsEV/cT7btLPZbVoR3VX+T9/QubnURQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.83':
|
||||
resolution: {integrity: sha512-WFUPQ9qZy31vmLxIJ3MfmHw+R2g/mLCgk8zmh7maJW8snV3vLPA7pZfIS65Dc61EVDp1vaBskwQ2RqPPzwkaew==}
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.84':
|
||||
resolution: {integrity: sha512-PSMTh8DiThvLRsbtc/a065I/ceZk17EXAATv9uNvHgkgo7wdEfTh2C3aveNkBMGByVO3tvnvD5v/YFtZL07cIg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.83':
|
||||
resolution: {integrity: sha512-X9YwIjsuy50WwOyYeNhEHjKHO8rrfH9M4U8vNqLuGmqsZdKua/GrUhdQGdjq7lTgdY3g4+Ta5jF8MzAa7UAs/g==}
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.84':
|
||||
resolution: {integrity: sha512-N1GY3noO1oqgEo3rYQIwY44kfM11vA0lDbN0orTOHfCSUZTUyiYCY0nZ197QMahZBm1aR/vYgsWpV74MMMDuNA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.83':
|
||||
resolution: {integrity: sha512-Vv2pLWQS8EnlSM1bstJ7vVhKA+mL4+my4sKUIn/bgIxB5O90dqiDhQjUDLP+5xn9ZMestRWDt3tdQEkGAmzq/A==}
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.84':
|
||||
resolution: {integrity: sha512-vUZmua6ADqTWyHyei81aXIt9wp0yjeNwTH0KdhdeoBb6azHmFR8uKTukZMXfLCC3bnsW0t4lW7K78KNMknmtjg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.83':
|
||||
resolution: {integrity: sha512-K1TtjbScfRNYhq8dengLLufXGbtEtWdUXPV505uLFPovyGHzDUGXLFP/zUJzj6xWXwgUjHNLgEPIt7mye0zr6Q==}
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.84':
|
||||
resolution: {integrity: sha512-YSs8ncurc1xzegUMNnQUTYrdrAuaXdPMOa+iYYyAxydOtg0ppV386hyYMsy00Yip1NlTgLCseRG4sHSnjQx6og==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@napi-rs/canvas@0.1.83':
|
||||
resolution: {integrity: sha512-f9GVB9VNc9vn/nroc9epXRNkVpvNPZh69+qzLJIm9DfruxFqX0/jsXG46OGWAJgkO4mN0HvFHjRROMXKVmPszg==}
|
||||
'@napi-rs/canvas@0.1.84':
|
||||
resolution: {integrity: sha512-88FTNFs4uuiFKP0tUrPsEXhpe9dg7za9ILZJE08pGdUveMIDeana1zwfVkqRHJDPJFAmGY3dXmJ99dzsy57YnA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@napi-rs/wasm-runtime@1.0.7':
|
||||
@@ -880,8 +868,8 @@ packages:
|
||||
'@push.rocks/smarterror@2.0.1':
|
||||
resolution: {integrity: sha512-iCcH1D8tlDJgMFsaJ6lhdOTKhbU0KoprNv9MRP9o7691QOx4JEDXiHtr/lNtxVo8BUtdb9CF6kazaknO9KuORA==}
|
||||
|
||||
'@push.rocks/smartexit@1.0.23':
|
||||
resolution: {integrity: sha512-WmwKYcwbHBByoABhHHB+PAjr5475AtD/xBh1mDcqPrFsOOUOZq3BBUdpq25wI3ccu/SZB5IwaimiVzadls6HkA==}
|
||||
'@push.rocks/smartexit@1.1.0':
|
||||
resolution: {integrity: sha512-GD8VLIbxQuwvhPXwK4eH162XAYSj+M3wGKWGNO3i1iY4bj8P3BARcgsWx6/ntN3aCo5ygWtrevrfD5iecYY2Ng==}
|
||||
|
||||
'@push.rocks/smartfeed@1.4.0':
|
||||
resolution: {integrity: sha512-bvj/3cGQI6TbbjbqrgC1uufcqprd/VthefuIsS8KHiHyCqYD5Z6RTjrbQY9WOCsmub/dcuMavfXQZqe9g2+OrQ==}
|
||||
@@ -1188,60 +1176,60 @@ packages:
|
||||
'@rolldown/pluginutils@1.0.0-beta.52':
|
||||
resolution: {integrity: sha512-/L0htLJZbaZFL1g9OHOblTxbCYIGefErJjtYOwgl9ZqNx27P3L0SDfjhhHIss32gu5NWgnxuT2a2Hnnv6QGHKA==}
|
||||
|
||||
'@rspack/binding-darwin-arm64@1.6.6':
|
||||
resolution: {integrity: sha512-vGVDP0rlWa2w/gLba/sncVfkCah0HmhdmK5vGj/7sSX0iViwQneA2xjxDHyCNSQrvfq9GJmj4Kmdq/9tGh0KuA==}
|
||||
'@rspack/binding-darwin-arm64@1.6.7':
|
||||
resolution: {integrity: sha512-QiIAP8JTAtht0j8/xZZEQTJRB9e+KrOm9c7JJm73CewVg55rDWRrwopiVfBNlTu1coem1ztUHJYdQhg2uXfqww==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rspack/binding-darwin-x64@1.6.6':
|
||||
resolution: {integrity: sha512-IcdEG2kOmbPPO70Zl7gDnowDjK7d7C1hWew2vU7dPltr2t1JalRIMnS051lhiur0ULkSxV3cW1zXqv0Oi8AnOg==}
|
||||
'@rspack/binding-darwin-x64@1.6.7':
|
||||
resolution: {integrity: sha512-DpQRxxTXkMMNPmBXeJBaAB8HmWKxH2IfvHv7vU+kBhJ3xdPtXU4/xBv1W3biluoNRG11gc1WLIgjzeGgaLCxmw==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.6':
|
||||
resolution: {integrity: sha512-rIguCCtlTcwoFlwheDiUgdImk27spuCRn43zGJogARpM/ZYRFKIuSwFDGUtJT2g0TSLUAHUhWAUqC36NwvrbMQ==}
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.7':
|
||||
resolution: {integrity: sha512-211/XoBiooGGgUo/NxNpsrzGUXtH1d7g/4+UTtjYtfc8QHwu7ZMHcsqg0wss53fXzn/yyxd0DZ56vBHq52BiFw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-linux-arm64-musl@1.6.6':
|
||||
resolution: {integrity: sha512-x6X6Gr0fUw6qrJGxZt3Rb6oIX+jd9pdcyp0VbtofcLaqGVQbzustYsYnuLATPOys0q4J/4kWnmEhkjLJHwkhpQ==}
|
||||
'@rspack/binding-linux-arm64-musl@1.6.7':
|
||||
resolution: {integrity: sha512-0WnqAWz3WPDsXGvOOA++or7cHpoidVsH3FlqNaAfRu6ni6n7ig/s0/jKUB+C5FtXOgmGjAGkZHfFgNHsvZ0FWw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-linux-x64-gnu@1.6.6':
|
||||
resolution: {integrity: sha512-gSlVdASszWHosQKn+nzYOInBijdQboUnmNMGgW9/PijVg3433IvQjzviUuJFno8CMGgrACV9yw+ZFDuK0J57VA==}
|
||||
'@rspack/binding-linux-x64-gnu@1.6.7':
|
||||
resolution: {integrity: sha512-iMrE0Q4IuYpkE0MjpaOVaUDYbQFiCRI9D3EPoXzlXJj4kJSdNheODpHTBVRlWt8Xp7UAoWuIFXCvKFKcSMm3aQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-linux-x64-musl@1.6.6':
|
||||
resolution: {integrity: sha512-TZaqVkh7memsTK/hxkOBrbpdzbmBUMea1YnYt++7QjMgco1kWFvAQ+YhAWtIaOaEg8s6C07Lt0Zp8izM2Dja0g==}
|
||||
'@rspack/binding-linux-x64-musl@1.6.7':
|
||||
resolution: {integrity: sha512-e7gKFxpdEQwYGk7lTC/hukTgNtaoAstBXehnZNk4k3kuU6+86WDrkn18Cd949iNqfIPtIG/wIsFNGbkHsH69hQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rspack/binding-wasm32-wasi@1.6.6':
|
||||
resolution: {integrity: sha512-W4mWdlLnYrbUaktyHOGNfATblxMTbgF7CBfDw8PhbDtjd2l8e/TnaHgIDkwITHXAOMEF/QEKfo9FtusbcQJNKw==}
|
||||
'@rspack/binding-wasm32-wasi@1.6.7':
|
||||
resolution: {integrity: sha512-yx88EFdE9RP3hh7VhjjW6uc6wGU0KcpOcZp8T8E/a+X8L98fX0aVrtM1IDbndhmdluIMqGbfJNap2+QqOCY9Mw==}
|
||||
cpu: [wasm32]
|
||||
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.6':
|
||||
resolution: {integrity: sha512-cw5OgxqoDwjoZlk0L3vGEwcjPZsOVFYLwr2ssiC05rsTbhBwxj8coLpAJdvUvbf6C2TTmCB7iPe2sPq1KWD37g==}
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.7':
|
||||
resolution: {integrity: sha512-vgxVYpFK8P5ulSXQQA+EbX78R/SUU+WIf0JIY+LoUoP89gZOsise/lKAJMAybzpeTJ1t0ndLchFznDYnzq+l4Q==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.6':
|
||||
resolution: {integrity: sha512-M4ruR+VZ59iy+mPjy6FQPT27cOgeytf3wFBrt7e0suKeNLYGxrNyI9YhgpCTY++SMJsAMgRLGDHoI3ZgWulw1Q==}
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.7':
|
||||
resolution: {integrity: sha512-bV5RTW0Va0UQKJm9HWLt7fWNBPaBBBxCJOA2pJT3nGGm6CCXKnZSyEiVbFUk4jI/uiwBfqenlLkzaGoMRbeDhA==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rspack/binding-win32-x64-msvc@1.6.6':
|
||||
resolution: {integrity: sha512-q5QTvdhPUh+CA93cQG5zWKRIHMIWPzw+ftFDEwBw52zYdvNAoLniqD8o5Mi8CT0pndhulXgR5aw0Sjd3eMah+A==}
|
||||
'@rspack/binding-win32-x64-msvc@1.6.7':
|
||||
resolution: {integrity: sha512-8xlbuJQtYktlBjZupOHlO8FeZqSIhsV3ih7xBSiOYar6LI6uQzA7XiO3I5kaPSDirBMMMKv1Z4rKCxWx10a3TQ==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rspack/binding@1.6.6':
|
||||
resolution: {integrity: sha512-noiV+qhyBTVpvG2M4bnOwKk2Ynl6G47Wf7wpCjPCFr87qr3txNwTTnhkEJEU59yj+VvIhbRD2rf5+9TLoT0Wxg==}
|
||||
'@rspack/binding@1.6.7':
|
||||
resolution: {integrity: sha512-7ICabuBN3gHc6PPN52+m1kruz3ogiJjg1C0gSWdLRk18m/4jlcM2aAy6wfXjgODJdB0Yh2ro/lIpBbj+AYWUGA==}
|
||||
|
||||
'@rspack/core@1.6.6':
|
||||
resolution: {integrity: sha512-2mR+2YBydlgZ7Q0Rpd6bCC3MBnV9TS0x857K0zIhbDj4BQOqaWVy1n7fx/B3MrS8TR0QCuzKfyDAjNz+XTyJVQ==}
|
||||
'@rspack/core@1.6.7':
|
||||
resolution: {integrity: sha512-tkd4nSzTf+pDa9OAE4INi/JEa93HNszjWy5C9+trf4ZCXLLHsHxHQFbzoreuz4Vv2PlCWajgvAdiPMV1vGIkuw==}
|
||||
engines: {node: '>=18.12.0'}
|
||||
peerDependencies:
|
||||
'@swc/helpers': '>=0.5.1'
|
||||
@@ -1760,8 +1748,8 @@ packages:
|
||||
'@types/node@22.19.3':
|
||||
resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
|
||||
|
||||
'@types/node@24.10.1':
|
||||
resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==}
|
||||
'@types/node@24.10.4':
|
||||
resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==}
|
||||
|
||||
'@types/qs@6.14.0':
|
||||
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||
@@ -1826,8 +1814,8 @@ packages:
|
||||
'@ungap/structured-clone@1.3.0':
|
||||
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
|
||||
|
||||
'@uptime.link/webwidget@1.2.5':
|
||||
resolution: {integrity: sha512-uyVQ87JG0gz7M2MjMWJaTnFbigBTNhcdKpqP9V3kkQyzxod3HV963vidrdWTgKbULtDyPTjtaoS5gSqn67BJhQ==}
|
||||
'@uptime.link/webwidget@1.2.6':
|
||||
resolution: {integrity: sha512-rpr3lIQ69OwfYJSBhBYOP2rx4yyowpdpLbqUvkiBVx93SEc/9gwM8Sy9vcBztod9e9j5Nwac/82Ygjx7pRfykQ==}
|
||||
|
||||
'@webcontainer/api@1.2.0':
|
||||
resolution: {integrity: sha512-tzoKBd4lLdhHy5GHFpUkl+ndoSba8JqmB7x0ZQFnWfjbcbQOvKQfxA8MEMUYhgqjWHnbrWdAfnBEHz5f5lYG5A==}
|
||||
@@ -1888,8 +1876,8 @@ packages:
|
||||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
asn1js@3.0.6:
|
||||
resolution: {integrity: sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==}
|
||||
asn1js@3.0.7:
|
||||
resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
async-mutex@0.5.0:
|
||||
@@ -2304,8 +2292,8 @@ packages:
|
||||
resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==}
|
||||
hasBin: true
|
||||
|
||||
fast-xml-parser@5.3.2:
|
||||
resolution: {integrity: sha512-n8v8b6p4Z1sMgqRmqLJm3awW4NX7NkaKPfb3uJIBTSH7Pdvufi3PQ3/lJLQrvxcMYl7JI2jnDO90siPEpD8JBA==}
|
||||
fast-xml-parser@5.3.3:
|
||||
resolution: {integrity: sha512-2O3dkPAAC6JavuMm8+4+pgTk+5hoAs+CjZ+sWcQLkX9+/tHRuTkQh/Oaifr8qDmZ8iEHb771Ea6G8CdwkrgvYA==}
|
||||
hasBin: true
|
||||
|
||||
fault@2.0.1:
|
||||
@@ -2514,8 +2502,8 @@ packages:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
iconv-lite@0.7.0:
|
||||
resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
|
||||
iconv-lite@0.7.1:
|
||||
resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
ieee754@1.2.1:
|
||||
@@ -2629,8 +2617,8 @@ packages:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
lenis@1.3.15:
|
||||
resolution: {integrity: sha512-zSYOFs0ydafX70uygFoipaHHQouPeE4DpZZhdOUyLJxVf2ZVvBCBBaolDDaQztTRsa6+stBlxq2GmFGJPAVryQ==}
|
||||
lenis@1.3.16:
|
||||
resolution: {integrity: sha512-KULpna+5TgRCDMSPx4SzJwtsjlz7EeoFCp4IDCXrlM73rLBAj34Egcl7GCLz/6+hXFOYt3DTBeTtJvTu45dJNA==}
|
||||
peerDependencies:
|
||||
'@nuxt/kit': '>=3.0.0'
|
||||
react: '>=17.0.0'
|
||||
@@ -2736,9 +2724,6 @@ packages:
|
||||
resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==}
|
||||
engines: {node: 20 || >=22}
|
||||
|
||||
lucide@0.555.0:
|
||||
resolution: {integrity: sha512-R7BkO2/XRpMADcMIRn1UOZOvirxr2Z6s/R82k0EUK71ZXXrlRbvkVwTAIf+9DRApeyH+zNMIGfiUdmrOhoAygQ==}
|
||||
|
||||
lucide@0.560.0:
|
||||
resolution: {integrity: sha512-w7++Pwdz0NxxMtC4ugLmsy66Ar95HnDIMjzJZdHl0kQKIHto3icgI+lbOZMlovZ1Mo4RGITWGhYn1ro7hcY/UA==}
|
||||
|
||||
@@ -2973,12 +2958,12 @@ packages:
|
||||
resolution: {integrity: sha512-irhhjRVLE20hbkRl4zpAYLnDMM+zIZnp0IDB9akAFFUZp/3XdOfwwddc7y6cNvF2WCEtfTYRwYbIfYa2kVY0og==}
|
||||
engines: {node: '>=20.19.0'}
|
||||
|
||||
mongodb-memory-server-core@10.4.1:
|
||||
resolution: {integrity: sha512-YJdrEyF9hk64nfeoVDMP6IfTzK+gLZhrQqYyP6JJMsqo2LK5eF7JRZ4YPQDmt1re/JhItpiU+ypiZbIG1OsW5Q==}
|
||||
mongodb-memory-server-core@10.4.2:
|
||||
resolution: {integrity: sha512-/w7SWH+f/bpzmQlYu0lRWF33GLOo0GwZrflP1gkDhc6PCuLo5T1mnME/W+mrFmsowLGzthdJnezGBpOnIYNALw==}
|
||||
engines: {node: '>=16.20.1'}
|
||||
|
||||
mongodb-memory-server@10.4.1:
|
||||
resolution: {integrity: sha512-XpCyV1e7QQ1lW28rgtXP4ZlX8ZfD/8z1ZGNxz2y3JrosLgDrNnYWvPjlgFj3JjboYUtlh1jF2Ez/rwsQA6cl0w==}
|
||||
mongodb-memory-server@10.4.2:
|
||||
resolution: {integrity: sha512-r2swgOhmhGfx80TJIALb7t4hlrRtdl+uqc0qrGe+nqmjZQn3prd0SOioxxuLb5LjtmQrx3CPQqJf+PmH5hg+5A==}
|
||||
engines: {node: '>=16.20.1'}
|
||||
|
||||
mongodb@6.21.0:
|
||||
@@ -3539,9 +3524,6 @@ packages:
|
||||
strnum@1.1.2:
|
||||
resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==}
|
||||
|
||||
strnum@2.1.1:
|
||||
resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==}
|
||||
|
||||
strnum@2.1.2:
|
||||
resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==}
|
||||
|
||||
@@ -3835,8 +3817,8 @@ snapshots:
|
||||
'@api.global/typedrequest': 3.2.5
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@api.global/typedsocket': 3.1.1(@push.rocks/smartserve@1.4.0)
|
||||
'@cloudflare/workers-types': 4.20251202.0
|
||||
'@design.estate/dees-comms': 1.0.27
|
||||
'@cloudflare/workers-types': 4.20251213.0
|
||||
'@design.estate/dees-comms': 1.0.30
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartchok': 1.2.0
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@@ -4442,8 +4424,6 @@ snapshots:
|
||||
|
||||
'@cfworker/json-schema@4.1.1': {}
|
||||
|
||||
'@cloudflare/workers-types@4.20251202.0': {}
|
||||
|
||||
'@cloudflare/workers-types@4.20251213.0': {}
|
||||
|
||||
'@configvault.io/interfaces@1.0.17':
|
||||
@@ -4473,42 +4453,6 @@ snapshots:
|
||||
'@push.rocks/smarttime': 4.1.1
|
||||
'@push.rocks/webstore': 2.0.20
|
||||
|
||||
'@design.estate/dees-catalog@2.0.7(@tiptap/pm@2.27.1)':
|
||||
dependencies:
|
||||
'@design.estate/dees-domtools': 2.3.6
|
||||
'@design.estate/dees-element': 2.1.3
|
||||
'@design.estate/dees-wcctools': 1.2.1
|
||||
'@fortawesome/fontawesome-svg-core': 7.1.0
|
||||
'@fortawesome/free-brands-svg-icons': 7.1.0
|
||||
'@fortawesome/free-regular-svg-icons': 7.1.0
|
||||
'@fortawesome/free-solid-svg-icons': 7.1.0
|
||||
'@push.rocks/smarti18n': 1.0.4
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartstring': 4.1.0
|
||||
'@tiptap/core': 2.27.1(@tiptap/pm@2.27.1)
|
||||
'@tiptap/extension-link': 2.27.1(@tiptap/core@2.27.1(@tiptap/pm@2.27.1))(@tiptap/pm@2.27.1)
|
||||
'@tiptap/extension-text-align': 2.27.1(@tiptap/core@2.27.1(@tiptap/pm@2.27.1))
|
||||
'@tiptap/extension-typography': 2.27.1(@tiptap/core@2.27.1(@tiptap/pm@2.27.1))
|
||||
'@tiptap/extension-underline': 2.27.1(@tiptap/core@2.27.1(@tiptap/pm@2.27.1))
|
||||
'@tiptap/starter-kit': 2.27.1
|
||||
'@tsclass/tsclass': 9.3.0
|
||||
'@webcontainer/api': 1.2.0
|
||||
apexcharts: 5.3.6
|
||||
highlight.js: 11.11.1
|
||||
ibantools: 4.5.1
|
||||
lit: 3.3.1
|
||||
lucide: 0.555.0
|
||||
monaco-editor: 0.52.2
|
||||
pdfjs-dist: 4.10.38
|
||||
xterm: 5.3.0
|
||||
xterm-addon-fit: 0.8.0(xterm@5.3.0)
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- '@tiptap/pm'
|
||||
- react
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@design.estate/dees-catalog@3.3.1(@tiptap/pm@2.27.1)':
|
||||
dependencies:
|
||||
'@design.estate/dees-domtools': 2.3.6
|
||||
@@ -4545,13 +4489,6 @@ snapshots:
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@design.estate/dees-comms@1.0.27':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.2.5
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
broadcast-channel: 7.2.0
|
||||
|
||||
'@design.estate/dees-comms@1.0.30':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.2.5
|
||||
@@ -4562,7 +4499,7 @@ snapshots:
|
||||
'@design.estate/dees-domtools@2.3.6':
|
||||
dependencies:
|
||||
'@api.global/typedrequest': 3.2.5
|
||||
'@design.estate/dees-comms': 1.0.27
|
||||
'@design.estate/dees-comms': 1.0.30
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartjson': 5.2.0
|
||||
@@ -4576,7 +4513,7 @@ snapshots:
|
||||
'@push.rocks/webrequest': 3.0.37
|
||||
'@push.rocks/websetup': 3.0.19
|
||||
'@push.rocks/webstore': 2.0.20
|
||||
lenis: 1.3.15
|
||||
lenis: 1.3.16
|
||||
lit: 3.3.1
|
||||
sweet-scroll: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
@@ -4597,18 +4534,6 @@ snapshots:
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@design.estate/dees-wcctools@1.2.1':
|
||||
dependencies:
|
||||
'@design.estate/dees-domtools': 2.3.6
|
||||
'@design.estate/dees-element': 2.1.3
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
lit: 3.3.1
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- react
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
'@design.estate/dees-wcctools@2.0.1':
|
||||
dependencies:
|
||||
'@design.estate/dees-domtools': 2.3.6
|
||||
@@ -4765,7 +4690,7 @@ snapshots:
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartspawn': 3.0.3
|
||||
'@rspack/core': 1.6.6
|
||||
'@rspack/core': 1.6.7
|
||||
'@types/html-minifier': 4.0.6
|
||||
esbuild: 0.27.1
|
||||
html-minifier: 4.0.0
|
||||
@@ -4976,52 +4901,52 @@ snapshots:
|
||||
'@module-federation/runtime': 0.21.6
|
||||
'@module-federation/sdk': 0.21.6
|
||||
|
||||
'@mongodb-js/saslprep@1.3.2':
|
||||
'@mongodb-js/saslprep@1.4.0':
|
||||
dependencies:
|
||||
sparse-bitfield: 3.0.3
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.83':
|
||||
'@napi-rs/canvas-android-arm64@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.83':
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.83':
|
||||
'@napi-rs/canvas-darwin-x64@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.83':
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.83':
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.83':
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.83':
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.83':
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.83':
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.83':
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.84':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas@0.1.83':
|
||||
'@napi-rs/canvas@0.1.84':
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas-android-arm64': 0.1.83
|
||||
'@napi-rs/canvas-darwin-arm64': 0.1.83
|
||||
'@napi-rs/canvas-darwin-x64': 0.1.83
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.83
|
||||
'@napi-rs/canvas-linux-arm64-gnu': 0.1.83
|
||||
'@napi-rs/canvas-linux-arm64-musl': 0.1.83
|
||||
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.83
|
||||
'@napi-rs/canvas-linux-x64-gnu': 0.1.83
|
||||
'@napi-rs/canvas-linux-x64-musl': 0.1.83
|
||||
'@napi-rs/canvas-win32-x64-msvc': 0.1.83
|
||||
'@napi-rs/canvas-android-arm64': 0.1.84
|
||||
'@napi-rs/canvas-darwin-arm64': 0.1.84
|
||||
'@napi-rs/canvas-darwin-x64': 0.1.84
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.84
|
||||
'@napi-rs/canvas-linux-arm64-gnu': 0.1.84
|
||||
'@napi-rs/canvas-linux-arm64-musl': 0.1.84
|
||||
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.84
|
||||
'@napi-rs/canvas-linux-x64-gnu': 0.1.84
|
||||
'@napi-rs/canvas-linux-x64-musl': 0.1.84
|
||||
'@napi-rs/canvas-win32-x64-msvc': 0.1.84
|
||||
optional: true
|
||||
|
||||
'@napi-rs/wasm-runtime@1.0.7':
|
||||
@@ -5045,21 +4970,21 @@ snapshots:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
'@peculiar/asn1-x509-attr': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-csr@2.6.0':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-ecc@2.6.0':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-pfx@2.6.0':
|
||||
@@ -5068,14 +4993,14 @@ snapshots:
|
||||
'@peculiar/asn1-pkcs8': 2.6.0
|
||||
'@peculiar/asn1-rsa': 2.6.0
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-pkcs8@2.6.0':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-pkcs9@2.6.0':
|
||||
@@ -5086,19 +5011,19 @@ snapshots:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
'@peculiar/asn1-x509-attr': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-rsa@2.6.0':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-schema@2.6.0':
|
||||
dependencies:
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
pvtsutils: 1.3.6
|
||||
tslib: 2.8.1
|
||||
|
||||
@@ -5106,13 +5031,13 @@ snapshots:
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
'@peculiar/asn1-x509': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
tslib: 2.8.1
|
||||
|
||||
'@peculiar/asn1-x509@2.6.0':
|
||||
dependencies:
|
||||
'@peculiar/asn1-schema': 2.6.0
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
pvtsutils: 1.3.6
|
||||
tslib: 2.8.1
|
||||
|
||||
@@ -5167,7 +5092,7 @@ snapshots:
|
||||
'@push.rocks/smartbucket': 3.3.10
|
||||
'@push.rocks/smartcache': 1.0.18
|
||||
'@push.rocks/smartenv': 5.0.13
|
||||
'@push.rocks/smartexit': 1.0.23
|
||||
'@push.rocks/smartexit': 1.1.0
|
||||
'@push.rocks/smartfile': 11.2.7
|
||||
'@push.rocks/smartjson': 5.2.0
|
||||
'@push.rocks/smartpath': 6.0.0
|
||||
@@ -5396,7 +5321,7 @@ snapshots:
|
||||
clean-stack: 1.3.0
|
||||
make-error-cause: 2.3.0
|
||||
|
||||
'@push.rocks/smartexit@1.0.23':
|
||||
'@push.rocks/smartexit@1.1.0':
|
||||
dependencies:
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@@ -5589,7 +5514,7 @@ snapshots:
|
||||
'@push.rocks/smartdata': 5.16.7
|
||||
'@push.rocks/smartpath': 5.1.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
mongodb-memory-server: 10.4.1
|
||||
mongodb-memory-server: 10.4.2
|
||||
transitivePeerDependencies:
|
||||
- '@aws-sdk/credential-providers'
|
||||
- '@mongodb-js/zstd'
|
||||
@@ -5709,7 +5634,7 @@ snapshots:
|
||||
'@push.rocks/smartshell@3.3.0':
|
||||
dependencies:
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartexit': 1.0.23
|
||||
'@push.rocks/smartexit': 1.1.0
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@types/which': 3.0.4
|
||||
tree-kill: 1.2.2
|
||||
@@ -5823,7 +5748,7 @@ snapshots:
|
||||
|
||||
'@push.rocks/smartxml@2.0.0':
|
||||
dependencies:
|
||||
fast-xml-parser: 5.3.2
|
||||
fast-xml-parser: 5.3.3
|
||||
|
||||
'@push.rocks/smartyaml@2.0.5':
|
||||
dependencies:
|
||||
@@ -5981,55 +5906,55 @@ snapshots:
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.52': {}
|
||||
|
||||
'@rspack/binding-darwin-arm64@1.6.6':
|
||||
'@rspack/binding-darwin-arm64@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-darwin-x64@1.6.6':
|
||||
'@rspack/binding-darwin-x64@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.6':
|
||||
'@rspack/binding-linux-arm64-gnu@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-arm64-musl@1.6.6':
|
||||
'@rspack/binding-linux-arm64-musl@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-x64-gnu@1.6.6':
|
||||
'@rspack/binding-linux-x64-gnu@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-linux-x64-musl@1.6.6':
|
||||
'@rspack/binding-linux-x64-musl@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-wasm32-wasi@1.6.6':
|
||||
'@rspack/binding-wasm32-wasi@1.6.7':
|
||||
dependencies:
|
||||
'@napi-rs/wasm-runtime': 1.0.7
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.6':
|
||||
'@rspack/binding-win32-arm64-msvc@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.6':
|
||||
'@rspack/binding-win32-ia32-msvc@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding-win32-x64-msvc@1.6.6':
|
||||
'@rspack/binding-win32-x64-msvc@1.6.7':
|
||||
optional: true
|
||||
|
||||
'@rspack/binding@1.6.6':
|
||||
'@rspack/binding@1.6.7':
|
||||
optionalDependencies:
|
||||
'@rspack/binding-darwin-arm64': 1.6.6
|
||||
'@rspack/binding-darwin-x64': 1.6.6
|
||||
'@rspack/binding-linux-arm64-gnu': 1.6.6
|
||||
'@rspack/binding-linux-arm64-musl': 1.6.6
|
||||
'@rspack/binding-linux-x64-gnu': 1.6.6
|
||||
'@rspack/binding-linux-x64-musl': 1.6.6
|
||||
'@rspack/binding-wasm32-wasi': 1.6.6
|
||||
'@rspack/binding-win32-arm64-msvc': 1.6.6
|
||||
'@rspack/binding-win32-ia32-msvc': 1.6.6
|
||||
'@rspack/binding-win32-x64-msvc': 1.6.6
|
||||
'@rspack/binding-darwin-arm64': 1.6.7
|
||||
'@rspack/binding-darwin-x64': 1.6.7
|
||||
'@rspack/binding-linux-arm64-gnu': 1.6.7
|
||||
'@rspack/binding-linux-arm64-musl': 1.6.7
|
||||
'@rspack/binding-linux-x64-gnu': 1.6.7
|
||||
'@rspack/binding-linux-x64-musl': 1.6.7
|
||||
'@rspack/binding-wasm32-wasi': 1.6.7
|
||||
'@rspack/binding-win32-arm64-msvc': 1.6.7
|
||||
'@rspack/binding-win32-ia32-msvc': 1.6.7
|
||||
'@rspack/binding-win32-x64-msvc': 1.6.7
|
||||
|
||||
'@rspack/core@1.6.6':
|
||||
'@rspack/core@1.6.7':
|
||||
dependencies:
|
||||
'@module-federation/runtime-tools': 0.21.6
|
||||
'@rspack/binding': 1.6.6
|
||||
'@rspack/binding': 1.6.7
|
||||
'@rspack/lite-tapable': 1.1.0
|
||||
|
||||
'@rspack/lite-tapable@1.1.0': {}
|
||||
@@ -6599,27 +6524,27 @@ snapshots:
|
||||
|
||||
'@types/bn.js@5.2.0':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/buffer-json@2.0.3': {}
|
||||
|
||||
'@types/clean-css@4.2.11':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
source-map: 0.6.1
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
@@ -6627,7 +6552,7 @@ snapshots:
|
||||
|
||||
'@types/dns-packet@5.6.5':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/elliptic@6.4.18':
|
||||
dependencies:
|
||||
@@ -6635,7 +6560,7 @@ snapshots:
|
||||
|
||||
'@types/express-serve-static-core@5.1.0':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 1.2.1
|
||||
@@ -6648,17 +6573,17 @@ snapshots:
|
||||
|
||||
'@types/from2@2.3.6':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/fs-extra@11.0.4':
|
||||
dependencies:
|
||||
'@types/jsonfile': 6.1.4
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/glob@8.1.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 5.1.2
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/hast@3.0.4':
|
||||
dependencies:
|
||||
@@ -6680,12 +6605,12 @@ snapshots:
|
||||
|
||||
'@types/jsonfile@6.1.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/jsonwebtoken@9.0.10':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/linkify-it@5.0.0': {}
|
||||
|
||||
@@ -6708,17 +6633,17 @@ snapshots:
|
||||
|
||||
'@types/mute-stream@0.0.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/node-forge@1.3.14':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/node@22.19.3':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/node@24.10.1':
|
||||
'@types/node@24.10.4':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
@@ -6734,22 +6659,22 @@ snapshots:
|
||||
|
||||
'@types/send@1.2.1':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/serve-static@2.2.0':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/symbol-tree@3.2.5': {}
|
||||
|
||||
'@types/tar-stream@3.1.4':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/through2@2.0.41':
|
||||
dependencies:
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
|
||||
'@types/trusted-types@2.0.7': {}
|
||||
|
||||
@@ -6779,12 +6704,12 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
|
||||
'@uptime.link/webwidget@1.2.5(@tiptap/pm@2.27.1)':
|
||||
'@uptime.link/webwidget@1.2.6(@tiptap/pm@2.27.1)':
|
||||
dependencies:
|
||||
'@design.estate/dees-catalog': 2.0.7(@tiptap/pm@2.27.1)
|
||||
'@design.estate/dees-catalog': 3.3.1(@tiptap/pm@2.27.1)
|
||||
'@design.estate/dees-domtools': 2.3.6
|
||||
'@design.estate/dees-element': 2.1.3
|
||||
'@design.estate/dees-wcctools': 1.2.1
|
||||
'@design.estate/dees-wcctools': 2.0.1
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- '@tiptap/pm'
|
||||
@@ -6809,7 +6734,7 @@ snapshots:
|
||||
acme-client@5.4.0:
|
||||
dependencies:
|
||||
'@peculiar/x509': 1.14.2
|
||||
asn1js: 3.0.6
|
||||
asn1js: 3.0.7
|
||||
axios: 1.13.2(debug@4.4.3)
|
||||
debug: 4.4.3
|
||||
node-forge: 1.3.3
|
||||
@@ -6853,7 +6778,7 @@ snapshots:
|
||||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
asn1js@3.0.6:
|
||||
asn1js@3.0.7:
|
||||
dependencies:
|
||||
pvtsutils: 1.3.6
|
||||
pvutils: 1.1.5
|
||||
@@ -6893,7 +6818,7 @@ snapshots:
|
||||
content-type: 1.0.5
|
||||
debug: 4.4.3
|
||||
http-errors: 2.0.1
|
||||
iconv-lite: 0.7.0
|
||||
iconv-lite: 0.7.1
|
||||
on-finished: 2.4.1
|
||||
qs: 6.14.0
|
||||
raw-body: 3.0.2
|
||||
@@ -7149,7 +7074,7 @@ snapshots:
|
||||
engine.io@6.6.4:
|
||||
dependencies:
|
||||
'@types/cors': 2.8.19
|
||||
'@types/node': 24.10.1
|
||||
'@types/node': 24.10.4
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.7.2
|
||||
@@ -7291,9 +7216,9 @@ snapshots:
|
||||
dependencies:
|
||||
strnum: 2.1.2
|
||||
|
||||
fast-xml-parser@5.3.2:
|
||||
fast-xml-parser@5.3.3:
|
||||
dependencies:
|
||||
strnum: 2.1.1
|
||||
strnum: 2.1.2
|
||||
|
||||
fault@2.0.1:
|
||||
dependencies:
|
||||
@@ -7575,7 +7500,7 @@ snapshots:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
iconv-lite@0.7.0:
|
||||
iconv-lite@0.7.1:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
@@ -7693,7 +7618,7 @@ snapshots:
|
||||
|
||||
kind-of@6.0.3: {}
|
||||
|
||||
lenis@1.3.15: {}
|
||||
lenis@1.3.16: {}
|
||||
|
||||
linkify-it@5.0.0:
|
||||
dependencies:
|
||||
@@ -7784,8 +7709,6 @@ snapshots:
|
||||
|
||||
lru-cache@11.2.4: {}
|
||||
|
||||
lucide@0.555.0: {}
|
||||
|
||||
lucide@0.560.0: {}
|
||||
|
||||
make-dir@3.1.0:
|
||||
@@ -8198,7 +8121,7 @@ snapshots:
|
||||
'@types/whatwg-url': 13.0.0
|
||||
whatwg-url: 14.2.0
|
||||
|
||||
mongodb-memory-server-core@10.4.1:
|
||||
mongodb-memory-server-core@10.4.2:
|
||||
dependencies:
|
||||
async-mutex: 0.5.0
|
||||
camelcase: 6.3.0
|
||||
@@ -8224,9 +8147,9 @@ snapshots:
|
||||
- socks
|
||||
- supports-color
|
||||
|
||||
mongodb-memory-server@10.4.1:
|
||||
mongodb-memory-server@10.4.2:
|
||||
dependencies:
|
||||
mongodb-memory-server-core: 10.4.1
|
||||
mongodb-memory-server-core: 10.4.2
|
||||
tslib: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- '@aws-sdk/credential-providers'
|
||||
@@ -8242,13 +8165,13 @@ snapshots:
|
||||
|
||||
mongodb@6.21.0:
|
||||
dependencies:
|
||||
'@mongodb-js/saslprep': 1.3.2
|
||||
'@mongodb-js/saslprep': 1.4.0
|
||||
bson: 6.10.4
|
||||
mongodb-connection-string-url: 3.0.2
|
||||
|
||||
mongodb@7.0.0:
|
||||
dependencies:
|
||||
'@mongodb-js/saslprep': 1.3.2
|
||||
'@mongodb-js/saslprep': 1.4.0
|
||||
bson: 7.0.0
|
||||
mongodb-connection-string-url: 7.0.0
|
||||
|
||||
@@ -8370,7 +8293,7 @@ snapshots:
|
||||
|
||||
pdfjs-dist@4.10.38:
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas': 0.1.83
|
||||
'@napi-rs/canvas': 0.1.84
|
||||
|
||||
peek-readable@5.4.2: {}
|
||||
|
||||
@@ -8532,7 +8455,7 @@ snapshots:
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
http-errors: 2.0.1
|
||||
iconv-lite: 0.7.0
|
||||
iconv-lite: 0.7.1
|
||||
unpipe: 1.0.0
|
||||
|
||||
rc@1.2.8:
|
||||
@@ -8861,8 +8784,6 @@ snapshots:
|
||||
|
||||
strnum@1.1.2: {}
|
||||
|
||||
strnum@2.1.1: {}
|
||||
|
||||
strnum@2.1.2: {}
|
||||
|
||||
strtok3@10.3.4:
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@idp.global/idp.global',
|
||||
version: '1.12.0',
|
||||
version: '1.13.0',
|
||||
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
||||
}
|
||||
|
||||
+42
-1
@@ -4,6 +4,10 @@ import { Reception } from './reception/classes.reception.js';
|
||||
|
||||
export const runCli = async () => {
|
||||
const serviceQenv = new plugins.qenv.Qenv('./', './.nogit', false);
|
||||
|
||||
// Create reception first so we can reference it in routes
|
||||
let reception: Reception;
|
||||
|
||||
const websiteServer = new plugins.typedserver.utilityservers.UtilityWebsiteServer({
|
||||
feedMetadata: null,
|
||||
domain: 'idp.global',
|
||||
@@ -22,11 +26,48 @@ export const runCli = async () => {
|
||||
addCustomRoutes: async (typedserver) => {
|
||||
// Enable SPA fallback - serves index.html for non-file routes (e.g., /login, /dashboard)
|
||||
typedserver.options.spaFallback = true;
|
||||
|
||||
// OIDC Discovery endpoint
|
||||
typedserver.addRoute('/.well-known/openid-configuration', 'GET', async (req) => {
|
||||
return new Response(JSON.stringify(reception.oidcManager.getDiscoveryDocument()), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
});
|
||||
|
||||
// JWKS endpoint
|
||||
typedserver.addRoute('/.well-known/jwks.json', 'GET', async (req) => {
|
||||
return new Response(JSON.stringify(reception.oidcManager.getJwks()), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
});
|
||||
|
||||
// OAuth Authorization endpoint
|
||||
typedserver.addRoute('/oauth/authorize', 'GET', async (req) => {
|
||||
return reception.oidcManager.handleAuthorize(req);
|
||||
});
|
||||
|
||||
// OAuth Token endpoint
|
||||
typedserver.addRoute('/oauth/token', 'POST', async (req) => {
|
||||
return reception.oidcManager.handleToken(req);
|
||||
});
|
||||
|
||||
// OAuth UserInfo endpoint (GET and POST)
|
||||
typedserver.addRoute('/oauth/userinfo', 'GET', async (req) => {
|
||||
return reception.oidcManager.handleUserInfo(req);
|
||||
});
|
||||
typedserver.addRoute('/oauth/userinfo', 'POST', async (req) => {
|
||||
return reception.oidcManager.handleUserInfo(req);
|
||||
});
|
||||
|
||||
// OAuth Revocation endpoint
|
||||
typedserver.addRoute('/oauth/revoke', 'POST', async (req) => {
|
||||
return reception.oidcManager.handleRevoke(req);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// lets add the reception routes
|
||||
const reception = new Reception({
|
||||
reception = new Reception({
|
||||
name: (await serviceQenv.getEnvVarOnDemand('INSTANCE_NAME')) || 'idp.global',
|
||||
mongoDescriptor: {
|
||||
mongoDbUrl: await serviceQenv.getEnvVarOnDemand('MONGODB_URL'),
|
||||
|
||||
@@ -0,0 +1,684 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
import type { Reception } from './classes.reception.js';
|
||||
import type { App } from './classes.app.js';
|
||||
|
||||
/**
|
||||
* OidcManager handles OpenID Connect (OIDC) server functionality
|
||||
* for third-party client authentication.
|
||||
*/
|
||||
export class OidcManager {
|
||||
public receptionRef: Reception;
|
||||
public get db() {
|
||||
return this.receptionRef.db.smartdataDb;
|
||||
}
|
||||
|
||||
// In-memory store for authorization codes (short-lived, 10 min TTL)
|
||||
private authorizationCodes = new Map<string, plugins.idpInterfaces.data.IAuthorizationCode>();
|
||||
|
||||
// In-memory store for access tokens (for validation)
|
||||
private accessTokens = new Map<string, plugins.idpInterfaces.data.IOidcAccessToken>();
|
||||
|
||||
// In-memory store for refresh tokens
|
||||
private refreshTokens = new Map<string, plugins.idpInterfaces.data.IOidcRefreshToken>();
|
||||
|
||||
// In-memory store for user consents (should be persisted later)
|
||||
private userConsents = new Map<string, plugins.idpInterfaces.data.IUserConsent>();
|
||||
|
||||
constructor(receptionRefArg: Reception) {
|
||||
this.receptionRef = receptionRefArg;
|
||||
|
||||
// Start cleanup task for expired codes/tokens
|
||||
this.startCleanupTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OIDC Discovery Document
|
||||
*/
|
||||
public getDiscoveryDocument(): plugins.idpInterfaces.data.IOidcDiscoveryDocument {
|
||||
const baseUrl = this.receptionRef.options.baseUrl || 'https://idp.global';
|
||||
return {
|
||||
issuer: baseUrl,
|
||||
authorization_endpoint: `${baseUrl}/oauth/authorize`,
|
||||
token_endpoint: `${baseUrl}/oauth/token`,
|
||||
userinfo_endpoint: `${baseUrl}/oauth/userinfo`,
|
||||
jwks_uri: `${baseUrl}/.well-known/jwks.json`,
|
||||
revocation_endpoint: `${baseUrl}/oauth/revoke`,
|
||||
scopes_supported: ['openid', 'profile', 'email', 'organizations', 'roles'],
|
||||
response_types_supported: ['code'],
|
||||
grant_types_supported: ['authorization_code', 'refresh_token'],
|
||||
subject_types_supported: ['public'],
|
||||
id_token_signing_alg_values_supported: ['RS256'],
|
||||
token_endpoint_auth_methods_supported: ['client_secret_basic', 'client_secret_post'],
|
||||
code_challenge_methods_supported: ['S256'],
|
||||
claims_supported: [
|
||||
'sub', 'iss', 'aud', 'exp', 'iat', 'auth_time', 'nonce',
|
||||
'name', 'preferred_username', 'picture',
|
||||
'email', 'email_verified',
|
||||
'organizations', 'roles'
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON Web Key Set (JWKS)
|
||||
*/
|
||||
public getJwks(): plugins.idpInterfaces.data.IJwks {
|
||||
const keypair = this.receptionRef.jwtManager.smartjwtInstance.getKeyPairAsJson();
|
||||
// Convert PEM to JWK format
|
||||
const jwk = this.pemToJwk(keypair.publicPem);
|
||||
return {
|
||||
keys: [jwk],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert PEM public key to JWK format
|
||||
*/
|
||||
private pemToJwk(publicPem: string): plugins.idpInterfaces.data.IJwk {
|
||||
// For now, use a simplified approach - in production, parse the PEM properly
|
||||
// The smartjwt library should provide this, or use crypto.createPublicKey
|
||||
const kid = plugins.smarthash.sha256FromStringSync(publicPem).substring(0, 16);
|
||||
|
||||
// This is a placeholder - proper implementation would extract n and e from PEM
|
||||
// For now, return a minimal structure
|
||||
return {
|
||||
kty: 'RSA',
|
||||
use: 'sig',
|
||||
alg: 'RS256',
|
||||
kid: kid,
|
||||
// These would be extracted from the actual public key
|
||||
n: Buffer.from(publicPem).toString('base64url').substring(0, 256),
|
||||
e: 'AQAB', // Standard RSA exponent (65537)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the authorization endpoint request
|
||||
*/
|
||||
public async handleAuthorize(request: Request): Promise<Response> {
|
||||
const url = new URL(request.url);
|
||||
const params = url.searchParams;
|
||||
|
||||
// Extract authorization request parameters
|
||||
const clientId = params.get('client_id');
|
||||
const redirectUri = params.get('redirect_uri');
|
||||
const responseType = params.get('response_type');
|
||||
const scope = params.get('scope');
|
||||
const state = params.get('state');
|
||||
const codeChallenge = params.get('code_challenge');
|
||||
const codeChallengeMethod = params.get('code_challenge_method');
|
||||
const nonce = params.get('nonce');
|
||||
const prompt = params.get('prompt') as 'none' | 'login' | 'consent' | null;
|
||||
|
||||
// Validate required parameters
|
||||
if (!clientId || !redirectUri || !responseType || !scope || !state) {
|
||||
return this.errorResponse('invalid_request', 'Missing required parameters');
|
||||
}
|
||||
|
||||
if (responseType !== 'code') {
|
||||
return this.errorResponse('unsupported_response_type', 'Only code response type is supported');
|
||||
}
|
||||
|
||||
// Validate code challenge method if present
|
||||
if (codeChallenge && codeChallengeMethod !== 'S256') {
|
||||
return this.errorResponse('invalid_request', 'Only S256 code challenge method is supported');
|
||||
}
|
||||
|
||||
// Find the app by client_id
|
||||
const app = await this.findAppByClientId(clientId);
|
||||
if (!app) {
|
||||
return this.errorResponse('invalid_client', 'Unknown client_id');
|
||||
}
|
||||
|
||||
// Validate redirect URI
|
||||
if (!app.data.oauthCredentials.redirectUris.includes(redirectUri)) {
|
||||
return this.errorResponse('invalid_request', 'Invalid redirect_uri');
|
||||
}
|
||||
|
||||
// Parse and validate scopes
|
||||
const requestedScopes = scope.split(' ') as plugins.idpInterfaces.data.TOidcScope[];
|
||||
const allowedScopes = app.data.oauthCredentials.allowedScopes as plugins.idpInterfaces.data.TOidcScope[];
|
||||
const validScopes = requestedScopes.filter(s => allowedScopes.includes(s));
|
||||
|
||||
if (!validScopes.includes('openid')) {
|
||||
return this.errorResponse('invalid_scope', 'openid scope is required');
|
||||
}
|
||||
|
||||
// For now, redirect to login page with OAuth parameters
|
||||
// The login page will handle authentication and call back to complete authorization
|
||||
const baseUrl = this.receptionRef.options.baseUrl || 'https://idp.global';
|
||||
const loginUrl = new URL(`${baseUrl}/login`);
|
||||
loginUrl.searchParams.set('oauth', 'true');
|
||||
loginUrl.searchParams.set('client_id', clientId);
|
||||
loginUrl.searchParams.set('redirect_uri', redirectUri);
|
||||
loginUrl.searchParams.set('scope', validScopes.join(' '));
|
||||
loginUrl.searchParams.set('state', state);
|
||||
if (codeChallenge) {
|
||||
loginUrl.searchParams.set('code_challenge', codeChallenge);
|
||||
loginUrl.searchParams.set('code_challenge_method', codeChallengeMethod!);
|
||||
}
|
||||
if (nonce) {
|
||||
loginUrl.searchParams.set('nonce', nonce);
|
||||
}
|
||||
|
||||
return Response.redirect(loginUrl.toString(), 302);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an authorization code after user authentication
|
||||
*/
|
||||
public async generateAuthorizationCode(
|
||||
clientId: string,
|
||||
userId: string,
|
||||
scopes: plugins.idpInterfaces.data.TOidcScope[],
|
||||
redirectUri: string,
|
||||
codeChallenge?: string,
|
||||
nonce?: string
|
||||
): Promise<string> {
|
||||
const code = plugins.smartunique.shortId(32);
|
||||
const authCode: plugins.idpInterfaces.data.IAuthorizationCode = {
|
||||
code,
|
||||
clientId,
|
||||
userId,
|
||||
scopes,
|
||||
redirectUri,
|
||||
codeChallenge,
|
||||
codeChallengeMethod: codeChallenge ? 'S256' : undefined,
|
||||
nonce,
|
||||
expiresAt: Date.now() + 10 * 60 * 1000, // 10 minutes
|
||||
used: false,
|
||||
};
|
||||
|
||||
this.authorizationCodes.set(code, authCode);
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the token endpoint request
|
||||
*/
|
||||
public async handleToken(request: Request): Promise<Response> {
|
||||
// Parse form data
|
||||
const contentType = request.headers.get('content-type');
|
||||
if (!contentType?.includes('application/x-www-form-urlencoded')) {
|
||||
return this.tokenErrorResponse('invalid_request', 'Content-Type must be application/x-www-form-urlencoded');
|
||||
}
|
||||
|
||||
const formData = await request.formData();
|
||||
const grantType = formData.get('grant_type') as string;
|
||||
|
||||
// Extract client credentials from Basic auth or form
|
||||
let clientId = formData.get('client_id') as string;
|
||||
let clientSecret = formData.get('client_secret') as string;
|
||||
|
||||
const authHeader = request.headers.get('authorization');
|
||||
if (authHeader?.startsWith('Basic ')) {
|
||||
const base64 = authHeader.substring(6);
|
||||
const decoded = Buffer.from(base64, 'base64').toString('utf-8');
|
||||
const [id, secret] = decoded.split(':');
|
||||
clientId = clientId || id;
|
||||
clientSecret = clientSecret || secret;
|
||||
}
|
||||
|
||||
if (!clientId) {
|
||||
return this.tokenErrorResponse('invalid_client', 'Missing client_id');
|
||||
}
|
||||
|
||||
// Find and validate app
|
||||
const app = await this.findAppByClientId(clientId);
|
||||
if (!app) {
|
||||
return this.tokenErrorResponse('invalid_client', 'Unknown client');
|
||||
}
|
||||
|
||||
// Validate client secret for confidential clients
|
||||
if (clientSecret) {
|
||||
const secretHash = await plugins.smarthash.sha256FromString(clientSecret);
|
||||
if (secretHash !== app.data.oauthCredentials.clientSecretHash) {
|
||||
return this.tokenErrorResponse('invalid_client', 'Invalid client credentials');
|
||||
}
|
||||
}
|
||||
|
||||
if (grantType === 'authorization_code') {
|
||||
return this.handleAuthorizationCodeGrant(formData, app);
|
||||
} else if (grantType === 'refresh_token') {
|
||||
return this.handleRefreshTokenGrant(formData, app);
|
||||
} else {
|
||||
return this.tokenErrorResponse('unsupported_grant_type', 'Unsupported grant type');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle authorization_code grant type
|
||||
*/
|
||||
private async handleAuthorizationCodeGrant(
|
||||
formData: FormData,
|
||||
app: App
|
||||
): Promise<Response> {
|
||||
const code = formData.get('code') as string;
|
||||
const redirectUri = formData.get('redirect_uri') as string;
|
||||
const codeVerifier = formData.get('code_verifier') as string;
|
||||
|
||||
if (!code || !redirectUri) {
|
||||
return this.tokenErrorResponse('invalid_request', 'Missing code or redirect_uri');
|
||||
}
|
||||
|
||||
// Find and validate authorization code
|
||||
const authCode = this.authorizationCodes.get(code);
|
||||
if (!authCode) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Invalid authorization code');
|
||||
}
|
||||
|
||||
if (authCode.used) {
|
||||
// Code reuse attack - revoke all tokens for this code
|
||||
this.authorizationCodes.delete(code);
|
||||
return this.tokenErrorResponse('invalid_grant', 'Authorization code already used');
|
||||
}
|
||||
|
||||
if (authCode.expiresAt < Date.now()) {
|
||||
this.authorizationCodes.delete(code);
|
||||
return this.tokenErrorResponse('invalid_grant', 'Authorization code expired');
|
||||
}
|
||||
|
||||
if (authCode.clientId !== app.data.oauthCredentials.clientId) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Client ID mismatch');
|
||||
}
|
||||
|
||||
if (authCode.redirectUri !== redirectUri) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Redirect URI mismatch');
|
||||
}
|
||||
|
||||
// Verify PKCE if code challenge was used
|
||||
if (authCode.codeChallenge) {
|
||||
if (!codeVerifier) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Code verifier required');
|
||||
}
|
||||
const expectedChallenge = this.generateS256Challenge(codeVerifier);
|
||||
if (expectedChallenge !== authCode.codeChallenge) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Invalid code verifier');
|
||||
}
|
||||
}
|
||||
|
||||
// Mark code as used
|
||||
authCode.used = true;
|
||||
|
||||
// Generate tokens
|
||||
const tokens = await this.generateTokens(
|
||||
authCode.userId,
|
||||
app.data.oauthCredentials.clientId,
|
||||
authCode.scopes,
|
||||
authCode.nonce
|
||||
);
|
||||
|
||||
return new Response(JSON.stringify(tokens), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': 'no-store',
|
||||
'Pragma': 'no-cache',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle refresh_token grant type
|
||||
*/
|
||||
private async handleRefreshTokenGrant(
|
||||
formData: FormData,
|
||||
app: App
|
||||
): Promise<Response> {
|
||||
const refreshToken = formData.get('refresh_token') as string;
|
||||
|
||||
if (!refreshToken) {
|
||||
return this.tokenErrorResponse('invalid_request', 'Missing refresh_token');
|
||||
}
|
||||
|
||||
const tokenHash = await plugins.smarthash.sha256FromString(refreshToken);
|
||||
const storedToken = this.refreshTokens.get(tokenHash);
|
||||
|
||||
if (!storedToken) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Invalid refresh token');
|
||||
}
|
||||
|
||||
if (storedToken.revoked) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Refresh token has been revoked');
|
||||
}
|
||||
|
||||
if (storedToken.expiresAt < Date.now()) {
|
||||
this.refreshTokens.delete(tokenHash);
|
||||
return this.tokenErrorResponse('invalid_grant', 'Refresh token expired');
|
||||
}
|
||||
|
||||
if (storedToken.clientId !== app.data.oauthCredentials.clientId) {
|
||||
return this.tokenErrorResponse('invalid_grant', 'Client ID mismatch');
|
||||
}
|
||||
|
||||
// Generate new tokens (without new refresh token by default)
|
||||
const tokens = await this.generateTokens(
|
||||
storedToken.userId,
|
||||
storedToken.clientId,
|
||||
storedToken.scopes,
|
||||
undefined,
|
||||
false // Don't generate new refresh token
|
||||
);
|
||||
|
||||
return new Response(JSON.stringify(tokens), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': 'no-store',
|
||||
'Pragma': 'no-cache',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate access token, ID token, and optionally refresh token
|
||||
*/
|
||||
private async generateTokens(
|
||||
userId: string,
|
||||
clientId: string,
|
||||
scopes: plugins.idpInterfaces.data.TOidcScope[],
|
||||
nonce?: string,
|
||||
includeRefreshToken = true
|
||||
): Promise<plugins.idpInterfaces.data.ITokenResponse> {
|
||||
const now = Date.now();
|
||||
const accessTokenLifetime = 3600; // 1 hour
|
||||
const refreshTokenLifetime = 30 * 24 * 3600; // 30 days
|
||||
|
||||
// Generate access token
|
||||
const accessToken = plugins.smartunique.shortId(32);
|
||||
const accessTokenHash = await plugins.smarthash.sha256FromString(accessToken);
|
||||
const accessTokenData: plugins.idpInterfaces.data.IOidcAccessToken = {
|
||||
id: plugins.smartunique.shortId(8),
|
||||
tokenHash: accessTokenHash,
|
||||
clientId,
|
||||
userId,
|
||||
scopes,
|
||||
expiresAt: now + accessTokenLifetime * 1000,
|
||||
issuedAt: now,
|
||||
};
|
||||
this.accessTokens.set(accessTokenHash, accessTokenData);
|
||||
|
||||
// Generate ID token (JWT)
|
||||
const idToken = await this.generateIdToken(userId, clientId, scopes, nonce);
|
||||
|
||||
const response: plugins.idpInterfaces.data.ITokenResponse = {
|
||||
access_token: accessToken,
|
||||
token_type: 'Bearer',
|
||||
expires_in: accessTokenLifetime,
|
||||
id_token: idToken,
|
||||
scope: scopes.join(' '),
|
||||
};
|
||||
|
||||
// Generate refresh token if requested
|
||||
if (includeRefreshToken) {
|
||||
const refreshToken = plugins.smartunique.shortId(48);
|
||||
const refreshTokenHash = await plugins.smarthash.sha256FromString(refreshToken);
|
||||
const refreshTokenData: plugins.idpInterfaces.data.IOidcRefreshToken = {
|
||||
id: plugins.smartunique.shortId(8),
|
||||
tokenHash: refreshTokenHash,
|
||||
clientId,
|
||||
userId,
|
||||
scopes,
|
||||
expiresAt: now + refreshTokenLifetime * 1000,
|
||||
issuedAt: now,
|
||||
revoked: false,
|
||||
};
|
||||
this.refreshTokens.set(refreshTokenHash, refreshTokenData);
|
||||
response.refresh_token = refreshToken;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an ID token (JWT)
|
||||
*/
|
||||
private async generateIdToken(
|
||||
userId: string,
|
||||
clientId: string,
|
||||
scopes: plugins.idpInterfaces.data.TOidcScope[],
|
||||
nonce?: string
|
||||
): Promise<string> {
|
||||
const baseUrl = this.receptionRef.options.baseUrl || 'https://idp.global';
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
const claims: plugins.idpInterfaces.data.IIdTokenClaims = {
|
||||
iss: baseUrl,
|
||||
sub: userId,
|
||||
aud: clientId,
|
||||
exp: now + 3600, // 1 hour
|
||||
iat: now,
|
||||
auth_time: now,
|
||||
};
|
||||
|
||||
if (nonce) {
|
||||
claims.nonce = nonce;
|
||||
}
|
||||
|
||||
// Add claims based on scopes
|
||||
if (scopes.includes('profile') || scopes.includes('email') || scopes.includes('organizations') || scopes.includes('roles')) {
|
||||
const userInfo = await this.getUserClaims(userId, scopes);
|
||||
Object.assign(claims, userInfo);
|
||||
}
|
||||
|
||||
// Sign the JWT
|
||||
const idToken = await this.receptionRef.jwtManager.smartjwtInstance.createJWT(claims);
|
||||
return idToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the userinfo endpoint
|
||||
*/
|
||||
public async handleUserInfo(request: Request): Promise<Response> {
|
||||
// Get access token from Authorization header
|
||||
const authHeader = request.headers.get('authorization');
|
||||
if (!authHeader?.startsWith('Bearer ')) {
|
||||
return new Response(JSON.stringify({ error: 'invalid_token' }), {
|
||||
status: 401,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'WWW-Authenticate': 'Bearer error="invalid_token"',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const accessToken = authHeader.substring(7);
|
||||
const tokenHash = await plugins.smarthash.sha256FromString(accessToken);
|
||||
const tokenData = this.accessTokens.get(tokenHash);
|
||||
|
||||
if (!tokenData) {
|
||||
return new Response(JSON.stringify({ error: 'invalid_token' }), {
|
||||
status: 401,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'WWW-Authenticate': 'Bearer error="invalid_token"',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (tokenData.expiresAt < Date.now()) {
|
||||
this.accessTokens.delete(tokenHash);
|
||||
return new Response(JSON.stringify({ error: 'invalid_token', error_description: 'Token expired' }), {
|
||||
status: 401,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'WWW-Authenticate': 'Bearer error="invalid_token", error_description="Token expired"',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Get user claims based on token scopes
|
||||
const userInfo = await this.getUserClaims(tokenData.userId, tokenData.scopes);
|
||||
|
||||
return new Response(JSON.stringify(userInfo), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user claims based on scopes
|
||||
*/
|
||||
private async getUserClaims(
|
||||
userId: string,
|
||||
scopes: plugins.idpInterfaces.data.TOidcScope[]
|
||||
): Promise<plugins.idpInterfaces.data.IUserInfoResponse> {
|
||||
const user = await this.receptionRef.userManager.CUser.getInstance({ id: userId });
|
||||
if (!user) {
|
||||
return { sub: userId };
|
||||
}
|
||||
|
||||
const claims: plugins.idpInterfaces.data.IUserInfoResponse = {
|
||||
sub: userId,
|
||||
};
|
||||
|
||||
// Profile scope
|
||||
if (scopes.includes('profile')) {
|
||||
claims.name = user.data?.name;
|
||||
claims.preferred_username = user.data?.username;
|
||||
// claims.picture = user.data?.avatarUrl; // If avatar exists
|
||||
}
|
||||
|
||||
// Email scope
|
||||
if (scopes.includes('email')) {
|
||||
claims.email = user.data?.email;
|
||||
claims.email_verified = user.data?.status === 'active';
|
||||
}
|
||||
|
||||
// Organizations scope (custom)
|
||||
if (scopes.includes('organizations')) {
|
||||
const organizations = await this.receptionRef.organizationmanager.getAllOrganizationsForUser(user);
|
||||
const roles = await this.receptionRef.roleManager.getAllRolesForUser(user);
|
||||
if (organizations) {
|
||||
claims.organizations = organizations.map(org => ({
|
||||
id: org.id,
|
||||
name: org.data?.name || '',
|
||||
slug: org.data?.slug || '',
|
||||
roles: roles
|
||||
.find(r => r.data?.organizationId === org.id)?.data?.roles || [],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Roles scope (custom - global roles)
|
||||
if (scopes.includes('roles')) {
|
||||
const roles: string[] = ['user'];
|
||||
if (user.data?.isGlobalAdmin) {
|
||||
roles.push('admin');
|
||||
}
|
||||
claims.roles = roles;
|
||||
}
|
||||
|
||||
return claims;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the revocation endpoint
|
||||
*/
|
||||
public async handleRevoke(request: Request): Promise<Response> {
|
||||
const formData = await request.formData();
|
||||
const token = formData.get('token') as string;
|
||||
const tokenTypeHint = formData.get('token_type_hint') as string;
|
||||
|
||||
if (!token) {
|
||||
return new Response(null, { status: 200 }); // Spec says always return 200
|
||||
}
|
||||
|
||||
const tokenHash = await plugins.smarthash.sha256FromString(token);
|
||||
|
||||
// Try to revoke as refresh token
|
||||
if (!tokenTypeHint || tokenTypeHint === 'refresh_token') {
|
||||
const refreshToken = this.refreshTokens.get(tokenHash);
|
||||
if (refreshToken) {
|
||||
refreshToken.revoked = true;
|
||||
return new Response(null, { status: 200 });
|
||||
}
|
||||
}
|
||||
|
||||
// Try to revoke as access token
|
||||
if (!tokenTypeHint || tokenTypeHint === 'access_token') {
|
||||
if (this.accessTokens.has(tokenHash)) {
|
||||
this.accessTokens.delete(tokenHash);
|
||||
return new Response(null, { status: 200 });
|
||||
}
|
||||
}
|
||||
|
||||
// Token not found - still return 200 per spec
|
||||
return new Response(null, { status: 200 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an app by its OAuth client_id
|
||||
*/
|
||||
private async findAppByClientId(clientId: string): Promise<App | null> {
|
||||
const apps = await this.receptionRef.appManager.CApp.getInstances({
|
||||
'data.oauthCredentials.clientId': clientId,
|
||||
});
|
||||
return apps[0] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate S256 PKCE challenge from verifier
|
||||
*/
|
||||
private generateS256Challenge(verifier: string): string {
|
||||
const hash = plugins.smarthash.sha256FromStringSync(verifier);
|
||||
return Buffer.from(hash, 'hex').toString('base64url');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error response for authorization endpoint
|
||||
*/
|
||||
private errorResponse(error: string, description: string): Response {
|
||||
return new Response(JSON.stringify({ error, error_description: description }), {
|
||||
status: 400,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error response for token endpoint
|
||||
*/
|
||||
private tokenErrorResponse(
|
||||
error: plugins.idpInterfaces.data.ITokenErrorResponse['error'],
|
||||
description: string
|
||||
): Response {
|
||||
const body: plugins.idpInterfaces.data.ITokenErrorResponse = {
|
||||
error,
|
||||
error_description: description,
|
||||
};
|
||||
return new Response(JSON.stringify(body), {
|
||||
status: 400,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Start cleanup task for expired tokens/codes
|
||||
*/
|
||||
private startCleanupTask(): void {
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
|
||||
// Clean up expired authorization codes
|
||||
for (const [code, data] of this.authorizationCodes) {
|
||||
if (data.expiresAt < now) {
|
||||
this.authorizationCodes.delete(code);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up expired access tokens
|
||||
for (const [hash, data] of this.accessTokens) {
|
||||
if (data.expiresAt < now) {
|
||||
this.accessTokens.delete(hash);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up expired refresh tokens
|
||||
for (const [hash, data] of this.refreshTokens) {
|
||||
if (data.expiresAt < now) {
|
||||
this.refreshTokens.delete(hash);
|
||||
}
|
||||
}
|
||||
}, 60 * 1000); // Run every minute
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import { AppManager } from './classes.appmanager.js';
|
||||
import { AppConnectionManager } from './classes.appconnectionmanager.js';
|
||||
import { ActivityLogManager } from './classes.activitylogmanager.js';
|
||||
import { UserInvitationManager } from './classes.userinvitationmanager.js';
|
||||
import { OidcManager } from './classes.oidcmanager.js';
|
||||
|
||||
export interface IReceptionOptions {
|
||||
/**
|
||||
@@ -49,6 +50,7 @@ export class Reception {
|
||||
public appConnectionManager = new AppConnectionManager(this);
|
||||
public activityLogManager = new ActivityLogManager(this);
|
||||
public userInvitationManager = new UserInvitationManager(this);
|
||||
public oidcManager = new OidcManager(this);
|
||||
housekeeping = new ReceptionHousekeeping(this);
|
||||
|
||||
constructor(public options: IReceptionOptions) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './loint-reception.activity.js';
|
||||
export * from './loint-reception.app.js';
|
||||
export * from './loint-reception.oidc.js';
|
||||
export * from './loint-reception.appconnection.js';
|
||||
export * from './loint-reception.billingplan.js';
|
||||
export * from './loint-reception.device.js';
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
* OIDC (OpenID Connect) data interfaces for third-party client support
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported OIDC scopes
|
||||
*/
|
||||
export type TOidcScope = 'openid' | 'profile' | 'email' | 'organizations' | 'roles';
|
||||
|
||||
/**
|
||||
* Authorization code for OAuth 2.0 authorization code flow
|
||||
*/
|
||||
export interface IAuthorizationCode {
|
||||
/** The authorization code string */
|
||||
code: string;
|
||||
/** OAuth client ID */
|
||||
clientId: string;
|
||||
/** User ID who authorized */
|
||||
userId: string;
|
||||
/** Scopes granted */
|
||||
scopes: TOidcScope[];
|
||||
/** Redirect URI used in authorization request */
|
||||
redirectUri: string;
|
||||
/** PKCE code challenge (S256 hashed) */
|
||||
codeChallenge?: string;
|
||||
/** PKCE code challenge method */
|
||||
codeChallengeMethod?: 'S256';
|
||||
/** Nonce from authorization request (for ID token) */
|
||||
nonce?: string;
|
||||
/** Expiration timestamp (10 minutes from creation) */
|
||||
expiresAt: number;
|
||||
/** Whether the code has been used (single-use) */
|
||||
used: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* OIDC Access Token (opaque or JWT)
|
||||
*/
|
||||
export interface IOidcAccessToken {
|
||||
/** Token identifier */
|
||||
id: string;
|
||||
/** The access token string (or hash for storage) */
|
||||
tokenHash: string;
|
||||
/** OAuth client ID */
|
||||
clientId: string;
|
||||
/** User ID */
|
||||
userId: string;
|
||||
/** Granted scopes */
|
||||
scopes: TOidcScope[];
|
||||
/** Expiration timestamp */
|
||||
expiresAt: number;
|
||||
/** Creation timestamp */
|
||||
issuedAt: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* OIDC Refresh Token
|
||||
*/
|
||||
export interface IOidcRefreshToken {
|
||||
/** Token identifier */
|
||||
id: string;
|
||||
/** The refresh token string (or hash for storage) */
|
||||
tokenHash: string;
|
||||
/** OAuth client ID */
|
||||
clientId: string;
|
||||
/** User ID */
|
||||
userId: string;
|
||||
/** Granted scopes */
|
||||
scopes: TOidcScope[];
|
||||
/** Expiration timestamp */
|
||||
expiresAt: number;
|
||||
/** Creation timestamp */
|
||||
issuedAt: number;
|
||||
/** Whether the token has been revoked */
|
||||
revoked: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* User consent record for an OAuth client
|
||||
*/
|
||||
export interface IUserConsent {
|
||||
/** Unique identifier */
|
||||
id: string;
|
||||
/** User who gave consent */
|
||||
userId: string;
|
||||
/** OAuth client ID */
|
||||
clientId: string;
|
||||
/** Scopes the user consented to */
|
||||
scopes: TOidcScope[];
|
||||
/** When consent was granted */
|
||||
grantedAt: number;
|
||||
/** When consent was last updated */
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* OIDC Discovery Document (OpenID Provider Configuration)
|
||||
*/
|
||||
export interface IOidcDiscoveryDocument {
|
||||
issuer: string;
|
||||
authorization_endpoint: string;
|
||||
token_endpoint: string;
|
||||
userinfo_endpoint: string;
|
||||
jwks_uri: string;
|
||||
revocation_endpoint: string;
|
||||
scopes_supported: TOidcScope[];
|
||||
response_types_supported: string[];
|
||||
grant_types_supported: string[];
|
||||
subject_types_supported: string[];
|
||||
id_token_signing_alg_values_supported: string[];
|
||||
token_endpoint_auth_methods_supported: string[];
|
||||
code_challenge_methods_supported: string[];
|
||||
claims_supported: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON Web Key Set (JWKS) response
|
||||
*/
|
||||
export interface IJwks {
|
||||
keys: IJwk[];
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON Web Key (RSA public key)
|
||||
*/
|
||||
export interface IJwk {
|
||||
kty: 'RSA';
|
||||
use: 'sig';
|
||||
alg: 'RS256';
|
||||
kid: string;
|
||||
n: string; // RSA modulus (base64url encoded)
|
||||
e: string; // RSA exponent (base64url encoded)
|
||||
}
|
||||
|
||||
/**
|
||||
* ID Token claims (JWT payload)
|
||||
*/
|
||||
export interface IIdTokenClaims {
|
||||
/** Issuer (idp.global URL) */
|
||||
iss: string;
|
||||
/** Subject (user ID) */
|
||||
sub: string;
|
||||
/** Audience (client ID) */
|
||||
aud: string;
|
||||
/** Expiration time (Unix timestamp) */
|
||||
exp: number;
|
||||
/** Issued at (Unix timestamp) */
|
||||
iat: number;
|
||||
/** Authentication time (Unix timestamp) */
|
||||
auth_time?: number;
|
||||
/** Nonce (if provided in authorization request) */
|
||||
nonce?: string;
|
||||
/** Access token hash (for hybrid flows) */
|
||||
at_hash?: string;
|
||||
|
||||
// Profile scope claims
|
||||
name?: string;
|
||||
preferred_username?: string;
|
||||
picture?: string;
|
||||
|
||||
// Email scope claims
|
||||
email?: string;
|
||||
email_verified?: boolean;
|
||||
|
||||
// Custom claims for organizations scope
|
||||
organizations?: IOrganizationClaim[];
|
||||
|
||||
// Custom claims for roles scope
|
||||
roles?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Organization claim in ID token / userinfo
|
||||
*/
|
||||
export interface IOrganizationClaim {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* UserInfo endpoint response
|
||||
*/
|
||||
export interface IUserInfoResponse {
|
||||
/** Subject (user ID) - always included */
|
||||
sub: string;
|
||||
|
||||
// Profile scope
|
||||
name?: string;
|
||||
preferred_username?: string;
|
||||
picture?: string;
|
||||
|
||||
// Email scope
|
||||
email?: string;
|
||||
email_verified?: boolean;
|
||||
|
||||
// Organizations scope (custom)
|
||||
organizations?: IOrganizationClaim[];
|
||||
|
||||
// Roles scope (custom)
|
||||
roles?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Token endpoint response
|
||||
*/
|
||||
export interface ITokenResponse {
|
||||
access_token: string;
|
||||
token_type: 'Bearer';
|
||||
expires_in: number;
|
||||
refresh_token?: string;
|
||||
id_token?: string;
|
||||
scope: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token endpoint error response
|
||||
*/
|
||||
export interface ITokenErrorResponse {
|
||||
error: 'invalid_request' | 'invalid_client' | 'invalid_grant' | 'unauthorized_client' | 'unsupported_grant_type' | 'invalid_scope';
|
||||
error_description?: string;
|
||||
error_uri?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorization request parameters
|
||||
*/
|
||||
export interface IAuthorizationRequest {
|
||||
client_id: string;
|
||||
redirect_uri: string;
|
||||
response_type: 'code';
|
||||
scope: string;
|
||||
state: string;
|
||||
code_challenge?: string;
|
||||
code_challenge_method?: 'S256';
|
||||
nonce?: string;
|
||||
prompt?: 'none' | 'login' | 'consent';
|
||||
}
|
||||
|
||||
/**
|
||||
* Token request for authorization_code grant
|
||||
*/
|
||||
export interface ITokenRequestAuthCode {
|
||||
grant_type: 'authorization_code';
|
||||
code: string;
|
||||
redirect_uri: string;
|
||||
client_id: string;
|
||||
client_secret?: string;
|
||||
code_verifier?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token request for refresh_token grant
|
||||
*/
|
||||
export interface ITokenRequestRefresh {
|
||||
grant_type: 'refresh_token';
|
||||
refresh_token: string;
|
||||
client_id: string;
|
||||
client_secret?: string;
|
||||
scope?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Union type for token requests
|
||||
*/
|
||||
export type ITokenRequest = ITokenRequestAuthCode | ITokenRequestRefresh;
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@idp.global/idp.global',
|
||||
version: '1.12.0',
|
||||
version: '1.13.0',
|
||||
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user