Официальный iOS SDK для интеграции аутентификации Flida в ваши iOS приложения.
- В Xcode откройте File > Add Package Dependencies...
- Введите URL репозитория:
https://github.com/flida-dev/ios-sdk - Выберите нужную версию.
Добавьте ключ FlidaAuthHost в ваш Info.plist:
<key>FlidaAuthHost</key>
<string>YOUR_CLIENT_ID.api.flida.dev</string>Формат: {clientId}.api.{domain}
Примеры:
019b650a-156e-77f3-ad1d-df2e2d8c2a5c.api.flida.dev019b650a-156e-77f3-ad1d-df2e2d8c2a5c.api.flida.ru
SDK автоматически извлекает из FlidaAuthHost:
- Client ID — первая часть строки
- API Endpoint —
https://api.{domain} - Auth Endpoint —
https://{domain} - Redirect URI —
flida{clientId}://auth
Добавьте URL scheme для обработки OAuth callback в Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>flida{YOUR_CLIENT_ID}</string>
</array>
</dict>
</array>SDK инициализируется автоматически из Info.plist при первом обращении к FlidaIDSDK.shared. Никаких дополнительных действий не требуется.
Для запуска флоу авторизации вызовите signIn. Необходимо передать ASWebAuthenticationPresentationContextProviding (обычно ваш view controller).
import AuthenticationServices
import FlidaIDSDK
class ViewController: UIViewController, ASWebAuthenticationPresentationContextProviding {
func signIn() {
FlidaIDSDK.shared.signIn(
presenting: self,
scopes: ["openid", "name", "e-mail-address", "phone-number"]
) { result in
switch result {
case .success(let tokenResponse):
print("Access Token: \(tokenResponse.token.accessToken)")
case .failure(let error):
print("Ошибка: \(error.localizedDescription)")
}
}
}
// ASWebAuthenticationPresentationContextProviding
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
return self.view.window!
}
}После авторизации можно получить данные пользователя:
FlidaIDSDK.shared.getUserInfo(accessToken: accessToken) { result in
switch result {
case .success(let user):
print("Имя: \(user.name)")
print("ID: \(user.id)")
case .failure(let error):
print("Ошибка: \(error.localizedDescription)")
}
}Для обновления access token:
FlidaIDSDK.shared.refreshTokens(refreshToken: refreshToken) { result in
switch result {
case .success(let tokenResponse):
print("Новый Access Token: \(tokenResponse.token.accessToken)")
case .failure(let error):
print("Ошибка: \(error.localizedDescription)")
}
}FlidaIDSDK.shared.logout()SDK предоставляет стрим событий на основе Combine для реактивного программирования. Подписывайтесь на события, чтобы получать уведомления об изменениях состояния аутентификации.
| Событие | Описание |
|---|---|
signedIn(user:accessToken:) |
Пользователь успешно авторизовался |
signInFailed(error:) |
Ошибка авторизации |
tokensRefreshed(accessToken:) |
Токены успешно обновлены |
tokenRefreshFailed(error:) |
Ошибка обновления токенов |
loggedOut(reason:) |
Пользователь вышел из системы |
userInfoFetched(user:) |
Информация о пользователе получена |
userInfoFetchFailed(error:) |
Ошибка получения информации о пользователе |
| Причина | Описание |
|---|---|
.userInitiated |
Пользователь вызвал logout() явно |
.sessionExpired |
Refresh token истёк (404) |
.unauthorized |
Сервер вернул 401 при обновлении токена |
import Combine
import FlidaIDSDK
class AuthManager {
private var cancellables = Set<AnyCancellable>()
init() {
FlidaIDSDK.shared.events.events
.sink { [weak self] event in
self?.handleEvent(event)
}
.store(in: &cancellables)
}
private func handleEvent(_ event: FlidaEvent) {
switch event {
case .signedIn(let user, let accessToken):
print("Пользователь вошёл: \(user?.name ?? "Неизвестно")")
case .signInFailed(let error):
print("Ошибка входа: \(error.localizedDescription)")
case .tokensRefreshed(let accessToken):
print("Токены обновлены")
case .tokenRefreshFailed(let error):
print("Ошибка обновления токенов: \(error.localizedDescription)")
case .loggedOut(let reason):
switch reason {
case .userInitiated:
print("Пользователь вышел")
case .sessionExpired:
print("Сессия истекла")
case .unauthorized:
// 401 на refresh — перенаправить на логин
print("Сессия недействительна, войдите снова")
}
case .userInfoFetched(let user):
print("Информация о пользователе: \(user.name)")
case .userInfoFetchFailed(let error):
print("Ошибка получения информации: \(error.localizedDescription)")
}
}
}import SwiftUI
import Combine
import FlidaIDSDK
struct ContentView: View {
@State private var cancellables = Set<AnyCancellable>()
@State private var isLoggedIn = false
var body: some View {
Group {
if isLoggedIn {
MainView()
} else {
LoginView()
}
}
.onAppear {
FlidaIDSDK.shared.events.events
.sink { event in
switch event {
case .signedIn:
isLoggedIn = true
case .loggedOut:
isLoggedIn = false
default:
break
}
}
.store(in: &cancellables)
}
}
}Все методы SDK возвращают типизированные ошибки FlidaError:
FlidaIDSDK.shared.signIn(presenting: self, scopes: ["openid"]) { result in
switch result {
case .success(let response):
// Успех
case .failure(let error):
switch error {
case .userCancelled:
// Пользователь отменил — не показываем ошибку
break
case .notInitialized:
print("Настройте FlidaAuthHost в Info.plist")
case .unauthorized:
print("Токен истёк, войдите снова")
case .networkError(let underlyingError):
print("Ошибка сети: \(underlyingError)")
default:
print("Ошибка: \(error.localizedDescription)")
}
}
}| Ошибка | Описание |
|---|---|
notInitialized |
SDK не настроен (отсутствует FlidaAuthHost) |
userCancelled |
Пользователь отменил авторизацию |
invalidCallbackURL |
Неверный callback URL |
stateMismatch |
Несоответствие OAuth state (возможная CSRF атака) |
noAuthorizationCode |
Нет кода авторизации в callback |
pkceGenerationFailed |
Ошибка генерации PKCE challenge |
oauthError(String) |
OAuth ошибка от сервера |
unauthorized |
401 — Access token истёк |
forbidden(String?) |
403 — Доступ запрещён |
refreshTokenExpired |
Refresh token истёк |
tokenExchangeFailed(String?) |
Ошибка обмена токена |
networkError(Error) |
Ошибка сетевого запроса |
serverError(statusCode:message:) |
Сервер вернул ошибку |
decodingError(Error) |
Ошибка декодирования ответа |
noData |
Нет данных от сервера |
SDK включает систему логирования с настраиваемыми уровнями.
| Уровень | Описание |
|---|---|
.none |
Логирование отключено (по умолчанию) |
.error |
Только ошибки |
.warning |
Ошибки и предупреждения |
.info |
Ошибки, предупреждения и информационные сообщения |
.debug |
Всё выше + информация о HTTP запросах/ответах |
.verbose |
Все сообщения, включая тела HTTP запросов |
// Включить debug логирование
FlidaIDSDK.shared.setLogLevel(.debug)
// Или для максимальной детализации
FlidaIDSDK.shared.setLogLevel(.verbose)
⚠️ Важно: На уровне.verboseчувствительные данные автоматически маскируются, но рекомендуется использовать verbose логирование только при разработке.