Skip to content

feat(auth): partner region login (Jio, bro.game, etc.)#64

Draft
owenselles wants to merge 3 commits into
mainfrom
feat/partner-region-login
Draft

feat(auth): partner region login (Jio, bro.game, etc.)#64
owenselles wants to merge 3 commits into
mainfrom
feat/partner-region-login

Conversation

@owenselles

Copy link
Copy Markdown
Owner

Summary

GeForce NOW is available via third-party partners in some regions — Jio in India, bro.game in Brazil, and potentially others. NVIDIA already exposes these via https://pcs.geforcenow.com/v1/serviceUrls, the same endpoint we already call in NVIDIAAuthAPI.fetchProviders(). The auth plumbing (idpId, streamingServiceUrl, AuthSession.provider) was already wired end-to-end — the only missing piece was surfacing provider choice in the UI.

  • LoginView: fetches providers on appear; shows one button per provider when multiple are returned (e.g. "NVIDIA", "Jio", "bro.game"), falling back to the existing single NVIDIA button if the fetch fails or only one provider is available
  • GamesViewModel: guards measureTopZones() to skip PrintedWaste zone discovery for non-nvidiagrid.net providers — prevents NVIDIA zone URLs from being passed to a partner session API; partner sessions use a nil zone hint and let the provider's own CloudMatch route the connection

No changes to auth endpoints, CloudMatchClient, GamesClient, or any streaming code — partner idpId federation happens server-side on login.nvidia.com.

Test plan

  • NVIDIA login: single button still appears, zone auto-selection still runs — no regression
  • In a partner region (or by temporarily hardcoding a partner provider): multiple buttons appear on login screen
  • Selecting a partner provider completes the QR/device flow and loads the games library
  • Launching a game creates the session against the partner's streamingServiceUrl with no zone hint

…ro.game)

NVIDIA's serviceUrls endpoint already returns partner providers (Jio in India,
bro.game in Brazil, etc.) with their own idpId and streamingServiceUrl. This
surfaces them in the login UI so users in partner regions can authenticate and
stream via the correct infrastructure.

- LoginView: fetch providers on appear; show one button per provider when
  multiple are returned, falling back to the single NVIDIA button otherwise
- GamesViewModel: skip PrintedWaste zone discovery for non-nvidiagrid.net
  providers so NVIDIA zone URLs are never passed to a partner session API;
  partner sessions fall back to nil zone and let the provider's CloudMatch route
@aarikmudgal aarikmudgal added the enhancement New feature or request label Jul 10, 2026
@aarikmudgal

Copy link
Copy Markdown
Collaborator

@owenselles Thinking out loud, maybe we can check if this PR have some overlap with #67 . Maybe we should unify and combine the server/location feature.

@owenselles

Copy link
Copy Markdown
Owner Author

Agree also for testing this we need someone with a partner account

@RichiX9711

Copy link
Copy Markdown

Hi! I have an active GeForce NOW account through Digevo and I can help test the partner-provider implementation in PR #64.

I also have an Apple TV 4K 3rd generation, so I can test the complete flow on real hardware: provider detection, authentication, library loading, game launch, server routing, and streaming.

If needed, I can build and test the PR branch myself and provide logs or other diagnostic information.

@owenselles

Copy link
Copy Markdown
Owner Author

Yea @RichiX9711 if you can that would be of great help as no one else I know has a partner account

@owenselles

Copy link
Copy Markdown
Owner Author

So I have no real way to test and implement this. Current implementation is based on other open source apps

@RichiX9711

Copy link
Copy Markdown

I tested this PR on real hardware with an active Digevo GeForce NOW partner account in Peru.

Test environment

Apple TV 4K (3rd generation)
Active GeForce NOW subscription through Digevo
Tested with Rocket League
Branch: feat/partner-region-login
What works

The core partner authentication flow is working:

Digevo is correctly returned and displayed as a login provider.
Selecting Digevo starts the QR/PIN device authentication flow successfully.
Authentication completes successfully.
The game library loads correctly.
The account is recognized with the expected subscription tier (ULTIMATE in my test).
Rocket League launches successfully.
WebRTC signaling, audio/video tracks, and the game stream work.

