WebAuthenticator
public final class WebAuthenticator : Sendable
Implements SEP-0010 - Stellar Web Authentication.
This class provides functionality for authenticating users through the Stellar Web Authentication protocol, which allows clients to prove they possess the signing key for a Stellar account. 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-0010 defines a standard protocol for proving account ownership without transmitting secret keys. The server generates a challenge transaction that the client signs with their account’s signing key, proving ownership without revealing the secret key itself.
Typical Workflow
- Initialize from Domain: Create a WebAuthenticator 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 WebAuthenticator from anchor domain
let result = await WebAuthenticator.from(
domain: "https://testanchor.stellar.org",
network: .testnet
)
switch result {
case .success(let webAuth):
// Step 2: Get JWT token for user account
let userKeyPair = try KeyPair(secretSeed: "S...")
let jwtResult = await webAuth.jwtToken(
forUserAccount: userKeyPair.accountId,
signers: [userKeyPair],
homeDomain: "testanchor.stellar.org"
)
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 Accounts:
// Provide multiple signers for accounts requiring multiple signatures
let signers = [keyPair1, keyPair2, keyPair3]
let result = await webAuth.jwtToken(
forUserAccount: accountId,
signers: signers
)
Muxed Accounts:
// For muxed accounts starting with M, provide memo
let result = await webAuth.jwtToken(
forUserAccount: "M...",
memo: 12345,
signers: [keyPair]
)
Client Domain Signing:
// For client domain verification (mutual authentication)
let clientDomainKeyPair = try KeyPair(accountId: "G...")
let result = await webAuth.jwtToken(
forUserAccount: userAccountId,
signers: [userKeyPair],
clientDomain: "wallet.example.com",
clientDomainAccountKeyPair: clientDomainKeyPair,
clientDomainSigningFunction: { txXdr in
// Sign on server and return signed transaction
return try await signOnServer(txXdr)
}
)
Authentication Flow Details
The SEP-0010 authentication process involves:
- Client requests a challenge transaction from the server
- Server returns a transaction with specific operations and time bounds
- Client validates the challenge transaction
- Client signs the transaction with their account key(s)
- Client submits the signed transaction to the server
- Server validates signatures and returns a JWT token
The JWT token typically expires after 24 hours and must be refreshed.
Error Handling
let result = await webAuth.jwtToken(forUserAccount: accountId, signers: signers)
switch result {
case .success(let token):
// Use token
case .failure(let error):
switch error {
case .requestError(let horizonError):
// Network or server error
case .validationErrorError(let validationError):
// Challenge validation failed
case .signingError:
// Transaction signing failed
case .parsingError(let parseError):
// Response parsing failed
}
}
Security Considerations
- Never transmit secret keys to the server
- Validate the challenge transaction before signing
- Check time bounds to prevent replay attacks
- Store JWT tokens securely
- Refresh tokens before expiration
See also:
- SEP-0010 Specification
- [StellarToml] for discovering authentication endpoints
-
The URL of the SEP-10 web authentication endpoint for obtaining JWT tokens.
Declaration
Swift
public let authEndpoint: String -
The server’s public signing key used to validate challenge transaction signatures.
Declaration
Swift
public let serverSigningKey: String -
The Stellar network used for authentication and transaction validation.
Declaration
Swift
public let network: Network -
The server’s home domain hosting the stellar.toml configuration file.
Declaration
Swift
public let serverHomeDomain: String -
Grace period in seconds for validating challenge transaction time bounds (default: 5 minutes).
Declaration
Swift
public let gracePeriod: UInt64 -
from(domain:Asynchronousnetwork: secure: ) Creates a WebAuthenticator instance by fetching configuration from a domain’s stellar.toml file.
This is the recommended way to initialize a WebAuthenticator. It automatically retrieves the authentication endpoint and server signing key from the anchor’s stellar.toml configuration file.
Example:
let result = await WebAuthenticator.from( domain: "testanchor.stellar.org", network: .testnet )Declaration
Swift
public static func from(domain: String, network: Network, secure: Bool = true) async -> WebAuthenticatorForDomainEnumParameters
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
WebAuthenticatorForDomainEnum indicating success with WebAuthenticator instance or failure with error
-
Initializes a WebAuthenticator instance with explicit configuration parameters.
Declaration
Swift
public init(authEndpoint: String, network: Network, serverSigningKey: String, serverHomeDomain: String)Parameters
authEndpointEndpoint to be used for the authentication procedure. Usually taken from stellar.toml.
networkThe network used.
serverSigningKeyThe server public key, taken from stellar.toml.
serverHomeDomainThe server home domain of the server where the stellar.toml was loaded from
-
jwtToken(forUserAccount:Asynchronousmemo: signers: homeDomain: clientDomain: clientDomainAccountKeyPair: clientDomainSigningFunction: ) Obtains a JWT token through the SEP-0010 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 userKeyPair = try KeyPair(secretSeed: "S...") let result = await webAuth.jwtToken( forUserAccount: userKeyPair.accountId, signers: [userKeyPair], homeDomain: "testanchor.stellar.org" )Declaration
Swift
public func jwtToken(forUserAccount accountId: String, memo: UInt64? = nil, signers: [KeyPair], homeDomain: String? = nil, clientDomain: String? = nil, clientDomainAccountKeyPair: KeyPair? = nil, clientDomainSigningFunction: ((String) async throws -> String)? = nil) async -> GetJWTTokenResponseEnumParameters
forUserAccountThe Stellar account ID (starting with G or M) to authenticate
memoID memo for the account. Required if the account is muxed (starts with M) and accountId starts with G
signersArray of KeyPair objects with secret keys for signing the challenge. For multi-sig accounts, include all required signers
homeDomainThe anchor’s domain hosting the stellar.toml file. Optional but recommended
clientDomainDomain of the client application for mutual authentication. Used to prove the client’s identity to the server
clientDomainAccountKeyPairKeyPair for client domain signing. If it includes a private key, it will be used directly. If only public key, use clientDomainSigningFunction
clientDomainSigningFunctionFunction for remote client domain signing. Accepts base64 XDR transaction, returns signed transaction. Use when client domain signing occurs on a server
Return Value
GetJWTTokenResponseEnum with JWT token on success or error details on failure
-
Requests a SEP-10 challenge transaction from the authentication server.
Declaration
Swift
public func getChallenge(forAccount accountId: String, memo: UInt64? = nil, homeDomain: String? = nil, clientDomain: String? = nil) async -> ChallengeResponseEnumParameters
forAccountThe Stellar account ID to authenticate
memoOptional ID memo. Required for muxed accounts starting with G, prohibited for accounts starting with M
homeDomainOptional anchor domain for verification
clientDomainOptional client domain for mutual authentication
Return Value
ChallengeResponseEnum with base64-encoded challenge transaction or error
-
isValidChallenge(transactionEnvelopeXDR:userAccountId: memo: serverSigningKey: clientDomainAccount: timeBoundsGracePeriod: ) Validates a SEP-10 challenge transaction according to protocol specifications.
Declaration
Swift
public func isValidChallenge(transactionEnvelopeXDR: TransactionEnvelopeXDR, userAccountId: String, memo: UInt64? = nil, serverSigningKey: String, clientDomainAccount: String? = nil, timeBoundsGracePeriod: UInt64? = nil) -> ChallengeValidationResponseEnumParameters
transactionEnvelopeXDRThe challenge transaction envelope to validate
userAccountIdThe expected user account ID
memoExpected memo value for non-muxed accounts
serverSigningKeyThe server’s public signing key
clientDomainAccountExpected client domain account for mutual authentication
timeBoundsGracePeriodGrace period in seconds for time bounds validation
Return Value
ChallengeValidationResponseEnum indicating success or specific validation error
-
Signs a challenge transaction with the provided keypairs.
Declaration
Swift
public func signTransaction(transactionEnvelopeXDR: TransactionEnvelopeXDR, keyPairs: [KeyPair]) -> String?Parameters
transactionEnvelopeXDRThe transaction envelope to sign
keyPairsArray of keypairs to sign the transaction with
Return Value
Base64-encoded signed transaction XDR, or nil if signing fails
-
sendCompletedChallenge(base64EnvelopeXDR:Asynchronous) Submits a signed challenge transaction to the authentication server to obtain a JWT token.
Declaration
Swift
public func sendCompletedChallenge(base64EnvelopeXDR: String) async -> SendChallengeResponseEnumParameters
base64EnvelopeXDRBase64-encoded signed transaction envelope
Return Value
SendChallengeResponseEnum with JWT token on success or error details on failure
View on GitHub
Install in Dash