Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
9e14a9e
feat(web-sdk): comprehensive DPoP nonce handling and verification (DS…
dmihalcik-virtru Jun 8, 2026
431d56b
docs: add DPoP CLI flags design spec (DSPX-3397)
dmihalcik-virtru Jun 9, 2026
544a897
docs: add DPoP CLI flags implementation plan (DSPX-3397)
dmihalcik-virtru Jun 9, 2026
ad55545
feat(cli): add DPoP key pair helpers (DSPX-3397)
dmihalcik-virtru Jun 9, 2026
b53131c
fix(cli): guard derToPem empty input, warn on RS384/RS512 downgrade
dmihalcik-virtru Jun 9, 2026
5b095e3
feat(cli): change --dpop to string type, add --dpop-key option (DSPX-…
dmihalcik-virtru Jun 9, 2026
3500a8c
feat(cli): wire --dpop and --dpop-key into encrypt/decrypt commands (…
dmihalcik-virtru Jun 9, 2026
4a22391
🤖 🎨 Autoformat
dmihalcik-virtru Jun 9, 2026
4e46c51
fix(dpop): address code review feedback on nonce retry logic and defe…
dmihalcik-virtru Jun 10, 2026
23b04f0
test(dpop): add DPoP nonce challenge to mock server and cover retry l…
dmihalcik-virtru Jun 10, 2026
4c53ece
🤖 🎨 Autoformat
dmihalcik-virtru Jun 10, 2026
c93f382
🤖 🎨 Autoformat
dmihalcik-virtru Jun 10, 2026
8e8997c
ci(dpop): upgrade Keycloak to 26.2 and enable DPoP nonce challenges i…
dmihalcik-virtru Jun 10, 2026
c3f1238
fix(dpop): add missing CORS headers to mock server for browser test c…
dmihalcik-virtru Jun 10, 2026
ff4136f
chore(scripts): add local dev helper scripts for DPoP demo
dmihalcik-virtru Jun 11, 2026
a06d389
chore(scripts): add config-demo.sh to provision KC and start dev server
dmihalcik-virtru Jun 11, 2026
65161fb
fix(scripts): create demo user1 in config-demo.sh
dmihalcik-virtru Jun 11, 2026
e13ffba
fix(scripts): route OIDC through Vite proxy to avoid CORS
dmihalcik-virtru Jun 11, 2026
9760be2
fix(scripts): route KAS through Vite proxy; drop PLATFORM_URL
dmihalcik-virtru Jun 11, 2026
556ec89
fix(sdk): use DPoP scheme when presenting DPoP-bound tokens
dmihalcik-virtru Jun 11, 2026
e9821f8
test(web-app): add Playwright test capturing DPoP-protected headers
dmihalcik-virtru Jun 11, 2026
4f5b4de
fix(dpop): make nonce challenge handling RFC 9449 compliant (DSPX-3397)
dmihalcik-virtru Jun 16, 2026
26d2202
fix(cli): harden DPoP key loading and helper utilities (DSPX-3397)
dmihalcik-virtru Jun 16, 2026
62ebd72
refactor(dpop): use ConnectError type and dedupe CLI argv handling (D…
dmihalcik-virtru Jun 16, 2026
05c7775
test(cli): cover PEM loading, key-path resolution, and CLI argv shape…
dmihalcik-virtru Jun 16, 2026
a2328d0
🤖 🎨 Autoformat
dmihalcik-virtru Jun 16, 2026
7c9ceef
fix(dpop): send DPoP proof on initial Keycloak token request (DSPX-3397)
dmihalcik-virtru Jun 17, 2026
d43c19c
🤖 🎨 Autoformat
dmihalcik-virtru Jun 17, 2026
5d8bf86
fix(dpop): scope DPoP enablement to providers configured with a key (…
dmihalcik-virtru Jun 17, 2026
bb48237
fix(dpop): emit raw IEEE P1363 ECDSA sigs in DPoP proofs; strict mock…
dmihalcik-virtru Jun 17, 2026
f4a076e
fix(dpop): pass full request URL to AuthProvider.withCreds (DSPX-3397)
dmihalcik-virtru Jun 24, 2026
7511de4
fix(dpop): nonce-challenge retry on legacy fetch path; strip query fr…
dmihalcik-virtru Jun 24, 2026
62edbc5
🤖 🎨 Autoformat
dmihalcik-virtru Jun 24, 2026
d928f73
test(dpop): enforce RFC 9449 on RPC endpoints + retry on AuthProvider…
dmihalcik-virtru Jun 24, 2026
e7d523c
fix(dpop): sign rewrap request token with the dpop key's algorithm (D…
dmihalcik-virtru Jun 25, 2026
baa3df2
fix(dpop): surface RPC rewrap error instead of legacy 404 mask (DSPX-…
dmihalcik-virtru Jun 25, 2026
b35108a
fix(dpop): capture DPoP-Nonce at the Connect transport for rewrap ret…
dmihalcik-virtru Jun 25, 2026
583a299
debug(dpop): temporary fetch-layer header dump for 401/400 (DSPX-3397)
dmihalcik-virtru Jun 25, 2026
243aba6
debug(dpop): dump rewrap proof claims + 401 body (DSPX-3397)
dmihalcik-virtru Jun 25, 2026
a978a6c
fix(dpop): emit raw IEEE P1363 ECDSA sigs in rewrap request token (DS…
dmihalcik-virtru Jun 25, 2026
b352e10
refactor(dpop): use type alias for DPoPJwtHeaderParameters
dmihalcik-virtru Jul 7, 2026
b6a05e6
refactor(dpop): extract shared nonce-challenge helpers
dmihalcik-virtru Jul 7, 2026
b8c0207
refactor(dpop): make DPoP nonce cache injectable per-client
dmihalcik-virtru Jul 7, 2026
68db023
fix(access): surface swallowed legacy rewrap fallback error
dmihalcik-virtru Jul 7, 2026
2aa3a74
fix(cli): forward per-client DPoP nonce cache through LoggedAuthProvider
dmihalcik-virtru Jul 8, 2026
084baf6
refactor(dpop): default nonce cache to shared defaultNonceCache
dmihalcik-virtru Jul 8, 2026
9cd2d48
refactor(dpop): review cleanups — consolidate nonce helpers, drop dep…
dmihalcik-virtru Jul 9, 2026
2c91284
fix(access,dpop): surface masked RPC errors + add nonce-retry diagnos…
dmihalcik-virtru Jul 9, 2026
4a6edce
fix(cli,access): error on unsupported DPoP alg; trim auth-path error …
dmihalcik-virtru Jul 9, 2026
20ad3f1
harden(crypto): validate DER structure in derToIeeeP1363 (DSPX-3397)
dmihalcik-virtru Jul 9, 2026
5ce2fcc
refactor(dpop): narrow JWS alg types, replace unchecked cast (DSPX-3397)
dmihalcik-virtru Jul 9, 2026
b370338
fix(oidc): consistently reject DPoP-enabled-without-signingKey (DSPX-…
dmihalcik-virtru Jul 9, 2026
09a1c67
fix(sdk): export DPoP nonce cache (DSPX-3397)
dmihalcik-virtru Jul 17, 2026
e90c01e
fix(web-app): retry DPoP nonce challenges (DSPX-3397)
dmihalcik-virtru Jul 17, 2026
51c7f90
fix(dpop): prefer rotated Connect nonce metadata (DSPX-3397)
dmihalcik-virtru Jul 17, 2026
9ff1ecf
fix(crypto): enforce ECDSA JWS signature lengths (DSPX-3397)
dmihalcik-virtru Jul 17, 2026
17f0cd9
chore: rm stray spec prompts
dmihalcik-virtru Jul 18, 2026
68f3621
fix(cli): treat --no-dpop as disabling DPoP (DSPX-3397)
dmihalcik-virtru Jul 27, 2026
13d01c3
fix(oidc): keep non-DPoP tokens cached across key rotation (DSPX-3397)
dmihalcik-virtru Jul 27, 2026
22e057e
test(dpop): add RS256 JWS conformance coverage (DSPX-3397)
dmihalcik-virtru Jul 27, 2026
ae97eda
fix(cli): chain key-import error cause in loadDPoPKeyPairFromPem (DSP…
dmihalcik-virtru Jul 27, 2026
67e3eaf
fix(cli): fail inspect when requested DPoP binding is absent (DSPX-3397)
dmihalcik-virtru Jul 27, 2026
eb49e38
fix(access): surface missing BaseKey as ConfigurationError (DSPX-3397)
dmihalcik-virtru Jul 27, 2026
d30cfea
fix(access): log base-key fallback with errBrief, not raw error (DSPX…
dmihalcik-virtru Jul 27, 2026
3b34f9a
refactor(crypto): share asymmetric-alg guard across JWT and DPoP sign…
dmihalcik-virtru Jul 27, 2026
2c91d78
docs(dpop,access): correct comment and docstring rot (DSPX-3397)
dmihalcik-virtru Jul 27, 2026
20aeab2
fix(ci): probe keycloak health on the management port (DSPX-3397)
dmihalcik-virtru Aug 4, 2026
9f45ab0
fix(ci): run kcadm inside the keycloak container (DSPX-3397)
dmihalcik-virtru Aug 4, 2026
0fc4c3f
test(ci): exercise the DPoP nonce challenge in the roundtrip (DSPX-3397)
dmihalcik-virtru Aug 5, 2026
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
40 changes: 16 additions & 24 deletions .github/workflows/roundtrip/config-demo-idp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,22 @@

set -x

: "${KC_VERSION:=24.0.3}"
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"

if ! which kcadm.sh; then
KCADM_URL=https://github.com/keycloak/keycloak/releases/download/${KC_VERSION}/keycloak-${KC_VERSION}.zip
echo "DOWNLOADING ${KCADM_URL}"
if ! curl --output kc.zip --fail --location "${KCADM_URL}"; then
echo "[ERROR] Failed to download ${KCADM_URL}"
exit 3
fi
ls -l
if ! unzip ./kc.zip; then
echo "[ERROR] Failed to unzip file from ${KCADM_URL}"
exit 3
fi
ls -l
ls -l "$(pwd)/keycloak-${KC_VERSION}/bin"
PATH=$PATH:"$(pwd)/keycloak-${KC_VERSION}/bin"
export PATH
if ! which kcadm.sh; then
echo "[ERROR] Failed to find kcadm.sh"
exit 3
fi
fi
# Run kcadm inside the keycloak container instead of downloading the release
# zip. The container ships a JRE matching its own Keycloak version; the host
# does not necessarily -- Keycloak 26's kcadm needs Java 17, while the
# ubuntu-22.04 runner defaults to Java 11 (UnsupportedClassVersionError).
# Using -f makes the compose project resolve from this script's directory, so
# the caller's working directory doesn't matter.
kcadm.sh() {
docker compose -f "${APP_DIR}/docker-compose.yaml" \
exec -T keycloak /opt/keycloak/bin/kcadm.sh "$@"
}

kcadm.sh config credentials --server http://localhost:65432/auth \
# Inside the container Keycloak is reached on its own KC_HTTP_PORT, not through
# the vite dev-server proxy on 65432 that host-side callers use.
kcadm.sh config credentials --server http://localhost:8888/auth \
--realm master --user admin --password changeme

kcadm.sh create clients -r opentdf \
Expand All @@ -48,7 +39,8 @@ kcadm.sh create clients -r opentdf \
-s enabled=true \
-s standardFlowEnabled=true \
-s serviceAccountsEnabled=true \
-s 'protocolMappers=[{"name":"aud","protocol":"openid-connect","protocolMapper":"oidc-audience-mapper","consentRequired":false,"config":{"access.token.claim":"true","included.custom.audience":"http://localhost:65432"}}]'
-s 'protocolMappers=[{"name":"aud","protocol":"openid-connect","protocolMapper":"oidc-audience-mapper","consentRequired":false,"config":{"access.token.claim":"true","included.custom.audience":"http://localhost:65432"}}]' \
-s 'attributes={"dpop.bound.access.tokens":"true"}'

kcadm.sh create users -r opentdf -s username=user1 -s enabled=true -s firstName=Alice -s lastName=User
kcadm.sh set-password -r opentdf --username user1 --new-password testuser123
25 changes: 3 additions & 22 deletions .github/workflows/roundtrip/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
services:
keycloak:
image: keycloak/keycloak:24.0.5
image: keycloak/keycloak:26.2
restart: always
command:
- "start-dev"
- "--verbose"
environment:
KC_DB_VENDOR: postgres
KC_DB_URL_HOST: keycloakdb
KC_DB_URL_PORT: 5432
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: changeme
KC_FEATURES: 'preview,token-exchange'
KC_FEATURES: "preview,token-exchange,admin-fine-grained-authz:v1"
KC_HEALTH_ENABLED: 'true'
KC_HOSTNAME_ADMIN_URL: 'http://localhost:65432/auth'
KC_HOSTNAME_PORT: '65432'
Expand All @@ -29,24 +23,11 @@ services:
ports:
- '8888:8888'
healthcheck:
test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:8888/auth/health/live']
test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:9000/auth/health/live']
interval: 5s
timeout: 10s
retries: 3
start_period: 2m
keycloakdb:
image: postgres:15-alpine
restart: always
user: postgres
environment:
POSTGRES_PASSWORD: changeme
POSTGRES_USER: postgres
POSTGRES_DB: keycloak
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 5s
timeout: 5s
retries: 10
opentdfdb:
image: postgres:15-alpine
restart: always
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/roundtrip/encrypt-decrypt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ _tdf3_test() {
--ignoreAllowList \
--oidcEndpoint http://localhost:65432/auth/realms/opentdf \
--auth testclient:secret \
--dpop \
--output sample.txt.tdf \
encrypt "${plain}" \
--containerType tdf3 \
Expand All @@ -28,6 +29,7 @@ _tdf3_test() {
--ignoreAllowList \
--oidcEndpoint http://localhost:65432/auth/realms/opentdf \
--auth testclient:secret \
--dpop \
--output sample_out.txt \
--containerType tdf3 \
decrypt sample.txt.tdf
Expand All @@ -50,6 +52,7 @@ _tdf3_inspect_test() {
--ignoreAllowList \
--oidcEndpoint http://localhost:65432/auth/realms/opentdf \
--auth testclient:secret \
--dpop \
--output sample-with-attrs.txt.tdf \
--attributes 'https://attr.io/attr/a/value/1,https://attr.io/attr/x/value/2' \
encrypt "${plain}" \
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/roundtrip/keycloak_data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ realms:
serviceAccountsEnabled: true
clientAuthenticatorType: client-secret
secret: secret
attributes:
dpop.bound.access.tokens: "true"
protocolMappers:
- *customAudMapper
sa_realm_roles:
sa_realm_roles:
- opentdf-standard
- client:
clientID: tdf-entity-resolution
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/roundtrip/opentdf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ server:
public_client_id: 'opentdf-public'
audience: 'http://localhost:65432'
issuer: http://localhost:65432/auth/realms/opentdf
dpop:
# Make KAS answer the first DPoP-proofed request with 401 + DPoP-Nonce so
# the roundtrip actually walks the server-issued nonce retry, not just
# plain proof-of-possession. xtest can't cover this: its nonce cases only
# run when the shared `dpop-challenge` input is on, which also swaps in a
# platform config other SDKs aren't ready for. Left off, this PR's headline
# feature would ship with no CI coverage at all.
# Only `enforce` would reject bearer tokens outright; that stays off, so
# the non-DPoP paths in this job are unaffected.
require_nonce: true
policy:
## Dot notation is used to access nested claims (i.e. realm_access.roles)
# Claim that represents the user (i.e. email)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/roundtrip/wait-and-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ _init_platform() {
return 1
fi
if ! ./config-demo-idp.sh; then
echo "[ERROR] unable to provision keycloak"
echo "[ERROR] unable to configure demo idp clients"
return 1
fi
if ! ./init-temp-keys.sh; then
Expand Down
82 changes: 64 additions & 18 deletions cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CLIError, Level, log } from './logger.js';
import * as assertions from '@opentdf/sdk/assertions';
import { base64 } from '@opentdf/sdk/encodings';
import { type KeyPair } from '@opentdf/sdk/singlecontainer';
import { resolveDPoPFromArgs } from './dpop-helpers.js';

type AuthToProcess = {
auth?: string;
Expand Down Expand Up @@ -53,14 +54,10 @@ const parseJwtComplete = (jwt: string) => {
return { header: parseJwt(jwt, 0), payload: parseJwt(jwt) };
};

async function processAuth({
auth,
clientId,
clientSecret,
concurrencyLimit,
oidcEndpoint,
userId,
}: AuthToProcess): Promise<LoggedAuthProvider> {
async function processAuth(
{ auth, clientId, clientSecret, concurrencyLimit, oidcEndpoint, userId }: AuthToProcess,
dpopKeyPair?: KeyPair
): Promise<LoggedAuthProvider> {
log('DEBUG', 'Processing auth params');
if (!oidcEndpoint) {
throw new CLIError('CRITICAL', 'oidcEndpoint must be specified');
Expand All @@ -79,18 +76,32 @@ async function processAuth({
'Auth expects clientId and clientSecret, or combined auth param'
);
}
// Pass DPoP key into the provider config so the AccessToken is born with
// DPoP enabled (config.dpopEnabled + signingKey). Without this, the very
// first POST /token would go out without a DPoP proof — Keycloak clients
// with dpop_bound_access_tokens=true reject that with 400 invalid_request.
// Without a key, DPoP stays off so non-DPoP clients still get plain Bearer
// tokens that the platform will accept.
const actual = await AuthProviders.clientSecretAuthProvider({
clientId,
oidcOrigin: oidcEndpoint,
exchange: 'client',
clientSecret,
dpopEnabled: !!dpopKeyPair,
signingKey: dpopKeyPair,
});
if (concurrencyLimit !== 1) {
await actual.oidcAuth.get();
}
const requestLog: AuthProviders.HttpRequest[] = [];
return {
requestLog,
// Forward the wrapped provider's per-client DPoP-Nonce cache. Without this,
// the auth interceptor/transport fall back to the shared default cache while
// `withCreds` (delegated below) mints proofs from the wrapped provider's own
// cache — the two diverge and the DPoP-Nonce challenge retry never carries
// the server nonce (RFC 9449 §9).
nonceCache: actual.nonceCache,
updateClientPublicKey: async (signingKey: KeyPair) => {
actual.updateClientPublicKey(signingKey);
log('DEBUG', `updateClientPublicKey: [${signingKey?.publicKey}]`);
Expand Down Expand Up @@ -394,8 +405,14 @@ export const handleArgs = (args: string[]) => {
})
.option('dpop', {
group: 'Security:',
desc: 'Use DPoP for token binding',
type: 'boolean',
desc: 'Enable DPoP token binding. Optional value selects algorithm: ES256 (default), ES384, ES512, RS256. Use --dpop=ES512 to specify.',
type: 'string',
})
.option('dpopKey', {
alias: 'dpop-key',
group: 'Security:',
desc: 'Path to PEM-encoded PKCS8 private key for DPoP signing. Enables DPoP alone if --dpop is omitted.',
type: 'string',
})
.implies('auth', '--no-clientId')
.implies('auth', '--no-clientSecret')
Expand Down Expand Up @@ -513,6 +530,21 @@ export const handleArgs = (args: string[]) => {
description: 'output file',
})

.command(
'supports <feature>',
'Check if a feature is supported',
(yargs) => {
yargs.strict().positional('feature', {
describe: 'feature name to check',
type: 'string',
choices: ['dpop'],
});
},
async () => {
// yargs choices validation ensures feature is supported; return naturally exits 0
}
)

.command(
'inspect [file]',
'Inspect TDF and extract header information, without decrypting',
Expand Down Expand Up @@ -561,9 +593,11 @@ export const handleArgs = (args: string[]) => {
if (!argv.oidcEndpoint) {
throw new CLIError('CRITICAL', 'oidcEndpoint must be specified');
}
const authProvider = await processAuth(argv);
const { dpopEnabled, dpopKeyPair } = await resolveDPoPFromArgs(argv);
const authProvider = await processAuth(argv, dpopKeyPair);
log('DEBUG', `Initialized auth provider ${JSON.stringify(authProvider)}`);
const guessedPolicyEndpoint = guessPolicyUrl(argv);

const client = new OpenTDF({
authProvider,
defaultCreateOptions: {
Expand All @@ -574,7 +608,8 @@ export const handleArgs = (args: string[]) => {
ignoreAllowlist: ignoreAllowList,
noVerify: !!argv.noVerifyAssertions,
},
disableDPoP: !argv.dpop,
disableDPoP: !dpopEnabled,
dpopKeys: dpopKeyPair ? Promise.resolve(dpopKeyPair) : undefined,
policyEndpoint: guessedPolicyEndpoint,
platformUrl: argv.platformUrl || guessedPolicyEndpoint,
});
Expand All @@ -600,14 +635,23 @@ export const handleArgs = (args: string[]) => {
console.assert(!accessToken, 'Multiple authorization headers found');
accessToken = parseJwt(lastRequest.headers[h].split(' ')[1]);
log('INFO', `Access Token: ${JSON.stringify(accessToken)}`);
if (argv.dpop) {
console.assert(accessToken.cnf?.jkt, 'Access token must have a cnf.jkt');
if (dpopEnabled && !accessToken.cnf?.jkt) {
// A missing cnf.jkt means token binding silently didn't take
// effect; fail loudly rather than exit 0 with only a warning.
throw new CLIError(
'CRITICAL',
'DPoP requested but the access token is not bound (missing cnf.jkt)'
);
}
break;
}
}
console.assert(accessToken, 'No access_token found');
console.assert(!argv.dpop || dpopToken, 'DPoP requested but absent');
if (!accessToken) {
throw new CLIError('CRITICAL', 'No access_token found');
}
if (dpopEnabled && !dpopToken) {
throw new CLIError('CRITICAL', 'DPoP requested but no DPoP proof was sent');
}
} finally {
client.close();
}
Expand All @@ -624,7 +668,8 @@ export const handleArgs = (args: string[]) => {
},
async (argv) => {
log('DEBUG', 'Running encrypt command');
const authProvider = await processAuth(argv);
const { dpopEnabled, dpopKeyPair } = await resolveDPoPFromArgs(argv);
const authProvider = await processAuth(argv, dpopKeyPair);
log('DEBUG', `Initialized auth provider ${JSON.stringify(authProvider)}`);
const guessedPolicyEndpoint = guessPolicyUrl(argv);

Expand All @@ -633,7 +678,8 @@ export const handleArgs = (args: string[]) => {
defaultCreateOptions: {
defaultKASEndpoint: argv.kasEndpoint,
},
disableDPoP: !argv.dpop,
disableDPoP: !dpopEnabled,
dpopKeys: dpopKeyPair ? Promise.resolve(dpopKeyPair) : undefined,
policyEndpoint: guessedPolicyEndpoint,
platformUrl: argv.platformUrl || guessedPolicyEndpoint,
});
Expand Down
Loading
Loading