WebAuthForContracts
public final class WebAuthForContracts : @unchecked Sendable
Implements SEP-45 - Stellar Web Authentication for Contract Accounts.
This class provides functionality for authenticating Soroban smart contract accounts (C… addresses) through the Stellar Web Authentication protocol. The authentication flow returns a JWT token that can be used for subsequent requests to SEP-compliant services (SEP-6, SEP-12, SEP-24, SEP-31).
SEP-45 extends the SEP-10 authentication protocol to support contract accounts, which have different authentication requirements than traditional Stellar accounts. Contract accounts can implement custom authentication logic in their __check_auth function.
Typical Workflow
- Initialize from Domain: Create a WebAuthForContracts instance using the anchor’s stellar.toml
- Get JWT Token: Request and obtain a JWT token for authentication
- Use Token: Include the JWT token in subsequent SEP service requests
Example Usage
// Step 1: Create WebAuthForContracts from anchor domain
let result = await WebAuthForContracts.from(
domain: "testanchor.stellar.org",
network: .testnet
)
switch result {
case .success(let webAuth):
// Step 2: Get JWT token for contract account
let contractId = "CABC..."
let signerKeyPair = try KeyPair(secretSeed: "S...")
let jwtResult = await webAuth.jwtToken(
forContractAccount: contractId,
signers: [signerKeyPair]
)
switch jwtResult {
case .success(let jwtToken):
// Step 3: Use JWT token for SEP-24, SEP-6, SEP-12, etc.
print("JWT Token: \(jwtToken)")
case .failure(let error):
print("JWT token error: \(error)")
}
case .failure(let error):
print("WebAuth initialization error: \(error)")
}
Advanced Features
Multi-Signature Contracts:
// Provide multiple signers for contracts requiring multiple signatures
let signers = [keyPair1, keyPair2]
let result = await webAuth.jwtToken(
forContractAccount: contractId,
signers: signers
)
Contracts Without Signature Requirements:
// For contracts whose __check_auth doesn't require signatures
let result = await webAuth.jwtToken(
forContractAccount: contractId,
signers: [] // Empty signers array
)
Client Domain Signing:
// For client domain verification (mutual authentication)
let clientDomainKeyPair = try KeyPair(accountId: "G...")
let result = await webAuth.jwtToken(
forContractAccount: contractId,
signers: [contractSignerKeyPair],
clientDomain: "wallet.example.com",
clientDomainAccountKeyPair: clientDomainKeyPair,
clientDomainSigningCallback: { entry in
// Sign on server and return signed entry
return try await signOnServer(entry)
}
)
See also:
- SEP-0045 Specification
- [StellarToml] for discovering authentication endpoints
- [WebAuthenticator] for traditional account (G… and M…) authentication
-
The URL of the SEP-45 web authentication endpoint for obtaining JWT tokens.
Declaration
Swift
public let authEndpoint: String -
The web auth contract ID (C… address) from stellar.toml.
Declaration
Swift
public let webAuthContractId: String -
The server’s public signing key (G… address) used to validate challenge signatures.
Declaration
Swift
public let serverSigningKey: String -
The server’s home domain hosting the stellar.toml configuration file.
Declaration
Swift
public let serverHomeDomain: String -
The Stellar network used for authentication and signature validation.
Declaration
Swift
public let network: Network -
Whether to use application/x-www-form-urlencoded (true) or application/json (false) for requests.
Declaration
Swift
public var useFormUrlEncoded: Bool -
Optional Soroban RPC URL for fetching current ledger (defaults based on network).
Declaration
Swift
public var sorobanRpcUrl: String?
-
from(domain:Asynchronousnetwork: secure: ) Creates a WebAuthForContracts instance by fetching configuration from a domain’s stellar.toml file.
This is the recommended way to initialize a WebAuthForContracts. It automatically retrieves the authentication endpoint, web auth contract ID, and server signing key from the anchor’s stellar.toml configuration file.
Example:
let result = await WebAuthForContracts.from( domain: "testanchor.stellar.org", network: .testnet )Declaration
Swift
public static func from(domain: String, network: Network, secure: Bool = true) async -> WebAuthForContractsForDomainEnumParameters
domainThe anchor’s domain (e.g., “testanchor.stellar.org”)
networkThe Stellar network to use (.public, .testnet, or .futurenet)
secureWhether to use HTTPS (true) or HTTP (false). Default is true.
Return Value
WebAuthForContractsForDomainEnum indicating success with instance or failure with error
-
Initializes a WebAuthForContracts instance with explicit configuration parameters.
Throws
WebAuthForContractsError if parameters are invalidDeclaration
Swift
public init( authEndpoint: String, webAuthContractId: String, serverSigningKey: String, serverHomeDomain: String, network: Network, sorobanRpcUrl: String? = nil ) throwsParameters
authEndpointEndpoint to be used for the authentication procedure. Usually taken from stellar.toml.
webAuthContractIdThe web auth contract ID (C… address). Usually taken from stellar.toml.
serverSigningKeyThe server public key (G… address), taken from stellar.toml.
serverHomeDomainThe server home domain of the server where the stellar.toml was loaded from.
networkThe network used.
sorobanRpcUrlOptional Soroban RPC URL. Defaults based on network if not provided.
-
jwtToken(forContractAccount:Asynchronoussigners: homeDomain: clientDomain: clientDomainAccountKeyPair: clientDomainSigningCallback: signatureExpirationLedger: ) Obtains a JWT token through the SEP-45 authentication flow.
This method handles the complete authentication workflow: requesting a challenge from the server, validating it, signing it with the provided keypairs, and submitting it to receive a JWT token. The returned token can be used for authenticating with SEP-6, SEP-12, SEP-24, SEP-31, and other services.
Example:
let contractId = "CABC..." let signerKeyPair = try KeyPair(secretSeed: "S...") let result = await webAuth.jwtToken( forContractAccount: contractId, signers: [signerKeyPair] )Declaration
Swift
public func jwtToken( forContractAccount clientAccountId: String, signers: [KeyPair], homeDomain: String? = nil, clientDomain: String? = nil, clientDomainAccountKeyPair: KeyPair? = nil, clientDomainSigningCallback: ((SorobanAuthorizationEntryXDR) async throws -> SorobanAuthorizationEntryXDR)? = nil, signatureExpirationLedger: UInt32? = nil ) async -> GetContractJWTTokenResponseEnumParameters
forContractAccountThe contract account ID (starting with C) to authenticate
signersArray of KeyPair objects with secret keys for signing the challenge. For contracts that implement __check_auth with signature verification, provide keypairs with sufficient weight. Can be empty for contracts whose __check_auth implementation does not require signatures.
homeDomainThe anchor’s domain hosting the stellar.toml file. Optional, defaults to server home domain
clientDomainDomain of the client application for mutual authentication
clientDomainAccountKeyPairKeyPair for client domain signing. If it includes a private key, it will be used directly
clientDomainSigningCallbackFunction for remote client domain signing. Accepts SorobanAuthorizationEntryXDR, returns signed entry
signatureExpirationLedgerOptional expiration ledger for signatures. If nil and signers are provided, automatically set to current ledger + 10
Return Value
GetContractJWTTokenResponseEnum with JWT token on success or error details on failure
-
Requests a challenge from the authentication server.
Declaration
Swift
public func getChallenge( forContractAccount clientAccountId: String, homeDomain: String? = nil, clientDomain: String? = nil ) async -> GetContractChallengeResponseEnumParameters
forContractAccountThe contract account ID (starting with C) to authenticate
homeDomainOptional home domain for the request. Defaults to server home domain if not provided
clientDomainOptional client domain for mutual authentication
Return Value
GetContractChallengeResponseEnum with challenge response or error
-
Validates the authorization entries from the challenge response.
Validation steps:
- Each entry has no sub-invocations
- contract_address matches WEB_AUTH_CONTRACT_ID
- function_name is “web_auth_verify”
- Args validation (account, home_domain, web_auth_domain, nonce, etc.)
- Server entry exists and has valid signature
- Client entry exists
Throws
ContractChallengeValidationError on validation failureDeclaration
Swift
public func validateChallenge( authEntries: [SorobanAuthorizationEntryXDR], clientAccountId: String, homeDomain: String? = nil, clientDomainAccountId: String? = nil ) throwsParameters
authEntriesAuthorization entries to validate
clientAccountIdExpected client contract account
homeDomainExpected home domain. Defaults to server home domain if not provided
clientDomainAccountIdOptional expected client domain account
-
signAuthorizationEntries(authEntries:AsynchronousclientAccountId: signers: signatureExpirationLedger: clientDomainKeyPair: clientDomainAccountId: clientDomainSigningCallback: ) Signs the authorization entries for the client account.
Throws
Error if signing failsDeclaration
Swift
public func signAuthorizationEntries( authEntries: [SorobanAuthorizationEntryXDR], clientAccountId: String, signers: [KeyPair], signatureExpirationLedger: UInt32?, clientDomainKeyPair: KeyPair?, clientDomainAccountId: String?, clientDomainSigningCallback: ((SorobanAuthorizationEntryXDR) async throws -> SorobanAuthorizationEntryXDR)? ) async throws -> [SorobanAuthorizationEntryXDR]Parameters
authEntriesAuthorization entries to sign
clientAccountIdClient contract account
signersKeypairs to sign with
signatureExpirationLedgerOptional expiration ledger for signatures
clientDomainKeyPairOptional keypair for client domain signing
clientDomainAccountIdOptional client domain account ID (used with callback)
clientDomainSigningCallbackOptional callback for remote signing (single entry)
Return Value
Signed authorization entries
-
sendSignedChallenge(signedEntries:Asynchronous) Submits signed authorization entries to obtain a JWT token.
Declaration
Swift
public func sendSignedChallenge( signedEntries: [SorobanAuthorizationEntryXDR] ) async -> SubmitContractChallengeResponseEnumParameters
signedEntriesSigned authorization entries
Return Value
SubmitContractChallengeResponseEnum with JWT token or error
-
Decodes authorization entries from base64 XDR.
Throws
Error if decoding failsDeclaration
Swift
public func decodeAuthorizationEntries(base64Xdr: String) throws -> [SorobanAuthorizationEntryXDR]Parameters
base64XdrBase64-encoded XDR array of SorobanAuthorizationEntry
Return Value
Array of authorization entries
View on GitHub
Install in Dash