Skip to main content

iOS

Official

Native Swift SDK with hosted login and secure token storage.

Accessing Protected APIs

~3 min

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.

Accessing Protected APIs

1

Using URLSession

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

APIClient.swift
swift

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
}
2

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:

swift
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)")
}
3

Using Alamofire

If your project uses [Alamofire](https://github.com/Alamofire/Alamofire), create a request interceptor that injects the access token:

ThunderIDRequestInterceptor.swift
swift

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))
            }
        }
    }
}
ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.