Skip to content

fix: Allow guest and anonymous users without auth options#2140

Merged
oliverlaz merged 3 commits intomainfrom
oliver/allow-guest-anon-without-auth
Feb 26, 2026
Merged

fix: Allow guest and anonymous users without auth options#2140
oliverlaz merged 3 commits intomainfrom
oliver/allow-guest-anon-without-auth

Conversation

@oliverlaz
Copy link
Member

@oliverlaz oliverlaz commented Feb 26, 2026

💡 Overview

Update StreamVideoClientOptions typing so guest and anonymous users must not provide token or tokenProvider, while authenticated users must provide at least one of them.

Continuation of: #2138

📝 Implementation notes

  • disallow token/tokenProvider for guest and anonymous user options
  • keep authenticated users requiring token or tokenProvider
  • keep token/tokenProvider disallowed when user is omitted
  • verified with package and sample app TypeScript checks

🎫 Ticket: https://linear.app/stream/issue/RN-352/error-in-streamvideoclientgetorcreateinstance-method-and-user
📑 Docs: https://github.com/GetStream/docs-content/pull/1042

Summary by CodeRabbit

  • New Features

    • Enhanced type safety with distinct configuration options for guest, anonymous, and authenticated users.
  • Bug Fixes

    • Simplified authentication flow for guest and anonymous users, reducing unnecessary token/provider configurations.

@oliverlaz oliverlaz changed the title Allow guest and anonymous users without auth options fix: Allow guest and anonymous users without auth options Feb 26, 2026
@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

⚠️ No Changeset found

Latest commit: 33566c2

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

Split user shapes and client option variants: added GuestOrAnonymousUser and AuthenticatedUser, introduced option types for guest/anonymous vs authenticated clients (guest/anonymous disallow token/tokenProvider), removed StreamVideoClientOptionsWithUser, and updated StreamVideoClientOptions union. Also updated multiple sample apps to branch client creation by user.type, removing tokenProvider for guest/anonymous flows.

Changes

Cohort / File(s) Summary
Client types
packages/client/src/types.ts
Introduced GuestOrAnonymousUser and AuthenticatedUser. Added StreamVideoClientOptionsWithGuestOrAnonymousUser (disallows token/tokenProvider) and StreamVideoClientOptionsWithAuthenticatedUser (requires token or tokenProvider). Removed StreamVideoClientOptionsWithUser and updated StreamVideoClientOptions union.
React Native — guest flow simplification
sample-apps/react-native/dogfood/src/screens/Meeting/GuestMeetingScreen.tsx
Replaced tokenProvider wrapper with direct createToken call to obtain apiKey; removed tokenProvider from client creation in guest path.
Expo sample — Video client branching
sample-apps/react-native/expo-video-sample/components/VideoWrapper.tsx
Added guard for missing user and computed user_id for anonymous. Split client creation: guest/anonymous path creates client without token/tokenProvider; other users retain token + tokenProvider lazy fetch.
React livestream hook — user/type handling
sample-apps/react/livestream-app/src/hooks/useInitVideoClient.ts
Changed anon representation to { type: 'anonymous' }, derive user_id from type or id, and branch client construction by user.type: guest/anonymous no token/tokenProvider; authenticated users use token or tokenProvider. Removed isAnon from dependencies.
React dogfood — client init refactor
sample-apps/react/react-dogfood/helpers/client.ts
Refactored getClient to explicitly branch: create client without token/tokenProvider for guest/anonymous; for authenticated users build tokenProvider or use provided token (or throw if missing). Removed prior combined authOptions approach.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through types and took a bite,
Guests split from Auth in the soft moonlight,
Tokens stay hidden where they should be,
Clients now branch — hop, sip my tea! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: allowing guest and anonymous users to initialize the client without authentication options, which is the primary objective of this PR.
Description check ✅ Passed The description includes the required template sections (Overview, Implementation notes, Ticket, and Docs link) and provides clear details about the typing changes and verification steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch oliver/allow-guest-anon-without-auth

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
sample-apps/react/livestream-app/src/hooks/useInitVideoClient.ts (1)

31-55: TokenProvider is created but unused for anonymous/guest users.

The tokenProvider function (lines 31-47) is created unconditionally, but for anonymous/guest users (lines 48-50), it's never used. While this doesn't cause functional issues, it's slightly wasteful to define the function.

Consider moving the tokenProvider definition inside the else branch:

♻️ Optional: move tokenProvider inside else branch
-    const tokenProvider = async () => {
-      const endpoint = new URL(tokenProviderUrl);
-      endpoint.searchParams.set('api_key', apiKey);
-      endpoint.searchParams.set(
-        'user_id',
-        user.type === 'anonymous' ? '!anon' : user.id!,
-      );
-
-      if (user.type === 'anonymous') {
-        endpoint.searchParams.set(
-          'call_cids',
-          `${type ?? DEFAULT_CALL_TYPE}:${callId}`,
-        );
-      }
-      const response = await fetch(endpoint).then((res) => res.json());
-      return response.token as string;
-    };
     const _client =
       user.type === 'anonymous' || user.type === 'guest'
         ? new StreamVideoClient({ apiKey, user })
-        : new StreamVideoClient({
+        : (() => {
+            const tokenProvider = async () => {
+              const endpoint = new URL(tokenProviderUrl);
+              endpoint.searchParams.set('api_key', apiKey);
+              endpoint.searchParams.set('user_id', user.id!);
+              const response = await fetch(endpoint).then((res) => res.json());
+              return response.token as string;
+            };
+            return new StreamVideoClient({
             apiKey,
             user,
             ...(token ? { token, tokenProvider } : { tokenProvider }),
-          });
+            });
+          })();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sample-apps/react/livestream-app/src/hooks/useInitVideoClient.ts` around
lines 31 - 55, The tokenProvider function is created unconditionally but only
used when user.type is neither 'anonymous' nor 'guest'; move the tokenProvider
definition inside the else branch that constructs the StreamVideoClient for
authenticated users so it’s only created when needed, and ensure the
StreamVideoClient construction still passes either { token, tokenProvider } when
token is present or { tokenProvider } otherwise; update references to
tokenProvider and StreamVideoClient in that block and remove the now-unused
top-level tokenProvider.
sample-apps/react-native/expo-video-sample/components/VideoWrapper.tsx (1)

21-31: Unnecessary token fetch for guest/anonymous users.

The fetchAuthDetails() call on line 24 is executed unconditionally, but for guest/anonymous users (lines 26-31), the fetched token is never used. This results in a wasted network request.

Consider moving the fetch inside the else branch or conditionally fetching only for authenticated users:

♻️ Proposed refactor to avoid unnecessary fetch
      if (!user) return;
      const user_id = user.type === 'anonymous' ? '!anon' : user.id;
      if (!user_id) return;
-     const fetchAuthDetails = async () => {
-       return await createToken({ user_id });
-     };
-     const { apiKey, token } = await fetchAuthDetails();

      if (user.type === 'guest' || user.type === 'anonymous') {
+       const { apiKey } = await createToken({ user_id });
        _videoClient = StreamVideoClient.getOrCreateInstance({
          apiKey,
          user,
          options: { logLevel: 'warn' },
        });
      } else {
+       const fetchAuthDetails = async () => {
+         return await createToken({ user_id });
+       };
+       const { apiKey, token } = await fetchAuthDetails();
        const tokenProvider = () =>
          fetchAuthDetails().then((auth) => auth.token);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sample-apps/react-native/expo-video-sample/components/VideoWrapper.tsx`
around lines 21 - 31, The code currently calls fetchAuthDetails()/createToken
unconditionally but never uses the returned token for guest/anonymous users;
update the logic so you only call fetchAuthDetails() when user.type is not
'guest' or 'anonymous' (i.e., move the await createToken({ user_id }) / const {
apiKey, token } into the else branch), or alternatively fetch only the apiKey
for guests if needed; adjust usage around apiKey/token and
StreamVideoClient.getOrCreateInstance so no network call is made for
guest/anonymous users.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sample-apps/react/livestream-app/src/hooks/useInitVideoClient.ts`:
- Around line 34-37: In useInitVideoClient.ts update the
endpoint.searchParams.set call to avoid the non-null assertion on user.id by
adding a runtime guard: when setting 'user_id' use user.type === 'anonymous' ?
'!anon' : (user.id ?? '<fallback>') (or choose a sensible fallback like
'!unknown' and/or log an error via the same logger used elsewhere) rather than
user.id!; ensure you reference getUser()’s returned object and handle both
missing id and guest/anonymous types so no non-null assertion is used.

---

Nitpick comments:
In `@sample-apps/react-native/expo-video-sample/components/VideoWrapper.tsx`:
- Around line 21-31: The code currently calls fetchAuthDetails()/createToken
unconditionally but never uses the returned token for guest/anonymous users;
update the logic so you only call fetchAuthDetails() when user.type is not
'guest' or 'anonymous' (i.e., move the await createToken({ user_id }) / const {
apiKey, token } into the else branch), or alternatively fetch only the apiKey
for guests if needed; adjust usage around apiKey/token and
StreamVideoClient.getOrCreateInstance so no network call is made for
guest/anonymous users.

In `@sample-apps/react/livestream-app/src/hooks/useInitVideoClient.ts`:
- Around line 31-55: The tokenProvider function is created unconditionally but
only used when user.type is neither 'anonymous' nor 'guest'; move the
tokenProvider definition inside the else branch that constructs the
StreamVideoClient for authenticated users so it’s only created when needed, and
ensure the StreamVideoClient construction still passes either { token,
tokenProvider } when token is present or { tokenProvider } otherwise; update
references to tokenProvider and StreamVideoClient in that block and remove the
now-unused top-level tokenProvider.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bb8f05b and 33566c2.

📒 Files selected for processing (4)
  • sample-apps/react-native/dogfood/src/screens/Meeting/GuestMeetingScreen.tsx
  • sample-apps/react-native/expo-video-sample/components/VideoWrapper.tsx
  • sample-apps/react/livestream-app/src/hooks/useInitVideoClient.ts
  • sample-apps/react/react-dogfood/helpers/client.ts

@oliverlaz oliverlaz merged commit 12749ae into main Feb 26, 2026
18 checks passed
@oliverlaz oliverlaz deleted the oliver/allow-guest-anon-without-auth branch February 26, 2026 15:41
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