The logs also confirm that the selected partner service URL is initially resolved correctly:

startSession: base=https://prod.DIG.geforcenow.nvidiagrid.net

So the provider selection and streamingServiceUrl plumbing are working with a real partner account.

Routing issue found

I found an issue with the current partner detection in GamesViewModel.measureTopZones().

The current check is:

let streamingUrl = authManager.session?.provider.streamingServiceUrl ?? ""
guard streamingUrl.contains("nvidiagrid.net") else { return }

This does not reliably distinguish NVIDIA's default service from a partner service.

Digevo's actual partner URL is:

https://prod.DIG.geforcenow.nvidiagrid.net

Because it also contains nvidiagrid.net, NVIDIA global zone discovery still runs for the Digevo account.

During my test, CloudNow measured zones such as:

NP-ATL-04
NP-CHI-04
NP-PHX-02

At game launch it selected:

[Zones] best at launch:
https://np-atl-04.cloudmatchbeta.nvidiagrid.net/
ping=101ms

Then the session was created with:

sessionBase=https://np-atl-04.cloudmatchbeta.nvidiagrid.net/
routingZoneUrl=https://np-atl-04.cloudmatchbeta.nvidiagrid.net/

and the POST was sent directly to:

https://np-atl-04.cloudmatchbeta.nvidiagrid.net/v2/session

Therefore, although the selected provider initially resolves to Digevo, the auto-zone logic replaces the partner streamingServiceUrl with a global NVIDIA CloudMatch zone before session creation.

This appears to be caused by the interaction between:

measureTopZones() allowing Digevo because its URL also contains nvidiagrid.net.
createNewSession() using bestZoneUrl() as both sessionBase and routingZoneUrl.

I think partner detection should be based on the selected provider/default NVIDIA service rather than a substring check. Partner sessions should keep the provider's streamingServiceUrl and use no NVIDIA global zone hint, unless partner-specific zone discovery is implemented.

It may also be worth enforcing this at session creation, not only in measureTopZones(), so a partner session cannot accidentally reuse previously measured or persisted NVIDIA zones.

Build issue

The branch also failed to compile because measureTopZones() references authManager, but authManager is not available in that method's scope.

I locally fixed it by changing:

func measureTopZones() async

to:

func measureTopZones(authManager: AuthManager) async

and changing the call in MainTabView to:

.task { await viewModel.measureTopZones(authManager: authManager) }

After that change, the branch compiled and I was able to complete the full Digevo test.

tvOS provider picker issue

I also found a UI/focus issue in the provider picker. There are more providers than can fit on screen. The focus can continue moving to providers outside the visible area, but the UI does not scroll correctly to keep the focused provider visible.

During this interaction I also saw repeated tvOS focus-engine warnings:

Ignoring attempt to add focus items in already-visited container.
This can potentially cause infinite recursion.

I cannot confirm yet whether those warnings are the direct cause of the scrolling issue, but the provider picker needs focus-aware scrolling on tvOS.

Suggested next step

I can prepare a small fix that:

fixes the authManager compile error;
distinguishes the default NVIDIA service from partner providers correctly;
prevents NVIDIA global auto-zone selection from overriding a partner's streamingServiceUrl.

I would keep the provider-picker scrolling issue separate because it is an independent tvOS UI/focus problem.

I can also continue testing the changes with my real Digevo account and Apple TV hardware.

@owenselles

Copy link
Copy Markdown
Owner Author

Working on fixes for those issues will push to this pr in a few mins @RichiX9711 Thanks a lot for testing and please check again when you got time :)

The URL substring check (.contains("nvidiagrid.net")) failed for partners
like Digevo whose streamingServiceUrl also contains that domain. Fixes two
issues reported by tester with a real Digevo account:

- measureTopZones: match against NVIDIAAuth.defaultIdpId instead; also
  fix compile error by accepting authManager as a parameter (consistent
  with all other GamesViewModel methods) and update the MainTabView call site
- createNewSession: guard bestZoneUrl() behind the same idpId check so
  previously-measured NVIDIA zones cannot override a partner streamingServiceUrl
  even if topZones is stale from an earlier session
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants