feat(auth): partner region login (Jio, bro.game, etc.) - #64
Conversation
|
@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. |
|
Agree also for testing this we need someone with a partner account |
|
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. |
|
Yea @RichiX9711 if you can that would be of great help as no one else I know has a partner account |
|
So I have no real way to test and implement this. Current implementation is based on other open source apps |
|
I tested this PR on real hardware with an active Digevo GeForce NOW partner account in Peru. Test environment Apple TV 4K (3rd generation) The core partner authentication flow is working: Digevo is correctly returned and displayed as a login provider. 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 ?? "" 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 At game launch it selected: [Zones] best at launch: Then the session was created with: sessionBase=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. 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. 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; 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. |
|
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 :) |
|
Hi guys, it's been a few days since my last comment, I have completed the real-hardware validation of PR #64 using an active Digevo GeForce NOW account in Peru. PR scope validationThe original goal of this PR — authenticating and launching games through a third-party GeForce NOW partner — is working successfully in my environment. Test environment:
The following flow now works end to end:
Based on these results, I consider the original functional scope of PR #64 complete. Partner routing and automatic region selectionThe official GeForce NOW macOS client only exposes one selectable region for my account, named “LATAM West”. For CloudNow, however, I tested Digevo using provider-managed automatic routing instead of forcing that NVIDIA region manually. The important behavior is:
This is consistent with the changes already added to the PR that identify NVIDIA-direct sessions using the provider That distinction is necessary because Digevo’s own service URL also uses an NVIDIA Grid domain. Additional local telemetry workWhile testing Rocket League, I noticed visible stuttering during rapid camera movement. This appeared more frequently at 4K. To determine whether the stuttering came from Digevo/NVIDIA, the Apple TV decoder, or CloudNow’s rendering pipeline, I added local diagnostic telemetry. These diagnostics are not required for the partner-login functionality and are currently outside the intended scope of PR #64. The local telemetry uses CloudNow’s existing one-second WebRTC statistics timer. It does not create another timer or perform an additional WebRTC statistics query. In Diagnostic mode, it records:
I also corrected the interval packet-loss calculation so that it is reset for every statistics sample and cannot reuse the previous interval’s percentage. Comparative testsI performed separate 1080p and 4K Rocket League sessions on the same Apple TV and provider account. 1080pDuring the stable gameplay portion:
4KDuring the stable gameplay portion:
The camera-motion stuttering was consistent with these chronological FPS drops. Current findingsThe network does not currently appear to be the main cause:
The existing local pipeline counters also remained at zero:
The Apple TV requires more decode time at 4K than at 1080p, as expected, but the measured 4K decode time remained below the approximately There were also complete 4K windows that maintained 60 FPS with similar decode times. Therefore, the current data does not demonstrate decoder saturation or that the Apple TV is incapable of decoding the stream. The most significant observation is that, during severe 4K FPS reductions, bitrate decreases almost exactly in proportion to the number of frames. For example, a reduction from approximately 60 FPS at 95 Mbps to 42 FPS resulted in approximately 66.6 Mbps. The approximate number of bits per frame remained almost constant. This suggests that fewer frames may already be produced or delivered during those intervals, rather than CloudNow receiving 60 complete frames and dropping them locally. However, the current
Because of that, I do not think the logs are sufficient to assign the problem definitively to Digevo/NVIDIA, VideoToolbox, or CloudNow’s presentation pipeline. There is also one uncontrolled variable in the comparison: the 1080p and 4K sessions were assigned to different Digevo infrastructure hosts, although both were routed through the same Digevo CloudMatch service. Suggested follow-up outside PR #64The next useful diagnostic step would be to instrument the complete frame path:
In particular:
This would establish the responsible stage:
Sharing the evidenceI can provide sanitized versions of the 1080p and 4K telemetry logs. Before sharing them publicly, I will remove or normalize authentication data, account identifiers, request identifiers, local addresses, session-specific values and any potentially sensitive infrastructure details. I also have the diagnostic instrumentation as a local code change. Since it is outside the scope of PR #64, I have not assumed that it should be added to this branch. Please let me know which form would be most useful:
For now, my conclusion is that the third-party login and provider-managed Digevo routing are working correctly, while the 4K stuttering investigation should be treated as a separate diagnostic topic. |
|
Nicee good that it works now! |
|
@RichiX9711 Thank you for the thorough validation report — this is exactly the kind of real-hardware evidence needed to confirm the partner routing is correct. Two things addressed based on your findings: Provider picker scrolling — fixed. The Partner routing guard — the For the 4K diagnostic work — a separate draft PR from your fork with just the telemetry instrumentation would be ideal. That keeps the frame-path instrumentation reviewable on its own and avoids scope creep here. If you open it I'll take a look. The 4K stuttering investigation findings (frames-received vs decoded vs rendered breakdown) are worth tracking separately too — feel free to open an issue for that so it doesn't get lost. |
6f85002 to
bd2071c
Compare
- LoginView: fetch providers on appear and show a scrollable picker when multiple providers are available; @focusstate drives ScrollViewReader to keep the focused button centred (fixes tvOS focus-engine blind spot) - StreamView: guard NVIDIA zone/region selection with isNvidiaProvider so partner sessions route through their own infrastructure unchanged - README: document partner provider support and update requirements line
bd2071c to
6f6ecad
Compare
|
@owenselles The approach looks directionally good to me. I especially like that the routing fix moved away from checking whether the streaming URL contains Before merging, I think there are a few things worth tightening up:
|
- LoginProvider.isNvidiaDirect: centralizes the idpId==defaultIdpId check so it is not repeated inline across StreamView and SettingsView - LoginView: replace the nil-providers fallback with an explicit ProvidersState enum (.loading / .loaded); shows a spinner while the provider list is fetching so a partner-region user cannot accidentally tap the NVIDIA button before providers arrive; sets initial @focusstate to the first provider for deterministic tvOS focus on load - SettingsView: hide the server-location picker for partner sessions and replace it with a "Managed by partner provider" note, since those settings are silently ignored for partner routing anyway - Localization: add managed_by_partner key to all 34 locale tables
|
@owenselles I reviewed the latest head ( The latest commit adds the requested loading state, partner-managed Settings message, initial provider focus, and centralized MAJOR — Partner session creation can still fall back to NVIDIA
Every partner endpoint differs from This bypasses the new partner-routing guarantee and could:
The fallback policy should be explicit:
Please test a simulated partner HTTP failure and confirm that no request is sent to MAJOR — A single returned partner is treated as NVIDIA
For If the endpoint returns one partner provider, the UI therefore:
Please distinguish these states explicitly:
A single provider should use its own The NVIDIA fallback should only appear after an actual provider-fetch failure or when the sole provider is confirmed as NVIDIA-direct. MAJOR — “Try Again” forgets the selected partner
If the user selected a non-first partner provider and authentication fails, “Try Again” fetches the providers again and selects Please retain the attempted provider in “Cancel” can continue returning the user to the provider picker. MAJOR — Network Test can still test a stale NVIDIA route for partner users
The Settings picker is hidden for partner sessions, but A partner account can therefore still test:
For partner sessions:
Please test NVIDIA-direct → logout → partner login → Network Test without restarting the app. MAJOR — Persisted session and VPC state has no provider/account identity
After signing out and selecting another provider, The cached VPC ID is also used immediately while revalidation happens in the background. A newly selected partner can therefore receive initial catalog/library requests containing an NVIDIA or different-partner VPC ID. Suggested handling:
This is especially important for partner-to-partner switching because it avoids sending one partner’s token to another partner’s endpoint. Localization follow-upMINOR — New text is English in every locale
The new key currently contains |
…on identity, cache keying, l10n - CloudMatchClient: partner sessions no longer fall back to NVIDIA's global endpoint; SessionCreateRequest gains skipNvidiaFallback which gates the [preferredBase, fallbackBase] retry list to [preferredBase] only for partners. - LoginView: add @State selectedProvider so the correct provider is carried through to "Try Again" after a login failure; handle the single-provider case explicitly so a solo partner provider shows its own displayName and calls login(with:) instead of the NVIDIA fallback. - LastSessionRecord: add idpId field (backward-compat decode defaults to NVIDIAAuth.defaultIdpId); GamesViewModel.load() discards a persisted session whose idpId doesn't match the current provider before restoring it. - StreamView: pass skipNvidiaFallback and the current provider's idpId when creating and persisting a session. - ServerInfoClient: add cachedBase tracking and cachedForBase(_:) so the cache is provider-keyed; SettingsView NetworkTest resolveTarget() guards routing-mode branches with isNvidiaSession and uses cachedForBase(). - Localization: translate managed_by_partner into all 33 non-English locales.
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 inNVIDIAAuthAPI.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 availableGamesViewModel: guardsmeasureTopZones()to skip PrintedWaste zone discovery for non-nvidiagrid.netproviders — 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 connectionNo changes to auth endpoints,
CloudMatchClient,GamesClient, or any streaming code — partneridpIdfederation happens server-side onlogin.nvidia.com.Test plan
streamingServiceUrlwith no zone hint