Skip to content

Add Microsoft Entra ID (Azure AD) OIDC simulator#373

Open
taras wants to merge 3 commits into
mainfrom
entra-simulator
Open

Add Microsoft Entra ID (Azure AD) OIDC simulator#373
taras wants to merge 3 commits into
mainfrom
entra-simulator

Conversation

@taras

@taras taras commented Jul 8, 2026

Copy link
Copy Markdown
Member

Motivation

We want to run applications that authenticate against Microsoft Entra ID
(formerly Azure AD) locally — for development, previews, and integration tests —
without mock data and without changing the application's authentication source
code. Today we have the auth0 simulator but no Entra equivalent.

This adds @simulacrum/entra-simulator as a drop-in replacement for the core
Entra OIDC authentication user flows
. An application only needs to change
where its identity provider lives (the authority/issuer URL); every core
sign-in flow then behaves as it would against real Entra.

Approach

New package at packages/entra, modeled directly on packages/auth0 and built
on @simulacrum/foundation-simulator.

  • Tenant-scoped v2.0 endpoints mirroring real Entra: /:tenant/oauth2/v2.0/{authorize,token,logout},
    /:tenant/v2.0/.well-known/openid-configuration, /:tenant/discovery/v2.0/keys,
    /:tenant/discovery/instance (covers MSAL's /common/discovery/instance), and a
    Graph-style /oidc/userinfo. The :tenant path segment is authoritative — it
    becomes the tid claim and issuer tenant so discovery issuer and issued
    tokens stay internally consistent.
  • Flows: authorization-code + PKCE (S256/plain), refresh_token,
    client_credentials (app-only token with roles), and ROPC/password. Supports
    response_mode of query, fragment, form_post, and silent auth
    (prompt=none) via the session cookie.
  • Entra v2.0 token shapes: id/access tokens carry ver, iss, sub, aud,
    oid, tid, preferred_username, email, nonce, scp/roles, azp, and
    the id_token header sets kid matching the JWKS so real client libraries
    verify signatures. Reuses the same dev RSA key as the auth0 simulator.
  • Authorization codes and refresh tokens are encoded statelessly as base64url
    JSON (as auth0 does for refresh tokens), so the token endpoint needs no
    server-side session for the exchange. PKCE is verified per RFC 7636.
  • README documents drop-in config for MSAL, passport-azure-ad/NestJS, and
    next-auth.

Verification

  • 19 tests pass (vitest, matching the auth0 sibling), covering discovery/JWKS/
    instance discovery, the full auth-code + PKCE flow, all grant types, userinfo,
    logout, and silent auth.
  • Manually drove the built server end-to-end with curl as a real client would,
    including cryptographically verifying the issued id_token against the
    published JWKS
    with issuer + audience validation.
  • tsc, oxlint, oxfmt, and the tsdown build (attw + publint) are all clean.

A changeset is included (minor bump for the new package).

Summary by CodeRabbit

  • New Features

    • Added a local Microsoft Entra ID (OIDC) simulator package with OpenID discovery, JWKS, AAD instance discovery, authorization, token, userinfo, and logout endpoints.
    • Supports authorization-code + PKCE, refresh tokens, client credentials, and password (ROPC) sign-in flows.
    • Added a new start/boot entrypoint plus an example server for quick local testing.
  • Documentation

    • Added full package README and updated the main documentation to include the new simulator.
  • Tests

    • Added integration tests covering discovery metadata, sign-in redirects and response modes, token issuance, userinfo, silent auth, refresh/client-credentials/password grants, and logout.

A drop-in replacement for core Entra authentication user flows, built on
@simulacrum/foundation-simulator and modeled on the auth0 simulator.

Supports the OpenID discovery document, JWKS, AAD instance discovery, the
authorization-code + PKCE flow, refresh-token, client-credentials and ROPC
grants, userinfo and logout — all returning Entra v2.0 shaped tokens and
metadata, so applications point their authority at it with no source changes.
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new @simulacrum/entra-simulator package with Entra ID OIDC discovery, authorization, token, userinfo, and logout endpoints, plus supporting config, store, middleware, CLI/example entrypoints, tests, and documentation updates.

Changes

Entra Simulator Implementation

Layer / File(s) Summary
Configuration and type contracts
packages/entra/src/types.ts, packages/entra/src/config/get-config.ts, packages/entra/src/store/entities.ts, packages/entra/src/store/index.ts
Defines configuration, OAuth/OIDC token and query types, user/store schemas, default users, and store extension wiring.
Signing keys and token utilities
packages/entra/src/auth/constants.ts, packages/entra/src/auth/date.ts, packages/entra/src/handlers/utils.ts, packages/entra/src/handlers/url.ts
Adds embedded JWKS/signing key material, epoch helpers, code/token serialization, PKCE verification, scope checks, and URL trimming.
Express middleware
packages/entra/src/middleware/*
Adds CORS, session, no-cache, and error-handling middleware for the simulator app.
OpenID discovery endpoints
packages/entra/src/handlers/openid-handlers.ts
Serves OpenID configuration, JWKS, and instance discovery responses from request-derived tenant and base URL values.
Authorize, login, userinfo, and logout
packages/entra/src/handlers/entra-handlers.ts, packages/entra/src/views/login.ts
Implements the tenant-scoped login, authorization, userinfo, logout, and heartbeat flow with rendered HTML login UI.
Token grant handling
packages/entra/src/handlers/token.ts
Issues Entra-shaped access, ID, and refresh tokens for authorization-code, refresh-token, password, and client-credentials grants.
Router wiring and simulation entrypoint
packages/entra/src/handlers/index.ts, packages/entra/src/index.ts
Composes middleware and handlers into the router and exposes the public simulation factory.
CLI, example, and package build config
packages/entra/bin/start.mjs, packages/entra/example/index.mts, packages/entra/package.json, packages/entra/tsconfig.json, packages/entra/tsdown.config.ts
Adds package metadata, scripts, build configuration, and runnable CLI/example entrypoints.
Integration tests
packages/entra/test/*
Covers discovery, authorize/login, token grants, userinfo, logout, silent auth, PKCE, and redirect edge cases.
Documentation and changelog
packages/entra/README.md, README.md, .changes/*, .changes/config.json
Adds package docs, root simulator listing, changelog entry, and monorepo package registration.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding an Entra ID OIDC simulator.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch entra-simulator

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@frontsidejack

frontsidejack commented Jul 8, 2026

Copy link
Copy Markdown
Member

Package Changes Through 56105c8

There are 1 changes which include @simulacrum/entra-simulator with minor

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
@simulacrum/entra-simulator 0.1.0 0.2.0

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

@taras taras changed the base branch from v0 to main July 8, 2026 12:10
@pkg-pr-new

pkg-pr-new Bot commented Jul 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/thefrontside/simulacrum/@simulacrum/entra-simulator@373

commit: 56105c8

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (4)
packages/entra/example/index.mts (1)

3-7: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer const for non-reassigned variables.

config, port, authority, and app are never reassigned. Using const is idiomatic and prevents accidental reassignment.

♻️ Proposed fix
-let config = getConfig();
-let port = config.port ?? 4400;
-let authority = `https://localhost:${port}/${config.tenant}`;
-
-let app = simulation({
+const config = getConfig();
+const port = config.port ?? 4400;
+const authority = `https://localhost:${port}/${config.tenant}`;
+
+const app = simulation({
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/entra/example/index.mts` around lines 3 - 7, The example setup
currently uses mutable bindings for values that are never reassigned. Update the
variable declarations in the entrypoint around getConfig, the derived port and
authority values, and the simulation app creation to use const instead of let,
keeping the same initialization flow while making the intent explicit and
preventing accidental reassignment.
packages/entra/tsconfig.json (1)

7-7: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

include pattern doesn't cover .mts files.

The example file example/index.mts uses the .mts extension, but the include glob example/**/*.ts only matches .ts files. TypeScript treats .mts as a distinct extension, so example/index.mts is excluded from tsc --noEmit type checking.

♻️ Proposed fix
-  "include": ["src/**/*.ts", "test/**/*.ts", "example/**/*.ts"]
+  "include": ["src/**/*.ts", "test/**/*.ts", "example/**/*.mts"]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/entra/tsconfig.json` at line 7, The tsconfig include list in this
package misses .mts files, so example/index.mts is not type-checked by tsc
--noEmit. Update the include globs in the Entra tsconfig so the existing
src/test/example patterns also cover .mts alongside .ts, keeping the change
aligned with the current include configuration.
packages/entra/src/middleware/error-handling.ts (1)

28-34: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Consider gating stack trace exposure behind a debug flag.

Returning error.stack in the 500 response body is helpful for local debugging but could leak internal paths and structure if the simulator is exposed beyond localhost. Consider omitting the stack unless a debug/verbose mode is enabled.

♻️ Suggested refactor
   } else {
     console.error(error);
     res.status(500).json({
       error: {
         name: error.name,
         message: error.message,
-        stack: error.stack,
+        ...(process.env.NODE_ENV !== "production" && { stack: error.stack }),
       },
     });
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/entra/src/middleware/error-handling.ts` around lines 28 - 34, The
500 response in error-handling should not always expose the stack trace. Update
the middleware in error-handling to conditionally include error.stack only when
a debug/verbose flag is enabled, and otherwise return just the safe error
fields. Keep the change localized to the error response construction so the
existing error-handling flow remains intact.
packages/entra/test/entra.test.ts (1)

37-81: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test coverage for fragment and form_post response modes.

The PR claims support for query, fragment, and form_post response modes, but the suite only exercises query. Adding tests for fragment (code in URL fragment) and form_post (HTML auto-submit form) would increase confidence in these claimed features.

As per PR objectives, the simulator supports "query, fragment, and form_post response modes."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/entra/test/entra.test.ts` around lines 37 - 81, The /authorize test
suite only covers the query response mode, so add coverage in the existing
describe("/authorize") block for the fragment and form_post paths exercised by
the authorize flow. Use the same authorize request setup in entra.test.ts and
assert that fragment returns a redirect with the code in the URL fragment, while
form_post returns an HTML auto-submit form containing the expected authorization
fields. Reference the existing authorize handling and response mode assertions
so the new tests validate the simulator’s claimed support for query, fragment,
and form_post.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/entra/package.json`:
- Around line 36-57: The package metadata is pointing TypeScript at the CommonJS
declaration file instead of the ESM declaration file. Update the top-level types
entry in package.json to use the ESM declaration output for the package’s main
entry, and add a matching types condition under both exports["."] and
publishConfig.exports["."] so consumers resolve the correct declarations from
the same entrypoint.

In `@packages/entra/README.md`:
- Around line 78-86: Add language tags to the fenced examples in the README so
markdownlint MD040 passes; update the plain code blocks around the tenant URL
examples in the documentation to use a text fence, and apply the same fix to the
other matching fenced example block referenced by the review. Use the existing
README example sections as the targets for the change.
- Around line 185-195: Clarify the endpoint scope list by explicitly noting that
`/oidc/userinfo` is the exception and is mounted globally, not tenant-scoped.
Update the README endpoint section near the tenant-scoped routes to call out
this special case, referencing the `/oidc/userinfo` entry so readers don’t
assume it follows the same `:tenant` routing as the other endpoints.

In `@packages/entra/src/handlers/entra-handlers.ts`:
- Around line 90-101: The autoPostForm helper in entra-handlers.ts is
interpolating action and fields directly into HTML attributes, which allows
reflected HTML injection in form_post responses. Update autoPostForm to escape
the action (redirect_uri) and every field name/value before building the form
markup, using the same HTML-escaping approach already used in login.ts. Keep the
existing behavior of auto-submitting the form, but ensure all interpolated
strings in autoPostForm are safely encoded.
- Around line 73-74: The redirect URL construction in entra-handlers.ts assumes
redirect_uri has no existing query string, so update the redirect logic in both
redirectWithCode and redirectWithError to choose the separator based on whether
query.redirect_uri already contains a query. Keep using "#" for fragment mode,
but for query mode use "&" when redirect_uri already has "?" and "?" otherwise,
so the res.redirect calls build valid URLs in all cases.

In `@packages/entra/src/handlers/openid-handlers.ts`:
- Around line 7-8: baseUrl currently builds URLs directly from req.get("Host"),
which can be undefined and produce invalid discovery URLs. Update baseUrl in
openid-handlers.ts to guard against a missing Host header by either falling back
to a configured/default host or rejecting the request with a 400 before
generating URLs, and make sure the callers that rely on baseUrl handle the
missing-header path cleanly.
- Around line 74-81: The discovery document in openid-handlers is advertising
grant types that the token endpoint does not actually support. Update the
`grant_types_supported` list in the OpenID discovery response to match the
grants handled by `token.ts` and `handleTokenRequest`/the token handler,
removing unsupported entries like `urn:ietf:params:oauth:grant-type:jwt-bearer`
and `implicit` unless corresponding token support is added. Keep the advertised
grants aligned with the token endpoint’s accepted flows (`authorization_code`,
`refresh_token`, `password`, `client_credentials`) so clients don’t discover
unusable options.

In `@packages/entra/src/handlers/token.ts`:
- Around line 204-221: `refreshTokenTokens` is overwriting the original
authentication time by calling `epochTime()` when issuing refreshed ID tokens.
Preserve the original `auth_time` by carrying it through the refresh flow: add
`auth_time` to `RefreshTokenPayload`, ensure it is set when the refresh token is
created, and then pass `decoded.auth_time` into `finishUserTokens` from
`refreshTokenTokens` instead of the current time so refreshed tokens keep the
original authentication timestamp.

In `@packages/entra/src/handlers/utils.ts`:
- Around line 21-22: `decodeAuthorizationCode` and `decodeRefreshToken`
currently let malformed base64url/JSON input surface as raw SyntaxError
exceptions, so update these helpers in utils.ts to catch parse/decode failures
and rethrow a typed OAuth-style error instead. Use the existing decoder
functions (`decodeAuthorizationCode`, `decodeRefreshToken`) as the entry points,
and convert invalid input into the same error shape/status your middleware
expects for `invalid_grant` (or equivalent) so the simulator returns a proper
400 response. Keep the logic localized to these helpers so callers don’t need to
change.

In `@packages/entra/src/middleware/session.ts`:
- Around line 5-13: Update createSession in session.ts to set the cookieSession
option httpOnly to true so the session cookie cannot be read by JavaScript;
silent iframe auth will still work because the browser sends the cookie
automatically. Also remove the weak default secret in createSession by requiring
an explicit secret parameter or otherwise warning loudly when the default is
used, so consumers do not accidentally ship with the fallback "shhh" value.

In `@packages/entra/src/store/index.ts`:
- Around line 88-100: The extendStore helper is dropping the logs setting from
ExtendStoreConfig, so createSimulationStore never receives it and action logging
stays off; update extendStore to forward extended?.logs alongside actions,
selectors, and schema, keeping the returned object shape aligned with the
existing extendActions, extendSelectors, and inputSchema wiring.

---

Nitpick comments:
In `@packages/entra/example/index.mts`:
- Around line 3-7: The example setup currently uses mutable bindings for values
that are never reassigned. Update the variable declarations in the entrypoint
around getConfig, the derived port and authority values, and the simulation app
creation to use const instead of let, keeping the same initialization flow while
making the intent explicit and preventing accidental reassignment.

In `@packages/entra/src/middleware/error-handling.ts`:
- Around line 28-34: The 500 response in error-handling should not always expose
the stack trace. Update the middleware in error-handling to conditionally
include error.stack only when a debug/verbose flag is enabled, and otherwise
return just the safe error fields. Keep the change localized to the error
response construction so the existing error-handling flow remains intact.

In `@packages/entra/test/entra.test.ts`:
- Around line 37-81: The /authorize test suite only covers the query response
mode, so add coverage in the existing describe("/authorize") block for the
fragment and form_post paths exercised by the authorize flow. Use the same
authorize request setup in entra.test.ts and assert that fragment returns a
redirect with the code in the URL fragment, while form_post returns an HTML
auto-submit form containing the expected authorization fields. Reference the
existing authorize handling and response mode assertions so the new tests
validate the simulator’s claimed support for query, fragment, and form_post.

In `@packages/entra/tsconfig.json`:
- Line 7: The tsconfig include list in this package misses .mts files, so
example/index.mts is not type-checked by tsc --noEmit. Update the include globs
in the Entra tsconfig so the existing src/test/example patterns also cover .mts
alongside .ts, keeping the change aligned with the current include
configuration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 00a5add8-b06a-49c2-8972-7ec90bd3c5a1

📥 Commits

Reviewing files that changed from the base of the PR and between 1d85e34 and e86d78e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • .changes/config.json
  • .changes/entra-simulator.md
  • README.md
  • packages/entra/README.md
  • packages/entra/bin/start.mjs
  • packages/entra/example/index.mts
  • packages/entra/package.json
  • packages/entra/src/auth/constants.ts
  • packages/entra/src/auth/date.ts
  • packages/entra/src/config/get-config.ts
  • packages/entra/src/handlers/entra-handlers.ts
  • packages/entra/src/handlers/index.ts
  • packages/entra/src/handlers/openid-handlers.ts
  • packages/entra/src/handlers/token.ts
  • packages/entra/src/handlers/url.ts
  • packages/entra/src/handlers/utils.ts
  • packages/entra/src/index.ts
  • packages/entra/src/middleware/create-cors.ts
  • packages/entra/src/middleware/error-handling.ts
  • packages/entra/src/middleware/no-cache.ts
  • packages/entra/src/middleware/session.ts
  • packages/entra/src/store/entities.ts
  • packages/entra/src/store/index.ts
  • packages/entra/src/types.ts
  • packages/entra/src/views/login.ts
  • packages/entra/test/entra.test.ts
  • packages/entra/test/helpers.ts
  • packages/entra/test/openid-handlers.test.ts
  • packages/entra/tsconfig.json
  • packages/entra/tsdown.config.ts

Comment thread packages/entra/package.json Outdated
Comment thread packages/entra/README.md
Comment thread packages/entra/README.md
Comment thread packages/entra/src/handlers/entra-handlers.ts Outdated
Comment thread packages/entra/src/handlers/entra-handlers.ts
Comment thread packages/entra/src/handlers/openid-handlers.ts
Comment thread packages/entra/src/handlers/token.ts
Comment thread packages/entra/src/handlers/utils.ts Outdated
Comment thread packages/entra/src/middleware/session.ts
Comment thread packages/entra/src/store/index.ts
This is a local dev tool, so security-only findings are ignored; the focus is
developer experience — avoiding opaque failures and confusing behavior.

- Return 400 invalid_grant (not an opaque 500 + stack) for malformed
  authorization codes and refresh tokens, matching real Entra
- Escape reflected values in the form_post auto-submit page so a legitimate
  state/redirect_uri containing " & < survives intact instead of corrupting the
  posted state (which would make the app reject the callback)
- Use & instead of ? when the redirect_uri already carries a query string
- Forward extendStore `logs` so `logs: true` actually enables action logging
- Point package "types" at the emitted ./dist/index.d.mts (the .d.cts path did
  not exist, breaking types for classic-resolution consumers)
- Drop grant types the token endpoint does not implement (jwt-bearer, implicit)
  from the discovery document
- Preserve auth_time across refresh so refreshed id tokens report the original
  sign-in time
- Clarify in the README that /oidc/userinfo is mounted globally, not tenant-scoped
- Add tests for fragment and form_post response modes, HTML escaping, the
  redirect-separator fix, and malformed-grant 400s

Deliberately not changed: session httpOnly and error stack-trace exposure are
security-only concerns that do not apply to a localhost dev tool (and the stack
trace aids debugging).
@taras

taras commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

Thanks @coderabbitai — triaged all 15 findings through a developer-experience lens, since this is a local dev tool that never runs in production (so security-only hardening is out of scope here).

Addressed (commit 56105c8):

  • utils.ts — malformed authorization codes / refresh tokens now return 400 invalid_grant instead of an opaque 500 + stack trace
  • entra-handlers.tsautoPostForm now HTML-escapes reflected values (framed as correctness: a legit state/redirect_uri with "/&/< was corrupting the posted state), and the redirect uses & when redirect_uri already has a query string
  • store/index.tsextendStore now forwards logs
  • package.jsontypes points at the emitted ./dist/index.d.mts
  • openid-handlers.ts — dropped jwt-bearer/implicit from grant_types_supported
  • token.tsauth_time is preserved across refresh
  • README — clarified /oidc/userinfo is mounted globally, not tenant-scoped
  • Added tests for fragment/form_post modes, escaping, the separator fix, and malformed-grant 400s

Intentionally not changed:

  • Session httpOnly and gating the error stack trace behind a debug flag — security-only concerns that don't apply to a localhost dev tool (the stack trace actively helps developers debug)
  • README MD040 tags, tsconfig .mts include, baseUrl Host guard, and const-vs-let in the example (the repo's house style uses let) — low/no DX value

Note: the logs-forwarding and types-field issues also exist in the auth0 sibling; left as an optional follow-up to keep this PR scoped.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/entra/test/entra.test.ts`:
- Around line 262-272: Strengthen the form_post escaping test in the entra test
suite by also asserting that the reflected state value escapes double quotes,
not just angle brackets. Update the html-escapes reflected values in the
form_post body case to verify the response body contains the escaped quote
entity (for the injected a"><script>... payload) alongside the existing
raw-script and &lt;script&gt; checks, using loginWith and the response body
assertions to locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b406e853-ec15-4af2-aa08-29c3134afcfe

📥 Commits

Reviewing files that changed from the base of the PR and between e86d78e and 56105c8.

📒 Files selected for processing (9)
  • packages/entra/README.md
  • packages/entra/package.json
  • packages/entra/src/handlers/entra-handlers.ts
  • packages/entra/src/handlers/openid-handlers.ts
  • packages/entra/src/handlers/token.ts
  • packages/entra/src/handlers/utils.ts
  • packages/entra/src/store/index.ts
  • packages/entra/src/types.ts
  • packages/entra/test/entra.test.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/entra/README.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/entra/src/store/index.ts
  • packages/entra/src/types.ts
  • packages/entra/src/handlers/utils.ts
  • packages/entra/src/handlers/openid-handlers.ts
  • packages/entra/package.json
  • packages/entra/src/handlers/token.ts
  • packages/entra/src/handlers/entra-handlers.ts

Comment thread packages/entra/test/entra.test.ts
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

@taras Thanks for the detailed breakdown and for working through all 15 findings so thoroughly.

The fixes in 56105c8 look good — the invalid_grant handling, HTML-escaping in autoPostForm, logs forwarding, types path fix, auth_time preservation across refresh, and the dropped grant_types_supported entries all address real correctness/DX gaps. Nice touch also adding targeted tests for the escaping and separator fixes.

On the intentionally-skipped items, that's a fair call — the DX-first framing makes sense for a simulator that's explicitly scoped to local development and never touches production traffic. I won't push further on httpOnly/stack-trace gating or the style nits (README lint tags, tsconfig include, const/let).

For the logs-forwarding and types-field parity gaps in the auth0 sibling package — happy to open a follow-up issue to track that if you'd like, just let me know.


✏️ Learnings added
Learnt from: taras
URL: https://github.com/thefrontside/simulacrum/pull/373

Timestamp: 2026-07-08T13:15:44.556Z
Learning: In the thefrontside/simulacrum repository, packages like simulacrum/auth0-simulator and simulacrum/entra-simulator are local-development-only OIDC/OAuth simulators that never run in production. Per maintainer taras, security-only hardening suggestions (e.g., session cookie httpOnly, gating error stack traces behind a debug flag) are intentionally out of scope for these packages since they don't apply to a localhost dev tool; reviews should be triaged through a developer-experience lens instead, prioritizing correctness and DX over security hardening for these simulator packages.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants