Skip to main content

Accessing Protected APIs

When your app needs to call a backend API that requires authentication, use ThunderIDClient.getAccessToken() to retrieve a valid access token and attach it as a Bearer token to your requests. The SDK automatically refreshes the token if it has expired.

Using URLSession

The following example calls a protected API endpoint using the standard URLSession:

APIClient.swift
import Foundation
import ThunderIDSwiftUI

func fetchProtectedResource(state: ThunderIDState) async throws -> Data {
let token = try await state.client.getAccessToken()

var request = URLRequest(url: URL(string: "https://localhost:8090/api/resource")!)
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")

let (data, response) = try await URLSession.shared.data(for: request)

guard let httpResponse = response as? HTTPURLResponse,
(200..<300).contains(httpResponse.statusCode) else {
throw URLError(.badServerResponse)
}

return data
}

Call it from a SwiftUI view:

ResourceView.swift
import SwiftUI
import ThunderIDSwiftUI

struct ResourceView: View {
@EnvironmentObject var state: ThunderIDState
@State private var result: String = ""

var body: some View {
Text(result.isEmpty ? "Loading..." : result)
.task {
do {
let data = try await fetchProtectedResource(state: state)
result = String(data: data, encoding: .utf8) ?? ""
} catch {
result = "Error: \(error.localizedDescription)"
}
}
}
}

Token Refresh

getAccessToken() refreshes the access token automatically when it is expired, as long as a valid refresh token is available. You do not need to handle refresh manually.

If the refresh token is also expired, getAccessToken() throws IAMError with code .sessionExpired. Handle this by signing the user out:

do {
let token = try await state.client.getAccessToken()
// use token
} catch let error as IAMError where error.code == .sessionExpired {
_ = try? await state.client.signOut()
await state.refresh()
} catch {
print("Unexpected error: \(error)")
}

Using Alamofire

If your project uses Alamofire, create a request interceptor that injects the access token:

ThunderIDRequestInterceptor.swift
import Alamofire
import ThunderIDSwiftUI

final class ThunderIDRequestInterceptor: RequestInterceptor {
let state: ThunderIDState

init(state: ThunderIDState) {
self.state = state
}

func adapt(
_ urlRequest: URLRequest,
for session: Session,
completion: @escaping (Result<URLRequest, Error>) -> Void
) {
Task {
do {
let token = try await state.client.getAccessToken()
var request = urlRequest
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
completion(.success(request))
} catch {
completion(.failure(error))
}
}
}
}

Create a session with the interceptor and use it for all protected requests:

let interceptor = ThunderIDRequestInterceptor(state: state)
let session = Session(interceptor: interceptor)

session.request("https://localhost:8090/api/resource")
.responseDecodable(of: MyResponse.self) { response in
print(response.value ?? "No data")
}
API Server URL

The ThunderID API server runs on https://localhost:8090 by default in local development. Replace this with your production server URL when deploying.

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© WSO2 LLC. All rights reserved.Privacy PolicyCookie Policy