Overview
The Bolt iOS SDK provides a built-in SSO flow that lets users log in with their Bolt account using OAuth 2.0, and optionally PKCE. After login, you receive an authorization code and state that your backend exchanges for an access token.
NOTE
If you don’t have a backend application and need to exchange the authorization code directly from your mobile app, enable PKCE mode and send the authorization code, state, and code verifier to the Bolt token exchange endpoint.
The SDK provides three approaches for starting the login flow, matching the checkout pattern:
| Approach | Best For |
|---|---|
| Completion handler | Simplest — works from anywhere, including SwiftUI. |
| Delegate pattern | Callback-based, mirrors the Android SDK. |
| View controller | Full control over presentation. |
Completion Handler
BoltCheckout.shared.startLogin { result in
switch result {
case .completed(let authorizationCode, let codeVerifier, let state):
// Send authCode and state to YOUR backend for token exchange
myBackendApi.exchangeBoltToken(authorizationCode, state)
case .canceled:
print("User canceled login")
case .failed(let error):
print("Login failed: \(error.localizedDescription)")
}
}
Delegate Pattern
Implement BoltLoginDelegate for callback-based results:
class LoginManager: BoltLoginDelegate {
func startLogin() {
BoltCheckout.shared.startLogin(delegate: self)
}
// --- BoltLoginDelegate callbacks ---
func onLoginSuccess(authCode: String, codeVerifier: String, state: String) {
// Send authCode and state to YOUR backend for token exchange.
myBackendApi.exchangeBoltToken(authCode, state)
}
func onLoginError(errorReason: String) {
// Login failed (e.g. network error, user denied permissions)
}
func onLoginCancel() {
// User dismissed the login screen without completing
}
}
View Controller (Explicit Presentation)
let loginVC = BoltLoginViewController(delegate: self)
present(loginVC, animated: true)
PKCE Mode
By default, the SDK does not include a PKCE code challenge in the authorization request. If your integration exchanges the authorization code directly from the client, enable PKCE:
let loginConfig = BoltLoginConfig(usePkce: true)
// Completion handler
BoltCheckout.shared.startLogin(loginConfig: loginConfig) { result in
switch result {
case .completed(let authorizationCode, let codeVerifier, let state):
// codeVerifier is non-empty when usePkce is true
// Send authorizationCode, codeVerifier, and state to token exchange endpoint
...
case .canceled: break
case .failed(let error): break
}
}
// Or delegate
BoltCheckout.shared.startLogin(loginConfig: loginConfig, delegate: self)
// Or view controller
let loginVC = BoltLoginViewController(delegate: self, loginConfig: loginConfig)
present(loginVC, animated: true)
When usePkce is false (default), no code_challenge is sent and codeVerifier in the callback will be an empty string.
How It Works
startLogin()opens a WebView with the Bolt-hosted login page. Your app does not pass an email — the user enters it directly on the page.- (PKCE flow only) The SDK generates a PKCE code verifier and code challenge automatically.
- The user enters their Bolt account email. Bolt sends a one-time passcode (OTP) via email or SMS — the user picks their preferred delivery method and enters the code.
- On success, the hosted page redirects with an authorization code.
- The SDK intercepts this redirect inside the WebView — no URL scheme configuration in your app is required.
onLoginSuccess(authCode:codeVerifier:state:)is called.
Backend Token Exchange
When onLoginSuccess fires, send authCode to your backend immediately. Your backend exchanges it for an access token:
| Environment | Token Endpoint |
|---|---|
| Sandbox | https://api-sandbox.bolt.com/v1/oauth/token |
| Production | https://api.bolt.com/v1/oauth/token |
POST https://api.bolt.com/v1/oauth/token
Content-Type: application/x-www-form-urlencoded
client_id=<your-publishable-key>
&code=<authCode from onLoginSuccess>
&grant_type=authorization_code
&scope=openid bolt.account.manage
&state=<state from onLoginSuccess>
WARNING
Do not write authCode to persistent storage (UserDefaults, Keychain, or disk). Forward it to your backend directly from the completion handler and let it go out of scope.
Logout
To log the user out of their Bolt session:
BoltCheckout.shared.logOut()
SFCC Integration
Some merchants use Salesforce Commerce Cloud (SFCC) as their e-commerce platform and have configured Bolt as an OAuth identity provider within SFCC. In this setup, the token exchange does not go directly to Bolt’s /v1/oauth/token endpoint. Instead, the Bolt authorization code and state are forwarded to SFCC, which handles the token exchange server-to-server on your behalf.
NOTE
In the SFCC flow, you should not use PKCE as the token exchange is made from your backend.
Key Differences from Standard SSO
| Standard Bolt SSO | SFCC Integration | |
|---|---|---|
| Token exchange endpoint | POST /v1/oauth/token (Bolt) |
Login-OAuthMobileBolt → Login-ExchangeSFCCToken (SFCC) |
codeVerifier usage |
Required only for PKCE flow | Not used — discard after onLoginSuccess |
| Who calls Bolt’s token API | Your backend | SFCC (server-to-server) |
| Resulting token | Bolt access token | SFCC JWT bearer token |
SFCC Endpoint Reference
| Step | Method | URL |
|---|---|---|
| Authorize | GET |
https://api-sandbox.bolt.com/v1/oauth/internal/authorize |
| SFCC code exchange | GET |
https://<sfcc-host>/.../Login-OAuthMobileBolt |
| SFCC token exchange | POST |
https://<sfcc-host>/.../Login-ExchangeSFCCToken |