diff --git a/Assets/Samples/Stream Video & Audio Chat SDK/0.9.0/Video & Audio Chat Example Project/Scripts/StreamVideoManager.cs b/Assets/Samples/Stream Video & Audio Chat SDK/0.9.0/Video & Audio Chat Example Project/Scripts/StreamVideoManager.cs index 8cec7b3a..ce016658 100644 --- a/Assets/Samples/Stream Video & Audio Chat SDK/0.9.0/Video & Audio Chat Example Project/Scripts/StreamVideoManager.cs +++ b/Assets/Samples/Stream Video & Audio Chat SDK/0.9.0/Video & Audio Chat Example Project/Scripts/StreamVideoManager.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -using System.Net.Http; using System.Threading.Tasks; using StreamVideo.Core; using StreamVideo.Core.Configs; using StreamVideo.Core.Exceptions; using StreamVideo.Core.StatefulModels; using StreamVideo.Core.StatefulModels.Tracks; +using StreamVideo.Libs; using StreamVideo.Libs.Auth; -using StreamVideo.Libs.Serialization; using StreamVideo.Libs.Utils; using UnityEngine; #if STREAM_DEBUG_ENABLED @@ -244,24 +243,6 @@ protected void OnApplicationPause(bool pauseStatus) } #endif - /// - /// API success response template when using Stream's Demo Credentials - /// - private class DemoCredentialsApiResponse - { - public string UserId; - public string Token; - public string APIKey; - } - - /// - /// API error response template when using Stream's Demo Credentials - /// - private class DemoCredentialsApiError - { - public string Error; - } - #pragma warning disable CS0414 //Disable warning that _info is unused. It's purpose is to display info box in the Unity Inspector only [SerializeField] @@ -281,6 +262,10 @@ private string _info [SerializeField] private string _userToken = ""; + [Header("Demo Credentials")] + [SerializeField] + private StreamEnvironment _environment = StreamEnvironment.Demo; + [Header("Background Music in a call")] [SerializeField] private AudioClip _musicClip = null; @@ -312,46 +297,16 @@ private async Task ConnectToStreamAsync(AuthCredentials credentials) if (credentialsEmpty) { - // If custom credentials are not defined - use Stream's Demo Credentials Debug.Log("Authorization credentials were not provided. Using Stream's Demo Credentials."); - var demoCredentials = await GetStreamDemoTokenAsync(); - credentials = new AuthCredentials(demoCredentials.APIKey, demoCredentials.UserId, - demoCredentials.Token); + var factory = new StreamDependenciesFactory(); + var provider = factory.CreateDemoCredentialsProvider(); + credentials = await provider.GetDemoCredentialsAsync("DemoUser", _environment); } await Client.ConnectUserAsync(credentials); } - /// - /// This method will fetch Stream's demo credentials. These credentials are not usable in a real production due to limited rates. - /// Customer accounts do have a FREE tier so please register at https://getstream.io/ to get your own app ID and credentials. - /// - private static async Task GetStreamDemoTokenAsync() - { - var serializer = new NewtonsoftJsonSerializer(); - var httpClient = new HttpClient(); - var uriBuilder = new UriBuilder - { - Host = "pronto.getstream.io", - Path = "/api/auth/create-token", - Query = $"user_id=DemoUser", - Scheme = "https", - }; - - var uri = uriBuilder.Uri; - var response = await httpClient.GetAsync(uri); - var result = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - var apiError = serializer.Deserialize(result); - throw new Exception( - $"Failed to get demo credentials. Error status code: `{response.StatusCode}`, Error message: `{apiError.Error}`"); - } - - return serializer.Deserialize(result); - } - private void OnCallStarted(IStreamCall call) { _activeCall = call; diff --git a/Packages/StreamVideo/Runtime/Libs/Auth/StreamDemoCredentialsProvider.cs b/Packages/StreamVideo/Runtime/Libs/Auth/StreamDemoCredentialsProvider.cs new file mode 100644 index 00000000..7e15209c --- /dev/null +++ b/Packages/StreamVideo/Runtime/Libs/Auth/StreamDemoCredentialsProvider.cs @@ -0,0 +1,98 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using StreamVideo.Libs.Http; +using StreamVideo.Libs.Serialization; + +namespace StreamVideo.Libs.Auth +{ + /// + /// Fetches demo/test credentials (API key + user token) from the Pronto endpoint. + /// DO NOT USE IN PRODUCTION. These credentials are rate-limited and meant only for internal testing and demo apps. + /// Customer accounts have a FREE tier for testing — please register at https://getstream.io/ to get your own app ID and credentials. + /// + public class StreamDemoCredentialsProvider + { + public StreamDemoCredentialsProvider(IHttpClient httpClient, ISerializer serializer) + { + _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); + _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); + } + + /// + /// Fetch demo credentials from https://pronto.getstream.io/api/auth/create-token. + /// The returned contains the API key, user ID, and signed token. + /// DO NOT USE IN PRODUCTION. Customer accounts have a FREE tier for testing — + /// please register at https://getstream.io/ to get your own app ID and credentials. + /// + public async Task GetDemoCredentialsAsync( + string userId, + StreamEnvironment environment = StreamEnvironment.Demo, + CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(userId)) + { + throw new ArgumentException("User ID must not be null or empty.", nameof(userId)); + } + + var uri = new UriBuilder + { + Scheme = "https", + Host = Host, + Path = Path, + Query = $"user_id={Uri.EscapeDataString(userId)}&environment={ToQueryValue(environment)}", + }.Uri; + + var response = await _httpClient.GetAsync(uri, cancellationToken); + if (!response.IsSuccessStatusCode) + { + string errorMessage = null; + try + { + var error = _serializer.Deserialize(response.Result); + errorMessage = error?.Error; + } + catch + { + // ignored — use raw response below + } + + throw new Exception( + $"Failed to get demo credentials. Status code: {response.StatusCode}, " + + $"Error: {errorMessage ?? response.Result}"); + } + + var result = _serializer.Deserialize(response.Result); + return new AuthCredentials(result.ApiKey, result.UserId, result.Token); + } + + private const string Host = "pronto.getstream.io"; + private const string Path = "/api/auth/create-token"; + + private static string ToQueryValue(StreamEnvironment environment) + { + switch (environment) + { + case StreamEnvironment.Demo: return "demo"; + case StreamEnvironment.Pronto: return "pronto"; + default: throw new ArgumentOutOfRangeException(nameof(environment), environment, + $"Unsupported environment: {environment}"); + } + } + + private class CredentialsResponse + { + public string UserId; + public string ApiKey; + public string Token; + } + + private class ErrorResponse + { + public string Error; + } + + private readonly IHttpClient _httpClient; + private readonly ISerializer _serializer; + } +} diff --git a/Packages/StreamVideo/Runtime/Libs/Auth/StreamDemoCredentialsProvider.cs.meta b/Packages/StreamVideo/Runtime/Libs/Auth/StreamDemoCredentialsProvider.cs.meta new file mode 100644 index 00000000..3b44088a --- /dev/null +++ b/Packages/StreamVideo/Runtime/Libs/Auth/StreamDemoCredentialsProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 917a3ed83d7d6aa4aa5399a3dbd41523 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/StreamVideo/Runtime/Libs/Auth/StreamEnvironment.cs b/Packages/StreamVideo/Runtime/Libs/Auth/StreamEnvironment.cs new file mode 100644 index 00000000..03121531 --- /dev/null +++ b/Packages/StreamVideo/Runtime/Libs/Auth/StreamEnvironment.cs @@ -0,0 +1,11 @@ +namespace StreamVideo.Libs.Auth +{ + /// + /// Stream backend environment used when fetching demo credentials from Pronto. + /// + public enum StreamEnvironment + { + Demo, + Pronto, + } +} diff --git a/Packages/StreamVideo/Runtime/Libs/Auth/StreamEnvironment.cs.meta b/Packages/StreamVideo/Runtime/Libs/Auth/StreamEnvironment.cs.meta new file mode 100644 index 00000000..cdb12e01 --- /dev/null +++ b/Packages/StreamVideo/Runtime/Libs/Auth/StreamEnvironment.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dfe7d5c118486ee4db1147a3f818d80a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/StreamVideo/Runtime/Libs/StreamDependenciesFactory.cs b/Packages/StreamVideo/Runtime/Libs/StreamDependenciesFactory.cs index 027926db..dea9b7b0 100644 --- a/Packages/StreamVideo/Runtime/Libs/StreamDependenciesFactory.cs +++ b/Packages/StreamVideo/Runtime/Libs/StreamDependenciesFactory.cs @@ -1,4 +1,4 @@ -using StreamVideo.Libs.AppInfo; +using StreamVideo.Libs.AppInfo; using StreamVideo.Libs.Auth; using StreamVideo.Libs.VideoClientInstanceRunner; using StreamVideo.Libs.Http; @@ -48,6 +48,9 @@ public virtual IHttpClient CreateHttpClient() public virtual ITokenProvider CreateTokenProvider(TokenProvider.TokenUriHandler urlFactory) => new TokenProvider(CreateHttpClient(), urlFactory); + public virtual StreamDemoCredentialsProvider CreateDemoCredentialsProvider() + => new StreamDemoCredentialsProvider(CreateHttpClient(), CreateSerializer()); + public virtual IStreamVideoClientRunner CreateClientRunner() { var go = new GameObject diff --git a/Packages/StreamVideo/Samples~/VideoChat/Scripts/StreamVideoManager.cs b/Packages/StreamVideo/Samples~/VideoChat/Scripts/StreamVideoManager.cs index 8cec7b3a..ce016658 100644 --- a/Packages/StreamVideo/Samples~/VideoChat/Scripts/StreamVideoManager.cs +++ b/Packages/StreamVideo/Samples~/VideoChat/Scripts/StreamVideoManager.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -using System.Net.Http; using System.Threading.Tasks; using StreamVideo.Core; using StreamVideo.Core.Configs; using StreamVideo.Core.Exceptions; using StreamVideo.Core.StatefulModels; using StreamVideo.Core.StatefulModels.Tracks; +using StreamVideo.Libs; using StreamVideo.Libs.Auth; -using StreamVideo.Libs.Serialization; using StreamVideo.Libs.Utils; using UnityEngine; #if STREAM_DEBUG_ENABLED @@ -244,24 +243,6 @@ protected void OnApplicationPause(bool pauseStatus) } #endif - /// - /// API success response template when using Stream's Demo Credentials - /// - private class DemoCredentialsApiResponse - { - public string UserId; - public string Token; - public string APIKey; - } - - /// - /// API error response template when using Stream's Demo Credentials - /// - private class DemoCredentialsApiError - { - public string Error; - } - #pragma warning disable CS0414 //Disable warning that _info is unused. It's purpose is to display info box in the Unity Inspector only [SerializeField] @@ -281,6 +262,10 @@ private string _info [SerializeField] private string _userToken = ""; + [Header("Demo Credentials")] + [SerializeField] + private StreamEnvironment _environment = StreamEnvironment.Demo; + [Header("Background Music in a call")] [SerializeField] private AudioClip _musicClip = null; @@ -312,46 +297,16 @@ private async Task ConnectToStreamAsync(AuthCredentials credentials) if (credentialsEmpty) { - // If custom credentials are not defined - use Stream's Demo Credentials Debug.Log("Authorization credentials were not provided. Using Stream's Demo Credentials."); - var demoCredentials = await GetStreamDemoTokenAsync(); - credentials = new AuthCredentials(demoCredentials.APIKey, demoCredentials.UserId, - demoCredentials.Token); + var factory = new StreamDependenciesFactory(); + var provider = factory.CreateDemoCredentialsProvider(); + credentials = await provider.GetDemoCredentialsAsync("DemoUser", _environment); } await Client.ConnectUserAsync(credentials); } - /// - /// This method will fetch Stream's demo credentials. These credentials are not usable in a real production due to limited rates. - /// Customer accounts do have a FREE tier so please register at https://getstream.io/ to get your own app ID and credentials. - /// - private static async Task GetStreamDemoTokenAsync() - { - var serializer = new NewtonsoftJsonSerializer(); - var httpClient = new HttpClient(); - var uriBuilder = new UriBuilder - { - Host = "pronto.getstream.io", - Path = "/api/auth/create-token", - Query = $"user_id=DemoUser", - Scheme = "https", - }; - - var uri = uriBuilder.Uri; - var response = await httpClient.GetAsync(uri); - var result = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - var apiError = serializer.Deserialize(result); - throw new Exception( - $"Failed to get demo credentials. Error status code: `{response.StatusCode}`, Error message: `{apiError.Error}`"); - } - - return serializer.Deserialize(result); - } - private void OnCallStarted(IStreamCall call) { _activeCall = call; diff --git a/Packages/StreamVideo/Tests/Shared/TestClient.cs b/Packages/StreamVideo/Tests/Shared/TestClient.cs index 9816146d..7613cf58 100644 --- a/Packages/StreamVideo/Tests/Shared/TestClient.cs +++ b/Packages/StreamVideo/Tests/Shared/TestClient.cs @@ -1,12 +1,11 @@ -#if STREAM_TESTS_ENABLED +#if STREAM_TESTS_ENABLED using System; using System.Diagnostics; -using System.Net.Http; using System.Threading.Tasks; using StreamVideo.Core; using StreamVideo.Core.StatefulModels; +using StreamVideo.Libs; using StreamVideo.Libs.Auth; -using StreamVideo.Libs.Serialization; using UnityEngine; using Debug = UnityEngine.Debug; @@ -52,7 +51,10 @@ public async Task ConnectAsync() var timer = new Stopwatch(); timer.Start(); - var getCredentialsTask = GetStreamDemoCredentialsAsync(); + var factory = new StreamDependenciesFactory(); + var provider = factory.CreateDemoCredentialsProvider(); + + var getCredentialsTask = provider.GetDemoCredentialsAsync("DemoUser", StreamEnvironment.Demo); while (!getCredentialsTask.IsCompleted) { await Task.Delay(1); @@ -64,9 +66,7 @@ public async Task ConnectAsync() } } - var demoCredentials = getCredentialsTask.Result; - var credentials - = new AuthCredentials(demoCredentials.APIKey, demoCredentials.UserId, demoCredentials.Token); + var credentials = getCredentialsTask.Result; var connectTask = Client.ConnectUserAsync(credentials); @@ -89,45 +89,6 @@ var credentials Debug.Log($"Client connected in {timer.Elapsed.TotalSeconds:F2} seconds"); } - private class DemoCredentialsApiResponse - { - public string UserId; - public string Token; - public string APIKey; - } - - private class DemoCredentialsApiError - { - public string Error; - } - - private static async Task GetStreamDemoCredentialsAsync() - { - Debug.Log("Get demo credentials " + Time.time); - var serializer = new NewtonsoftJsonSerializer(); - var httpClient = new HttpClient(); - var uriBuilder = new UriBuilder - { - Host = "pronto.getstream.io", - Path = "/api/auth/create-token", - Query = $"user_id=DemoUser", - Scheme = "https", - }; - - var uri = uriBuilder.Uri; - var response = await httpClient.GetAsync(uri); - var result = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - var apiError = serializer.Deserialize(result); - throw new Exception( - $"Failed to get demo credentials. Error status code: `{response.StatusCode}`, Error message: `{apiError.Error}`"); - } - - Debug.Log("Demo credentials received: " + Time.time); - - return serializer.Deserialize(result); - } } } #endif \ No newline at end of file