diff --git a/.changeset/development-token-source.md b/.changeset/development-token-source.md new file mode 100644 index 000000000..ecd6dacb7 --- /dev/null +++ b/.changeset/development-token-source.md @@ -0,0 +1,5 @@ +--- +"client-sdk-android": minor +--- + +Add `TokenSource.fromDevelopmentTokenServer`, the new name for the now-deprecated `TokenSource.fromSandboxTokenServer` (`SandboxTokenServerOptions` is likewise deprecated in favor of `DevelopmentTokenServerOptions`) diff --git a/README.md b/README.md index c3a625149..fd81df9ce 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Use this SDK to add realtime video, audio and data features to your Android/Kotl - [SDK Size](#sdk-size) - [Usage](#usage) - [Permissions](#permissions) + - [Token sources](#token-sources) - [Publishing camera and microphone](#publishing-camera-and-microphone) - [Sharing screen](#sharing-screen) - [Rendering subscribed tracks](#rendering-subscribed-tracks) @@ -102,6 +103,77 @@ These permission must be requested at runtime. Reference the [sample app](https://github.com/livekit/client-sdk-android/blob/4e76e36e0d9f895c718bd41809ab5ff6c57aabd4/sample-app-compose/src/main/java/io/livekit/android/composesample/MainActivity.kt#L134) for an example. +### Token sources + +To connect to a room, you need a server URL and a participant token. The `TokenSource` factory +methods cover the common ways of obtaining these credentials: + +#### 1. Literal + +Use this to pass a pregenerated server URL and token. Generate tokens via the +[LiveKit CLI](https://docs.livekit.io/frontends/build/authentication/custom/#manual-token-creation) +or from your [LiveKit Cloud](https://cloud.livekit.io/) project's API key page. + +```kt +val source = TokenSource.fromLiteral("wss://your.livekit.host", "your_token") +``` + +#### 2. Development Token Server + +For development and testing. Follow the +[development token server guide](https://docs.livekit.io/frontends/build/authentication/sandbox-token-server/) +to enable your project's development token server and get the token server ID from the settings page. + +This token generation mechanism is inherently insecure and should only be used for prototyping; +do **not** use it in production. + +```kt +val source = TokenSource.fromDevelopmentTokenServer("your token server id") +``` + +#### 3. Endpoint + +For production. Point to your own token endpoint URL and add any required authentication headers. +The request and response follow the standard format described in the +[endpoint token generation guide](https://docs.livekit.io/frontends/build/authentication/endpoint/). + +```kt +val source = TokenSource.fromEndpoint( + url = "https://your.token-server/api/token", + headers = mapOf("Authorization" to "Bearer "), +) +``` + +#### 4. Custom + +For fully custom logic, supply your own fetch function: + +```kt +val source = TokenSource.fromCustom { options -> + // Generate credentials via custom means here. + Result.success(TokenSourceResponse(serverUrl = "...", participantToken = "...")) +} +``` + +#### Fetching credentials and connecting + +Configurable token sources (development token server, endpoint, custom) accept +`TokenRequestOptions` per fetch; fixed sources (literal) take no options: + +```kt +val response = source.fetch( + TokenRequestOptions(roomName = "room", participantName = "participant"), +).getOrThrow() + +room.connect(response.serverUrl, response.participantToken) +``` + +To avoid refetching credentials that are still valid, wrap any token source with `.cached()`: + +```kt +val cachedSource = source.cached() +``` + ### Publishing camera and microphone ```kt diff --git a/livekit-android-sdk/src/main/java/io/livekit/android/token/EndpointTokenSource.kt b/livekit-android-sdk/src/main/java/io/livekit/android/token/EndpointTokenSource.kt index 6f3cdd30a..c0dfef7a4 100644 --- a/livekit-android-sdk/src/main/java/io/livekit/android/token/EndpointTokenSource.kt +++ b/livekit-android-sdk/src/main/java/io/livekit/android/token/EndpointTokenSource.kt @@ -46,14 +46,29 @@ internal class EndpointTokenSourceImpl( ) : this(URL(url), method, headers) } +/** + * Options for [TokenSource.fromDevelopmentTokenServer]. + * + * @param baseUrl optionally overrides the base url of the development token server. + */ +data class DevelopmentTokenServerOptions( + val baseUrl: String? = null, +) + +/** + * Options for the deprecated [TokenSource.fromSandboxTokenServer]. + * + * @see DevelopmentTokenServerOptions + */ +@Deprecated("Use DevelopmentTokenServerOptions instead", ReplaceWith("DevelopmentTokenServerOptions(baseUrl)")) data class SandboxTokenServerOptions( val baseUrl: String? = null, ) -internal class SandboxTokenSource(sandboxId: String, options: SandboxTokenServerOptions) : EndpointTokenSource { +internal class DevelopmentTokenSource(tokenServerId: String, options: DevelopmentTokenServerOptions) : EndpointTokenSource { override val url: URL = URL("${options.baseUrl ?: "https://cloud-api.livekit.io"}/api/v2/sandbox/connection-details") override val headers: Map = mapOf( - "X-Sandbox-ID" to sandboxId, + "X-Sandbox-ID" to tokenServerId, ) } diff --git a/livekit-android-sdk/src/main/java/io/livekit/android/token/TokenSource.kt b/livekit-android-sdk/src/main/java/io/livekit/android/token/TokenSource.kt index 866e48f15..f665918fa 100644 --- a/livekit-android-sdk/src/main/java/io/livekit/android/token/TokenSource.kt +++ b/livekit-android-sdk/src/main/java/io/livekit/android/token/TokenSource.kt @@ -165,6 +165,8 @@ interface TokenSource { /** * Creates a [ConfigurableTokenSource] that fetches from a given [url] using the standard token server format. * + * For more info: [https://docs.livekit.io/frontends/build/authentication/endpoint/](https://docs.livekit.io/frontends/build/authentication/endpoint/) + * * @param method the HTTP request method to use. Defaults to POST. * @see cached * @see CachingConfigurableTokenSource @@ -178,6 +180,8 @@ interface TokenSource { /** * Creates a [ConfigurableTokenSource] that fetches from a given [url] using the standard token server format. * + * For more info: [https://docs.livekit.io/frontends/build/authentication/endpoint/](https://docs.livekit.io/frontends/build/authentication/endpoint/) + * * @param method the HTTP request method to use. Defaults to POST. * @see cached * @see CachingConfigurableTokenSource @@ -189,18 +193,35 @@ interface TokenSource { ) /** - * Creates a [ConfigurableTokenSource] that fetches from a sandbox token server for credentials, + * Creates a [ConfigurableTokenSource] that queries a development token server for credentials, * which supports quick prototyping/getting started types of use cases. * * Note: This token provider is **insecure** and should **not** be used in production. * + * For more info: [https://docs.livekit.io/frontends/build/authentication/sandbox-token-server/](https://docs.livekit.io/frontends/build/authentication/sandbox-token-server/) + * * @see cached * @see CachingConfigurableTokenSource */ - fun fromSandboxTokenServer(sandboxId: String, options: SandboxTokenServerOptions = SandboxTokenServerOptions()): ConfigurableTokenSource = SandboxTokenSource( - sandboxId = sandboxId, + fun fromDevelopmentTokenServer( + tokenServerId: String, + options: DevelopmentTokenServerOptions = DevelopmentTokenServerOptions(), + ): ConfigurableTokenSource = DevelopmentTokenSource( + tokenServerId = tokenServerId, options = options, ) + + /** + * Creates a [ConfigurableTokenSource] that queries a development token server for credentials. + * + * Note: This token provider is **insecure** and should **not** be used in production. + * + * @see fromDevelopmentTokenServer + */ + @Suppress("DEPRECATION") + @Deprecated("Use fromDevelopmentTokenServer instead", ReplaceWith("fromDevelopmentTokenServer(sandboxId, DevelopmentTokenServerOptions(options.baseUrl))")) + fun fromSandboxTokenServer(sandboxId: String, options: SandboxTokenServerOptions = SandboxTokenServerOptions()): ConfigurableTokenSource = + fromDevelopmentTokenServer(sandboxId, DevelopmentTokenServerOptions(baseUrl = options.baseUrl)) } } diff --git a/livekit-android-test/src/test/java/io/livekit/android/token/TokenSourceTest.kt b/livekit-android-test/src/test/java/io/livekit/android/token/TokenSourceTest.kt index f7683b99d..c5aedc8fa 100644 --- a/livekit-android-test/src/test/java/io/livekit/android/token/TokenSourceTest.kt +++ b/livekit-android-test/src/test/java/io/livekit/android/token/TokenSourceTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 LiveKit, Inc. + * Copyright 2025-2026 LiveKit, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -187,8 +187,8 @@ class TokenSourceTest : BaseTest() { @Ignore("For manual testing only.") @Test fun testTokenServer() = runTest { - val source = TokenSource.fromSandboxTokenServer( - "", // Put sandboxId here to test manually. + val source = TokenSource.fromDevelopmentTokenServer( + "", // Put tokenServerId here to test manually. ) val options = TokenRequestOptions( roomName = "room-name",