WebAuthForContracts

class WebAuthForContracts(val authEndpoint: String, val webAuthContractId: String, val serverSigningKey: String, val serverHomeDomain: String, val network: Network, httpClient: HttpClient? = null, httpRequestHeaders: Map<String, String>? = null, val sorobanRpcUrl: String? = null)

SEP-45 Web Authentication client for contract accounts.

Provides secure authentication for Stellar smart contract accounts (C... addresses) using a challenge-response protocol with Soroban authorization entry signing. This implements the client side of the SEP-45 specification for authenticating contract accounts with Stellar services.

SEP-45 complements SEP-10, which handles traditional Stellar accounts (G... and M... addresses). Use this class when authenticating contract accounts; use SEP-10 WebAuth for regular accounts.

SEP-45 Authentication Flow

  1. Client requests authorization entries from the authentication server

  2. Server generates entries with specific security requirements and signs them

  3. Client validates the authorization entries (13 security checks)

  4. Client signs the validated entries with their keypair(s)

  5. Client submits the signed entries back to the server

  6. Server verifies the signatures via contract simulation and returns a JWT token

  7. Client uses the JWT token to authenticate subsequent API requests

The JWT token can be used to authenticate requests to SEP-6 (Deposit/Withdrawal), SEP-12 (KYC), SEP-24 (Hosted Deposit/Withdrawal), SEP-31 (Cross-Border Payments), and other Stellar services that require authentication.

Usage Patterns

High-Level API (Recommended for most use cases):

// Initialize from domain's stellar.toml
val webAuth = WebAuthForContracts.fromDomain("example.com", Network.PUBLIC)

// One-line authentication
val authToken = webAuth.jwtToken(
clientAccountId = contractId,
signers = listOf(signerKeyPair)
)

// Use token in API requests
httpClient.get("https://example.com/api/account") {
header("Authorization", "Bearer ${authToken.token}")
}

Contracts Without Signature Requirements:

// Some contracts implement __check_auth without requiring signatures
val authToken = webAuth.jwtToken(
clientAccountId = contractId,
signers = emptyList() // Valid for such contracts
)

Client Domain Verification (Local Signing):

val authToken = webAuth.jwtToken(
clientAccountId = contractId,
signers = listOf(signerKeyPair),
clientDomain = "wallet.mycompany.com",
clientDomainAccountKeyPair = clientDomainSigningKey
)

Client Domain Verification (Remote Signing):

val signingDelegate = Sep45ClientDomainSigningDelegate { entryXdr ->
// Send to wallet backend for domain signing
val response = httpClient.post("https://backend.wallet.com/sign") {
setBody(SignRequest(entryXdr))
}
response.body<SignResponse>().signedEntry
}

val authToken = webAuth.jwtToken(
clientAccountId = contractId,
signers = listOf(signerKeyPair),
clientDomain = "wallet.mycompany.com",
clientDomainSigningDelegate = signingDelegate
)

Security Considerations

  • Always validate the challenge before signing (done automatically in jwtToken())

  • Verify HTTPS is used for all communication with the authentication endpoint

  • Verify the server's signing key matches the stellar.toml SIGNING_KEY

  • Never skip validation checks (all checks are required)

  • Store JWT tokens securely (encrypted storage, not in logs)

  • Check token expiration before use

  • Use fromDomain to automatically discover and verify server configuration

See also:

Constructors

Link copied to clipboard
constructor(authEndpoint: String, webAuthContractId: String, serverSigningKey: String, serverHomeDomain: String, network: Network, httpClient: HttpClient? = null, httpRequestHeaders: Map<String, String>? = null, sorobanRpcUrl: String? = null)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard

The authentication endpoint URL (from stellar.toml WEB_AUTH_FOR_CONTRACTS_ENDPOINT)

Link copied to clipboard

The Stellar network (Network.PUBLIC or Network.TESTNET)

Link copied to clipboard

The home domain of the server (used in challenge validation)

Link copied to clipboard

The server's public signing key (from stellar.toml SIGNING_KEY, G... address)

Link copied to clipboard

Optional Soroban RPC URL for ledger queries (defaults based on network)

Link copied to clipboard

Whether to use application/x-www-form-urlencoded content type for token submission. If false, uses application/json.

Link copied to clipboard

The web auth contract ID (from stellar.toml WEB_AUTH_CONTRACT_ID, C... address)

Functions

Link copied to clipboard

Decodes authorization entries from base64 XDR.

Link copied to clipboard

Encodes authorization entries to base64 XDR.

Link copied to clipboard
suspend fun getChallenge(clientAccountId: String, homeDomain: String? = null, clientDomain: String? = null): Sep45ChallengeResponse

Requests a challenge from the authentication server.

Link copied to clipboard
suspend fun jwtToken(clientAccountId: String, signers: List<KeyPair> = emptyList(), homeDomain: String? = null, clientDomain: String? = null, clientDomainAccountKeyPair: KeyPair? = null, clientDomainSigningDelegate: Sep45ClientDomainSigningDelegate? = null, signatureExpirationLedger: Long? = null): Sep45AuthToken

Performs complete SEP-45 authentication flow.

Link copied to clipboard

Submits signed authorization entries to obtain a JWT token.

Link copied to clipboard
suspend fun signAuthorizationEntries(authEntries: List<SorobanAuthorizationEntryXdr>, clientAccountId: String, signers: List<KeyPair>, signatureExpirationLedger: Long?, clientDomainKeyPair: KeyPair? = null, clientDomainAccountId: String? = null, clientDomainSigningDelegate: Sep45ClientDomainSigningDelegate? = null): List<SorobanAuthorizationEntryXdr>

Signs the authorization entries for the client account.

Link copied to clipboard
suspend fun validateChallenge(authEntries: List<SorobanAuthorizationEntryXdr>, clientAccountId: String, homeDomain: String? = null, clientDomainAccountId: String? = null)

Validates the authorization entries from the challenge response.