# Token Authentication (/sdks/kotlin/how-to/connection/token-auth)



## Overview [#overview]

**Token authentication** proves a client's identity to a KubeMQ server that has authentication enabled, without embedding a username/password or issuing per-client TLS certs. It's the mechanism you reach for in shared clusters, multi-tenant deployments, or any environment where you need to control and audit which clients are allowed to connect — the token is issued and revoked by your identity provider, not baked into the application.

The token travels as a gRPC metadata header attached to every outgoing request, set via the `authToken` property in the client's DSL builder. The server validates it before honoring any call, including the initial handshake. Because a static token eventually expires, the recommended pattern is to source it from an environment variable (`System.getenv("KUBEMQ_AUTH_TOKEN")`) or `ClientConfig.fromEnvironment()` rather than hardcoding it, so rotation only requires updating the environment and rebuilding the client — the SDK does not refresh tokens automatically.

**Gotchas:** an invalid or expired token isn't rejected until the first real request — call `ping()` right after building the client so failures surface as a non-retryable `KubeMQException.Authentication` immediately, not on your first business request; never commit a real token to source control; and because token refresh isn't automatic, short-lived JWTs need your application to rebuild the client with a new token before the old one expires, not a set-and-forget builder property.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000` with authentication enabled
* Kotlin SDK installed (`implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1")`)
* A valid JWT token or API key

## Code [#code]

```kotlin title="TokenAuthExample.kt"
package io.kubemq.sdk.examples.connection

import io.kubemq.sdk.client.KubeMQClient
import kotlinx.coroutines.runBlocking

private const val ADDRESS = "localhost:50000"
private const val CLIENT_ID = "kotlin-connection-token-auth"
private const val AUTH_TOKEN = "your-jwt-token-or-api-key"

fun main() = runBlocking {
    // 1. Connect with environment token
    println("=== Connecting with Token from Environment ===\n")
    val envToken = System.getenv("KUBEMQ_AUTH_TOKEN")
    if (envToken.isNullOrBlank()) {
        println("KUBEMQ_AUTH_TOKEN environment variable not set.")
        println("  export KUBEMQ_AUTH_TOKEN=your-token-here\n")
    } else {
        val envClient = KubeMQClient.queues {
            address = ADDRESS
            clientId = CLIENT_ID
            authToken = envToken
        }
        envClient.use {
            val info = it.ping()
            println("Connected with environment token!")
            println("Server: ${info.host} v${info.version}")
        }
    }

    // 2. Connect with direct token
    println("=== Connecting with Authentication Token ===\n")
    try {
        val client = KubeMQClient.queues {
            address = ADDRESS
            clientId = CLIENT_ID
            authToken = AUTH_TOKEN
        }
        client.use {
            val info = it.ping()
            println("Successfully authenticated and connected!")
            println("Server: ${info.host}")
        }
    } catch (e: Exception) {
        println("Authentication failed: ${e.message}")
    }

    println("\nToken auth examples completed.")
}
```

## How It Works [#how-it-works]

* The `authToken` property in the DSL builder sets the JWT bearer token sent with every gRPC request.
* `System.getenv("KUBEMQ_AUTH_TOKEN")` reads the token from an environment variable for secure configuration.
* Authentication failures throw `KubeMQException.Authentication` which is non-retryable.
* Tokens can also be loaded from `ClientConfig.fromEnvironment()`.

## Related [#related]

* [Connect](/sdks/kotlin/tutorials/connect)
* [Connection Error](/sdks/kotlin/how-to/error-handling/connection-error)
* [TLS Setup](/sdks/kotlin/how-to/tls/tls-setup)
