Skip to content

Composition: Handle 401 responses with loginUrl from Chromatic#33705

Merged
kasperpeulen merged 1 commit into
nextfrom
kasper/refs-401-loginurl
Jan 29, 2026
Merged

Composition: Handle 401 responses with loginUrl from Chromatic#33705
kasperpeulen merged 1 commit into
nextfrom
kasper/refs-401-loginurl

Conversation

@kasperpeulen
Copy link
Copy Markdown
Member

@kasperpeulen kasperpeulen commented Jan 29, 2026

Closes #

What I did

Chromatic is changing their endpoints to return HTTP 401 instead of 200 when authentication is required for private Storybooks. Previously, they returned 200 OK with { loginUrl: "..." } in the response body. After this change, they will return 401 Unauthorized with the same { loginUrl: "..." } body.

This PR updates the refs/composition feature to handle both scenarios:

  • Runtime (refs.ts): Extract loginUrl from 401 response bodies in handleRequest()
  • Build-time (get-storybook-refs.ts): Already returns false for 401 (no change needed), exported checkRef for testing
  • Tests: Added unit tests for both code paths

Note for Chromatic

Chromatic can only roll out this change (returning 401 instead of 200) after deprecating Storybook < 10.2. Until then, the following endpoints must continue returning 200 OK with { loginUrl: "..." } for backwards compatibility:

  • GET /index.json
  • GET /stories.json
  • GET /metadata.json

Note: /iframe.html does not need to be in this list - both 200 with loginUrl and 401 result in the same behavior: the build-time check marks the ref as type: 'unknown', which triggers the runtime fetch with credentials.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

Manual testing

Caution

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Manual testing was performed with the following steps:

  1. Added a private Chromatic ref to code/.storybook/main.ts:

    refs: {
      private: {
        title: 'Private (auth test)',
        url: 'https://62e7a15f87b0f4a7bed2cf04-ejukkgyspq.chromatic.com',
      },
    },
  2. Ran yarn nx run-many -t compile and yarn storybook:ui

  3. Created a Playwright test that intercepts requests and returns 401 with loginUrl:

    await page.route('**/62e7a15f87b0f4a7bed2cf04-ejukkgyspq.chromatic.com/**', (route) => {
      return route.fulfill({
        status: 401,
        contentType: 'application/json',
        body: JSON.stringify({ loginUrl: 'https://www.chromatic.com/start' }),
      });
    });
  4. Verified that clicking the "Private (auth test)" ref in the sidebar shows "Sign in to browse this Storybook" with a login button

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Chromatic is changing their endpoints to return 401 instead of 200 when
authentication is required. This change adds support for extracting
loginUrl from 401 response bodies in addition to the existing 200 handling.
@kasperpeulen kasperpeulen added maintenance User-facing maintenance tasks ci:normal labels Jan 29, 2026
@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Jan 29, 2026

View your CI Pipeline Execution ↗ for commit d29589d

Command Status Duration Result
nx run-many -t compile,check,knip,test,pretty-d... ✅ Succeeded 5m 47s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-29 13:48:43 UTC

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 29, 2026

📝 Walkthrough

Walkthrough

The PR adds authentication error handling for Storybook references. It exports the previously internal checkRef helper function, introduces a new unit test suite for it, implements 401 Unauthorized response detection in the manager API refs module to extract loginUrl from response bodies, and extends the test suite to verify the auth failure scenario with proper status code propagation.

Changes

Cohort / File(s) Summary
checkRef function export and testing
code/core/src/common/utils/get-storybook-refs.ts, code/core/src/common/utils/get-storybook-refs.test.ts
Export checkRef helper for external use; add comprehensive unit tests covering success (200 ok), failure (401), loginUrl detection, and network error scenarios using vitest with fetch mocks.
401 Authentication handling
code/core/src/manager-api/modules/refs.ts, code/core/src/manager-api/tests/refs.test.ts
Implement 401 Unauthorized response detection to extract and return loginUrl from JSON body in handleRequest; update test infrastructure with optional status property on ResponseResult interface; add test case for 401 auth failure flow.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

✨ Finishing touches
  • 📝 Generate docstrings

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

@kasperpeulen kasperpeulen added the patch:yes Bugfix & documentation PR that need to be picked to main branch label Jan 29, 2026
@kasperpeulen kasperpeulen merged commit afdf02a into next Jan 29, 2026
119 of 139 checks passed
@kasperpeulen kasperpeulen deleted the kasper/refs-401-loginurl branch January 29, 2026 10:01
@github-actions github-actions Bot mentioned this pull request Jan 30, 2026
10 tasks
valentinpalkovic pushed a commit that referenced this pull request Jan 30, 2026
Composition: Handle 401 responses with loginUrl from Chromatic
(cherry picked from commit afdf02a)
@github-actions github-actions Bot added the patch:done Patch/release PRs already cherry-picked to main/release branch label Jan 30, 2026
@github-actions github-actions Bot mentioned this pull request Jan 30, 2026
24 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:normal maintenance User-facing maintenance tasks patch:done Patch/release PRs already cherry-picked to main/release branch patch:yes Bugfix & documentation PR that need to be picked to main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants