Dev.to · 5 min read

Custom ID-JAG on PingFederate, Part 4: Testing Live Issuance Without Overclaiming

Custom ID-JAG on PingFederate, Part 4: Testing Live Issuance Without Overclaiming

A successful token response is useful evidence. It is not the whole test. For this custom PingFederate ID-JAG implementation, we wanted to know whether the server would reject the requests it should reject, whether the assertion could be verified independently, and whether Terraform still matched the running configuration afterward. The live runner passed 27 checks on a server reporting version 12.3.3.1. This final part explains what those checks mean and what they leave open. Code for this series: project repository. Four kinds of evidence, kept separate The project has four test layers: 26 Java offline checks, including signing and selected real PF parser, selector and serializer classes. 24 Node tests covering client protocol behavior and verification with local RSA fixtures. Four Terraform tests using mocked providers to check configuration restrictions. 27 live HTTP checks against the running PingFederate token and JWKS endpoints. The Java tests use the real 12.3.3 libraries but do not start an HTTP server. Some selected internal behavior is exercised reflectively in test code only. The deployed plugin does not use reflection. The Node client tests include mocked responses. The Terraform tests do not configure a real server. Only the live runner establishes that the installed plugin, configured policies, client authentication, request mappings and managed signing keys worked together on the running server. Reproduce the issuing-side lab The repository contains the complete implementation; the following commands assume you are running from its root. First, build with a local PF 12.3.3 installation: .\generator\build.ps1 -PfInstallDir C:\path\to\pingfederate\12.3.3 node --test The build script runs the standalone Java proof suite. Maven packaging is also supported, but Maven does not execute that standalone suite automatically. Deploy the resulting JAR to the test server's server/default/deploy directory and restart it. Wait for the Admin API to become ready and confirm that the custom generator descriptor appears. Next, create the local subject fixture: node scripts/create-local-fixture.mjs This creates a disposable subject-signing key and two independent client secrets under the ignored .local/ directory. Repeat runs preserve existing keys and secrets. The subject issuer is a reserved example-domain identifier. Its public JWKS is explicitly configured in the JWT processor. This is a controlled test fixture, not an identity provider completing a real login. Follow the Terraform guide to supply administrator credentials, initialize the providers, inspect a plan and apply it. Do not copy administrator passwords into source files or published commands. Then run: node scripts/live-local-proof.mjs The runner is deliberately restricted to the local runtime endpoint. It does not send fixture credentials to a downstream example domain. Verify the assertion, not just the HTTP status The positive exchange checks that the response uses the ID-JAG token-type URI and token_type equals N_A. The runner then fetches the configured PF JWKS and verifies the compact JWS signature. It checks the expected signing algorithm, JWT type, key identifier, issuer, audience, client, resource, scope and lifetime, along with subject and replay-identifier presence. An additional check confirms that the issued subject is the authorized fixture subject. The response expiry must be positive and no greater than 300 seconds. These checks distinguish a parseable token from an assertion whose signature and intended bindings have actually been verified. An example JWT is returned. Issued ID-JAG Header { "alg": "RS256", "typ": "oauth-id-jag+jwt", "kid": "IhqVmmqnFs0necq8KJgwg-W_8UY_RS256" } Body { "iss": "https://localhost:9031", "sub": "xaa-test-user", "aud": "https://target.example.test", "client_id": "target-client", "resource": "https://api.example.test/reports", "scope": "read:reports", "iat": 1788766854, "exp": 1788767154, "jti": "1847e9eb-b727-4372-aade-bd6b6bc10704" } Signature: present, not displayed Exercise the rejection paths The live suite sends subject tokens with the wrong issuer, wrong audience, wrong authorized party and unauthorized subject. It also tests an absent authorized party, expired tokens, missing expiry, multiple subject audiences and a modified signature. At the request layer, it tests missing and duplicate audience, resource and scope parameters, as well as unauthorized destinations, scopes and requested token types. At the client-authentication layer, it tests missing credentials, an incorrect secret and an authentication attempt using the disabled compatibility client. All of those cases were rejected. The runner requires an appropriate error status and OAuth error response without an issued access token; it does not claim that every rejection came from the custom generator. Several should fail earlier in PingFederate's pipeline. No subject token, issued assertion or client secret is printed by the runner. It reports check names and a summary. Keep server-side diagnostics protected too. Recheck the managed configuration After the live run, Terraform refreshed the eight managed resources and reported: No changes. Your infrastructure matches the configuration. The detailed exit code was zero. That establishes a clean post-apply plan for this configuration. It does not establish import behavior, every possible drift-recovery case, or a tested disaster-recovery process. Preserve the state and fixture inputs for the lab. Losing state and applying again to the same server is not a safe substitute for importing the existing resources. The work that remains This proof stops at issuing and independently verifying an ID-JAG. Real OIDC login must still be connected to the intended issuer. Subject resolution and authorization need production policy rather than one allowed fixture user. The downstream authorization server must be configured to trust the issuer and enforce the agreed assertion profile, authenticated client binding, resource and scope authorization, and replay handling. It must actually issue an access token before the full application-to-API path can be claimed as working. Multi-node deployment, key rotation behavior and broader profile conformance also need testing. The target URLs in this lab are examples, not deployed services. A useful result with a clear boundary The result is specific and reproducible: a custom generator on the tested PingFederate 12.3.3.1 server issued an ID-JAG using PF-managed keys, its signature verified against the live JWKS, 27 HTTP checks passed, and Terraform's post-apply plan was clean. That is enough to establish the issuing-side extension path as viable. It is not a reason to skip the remaining trust, authorization and receiving-side work.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Gadgets & Consumer Tech