Авторизация и аутентификация в Swift (iOS/macOS)
Авторизация и аутентификация — ключевые компоненты любого современного приложения. В экосистеме Apple (iOS/macOS) разработчики имеют доступ к мощным фреймворкам и библиотекам, которые упрощают эти процессы. В этой статье мы рассмотрим основные подходы, популярные библиотеки и приведём практические примеры на Swift.
Основные концепции
Прежде чем перейти к коду, важно различать два термина:
- Аутентификация — проверка личности пользователя (например, логин + пароль, Face ID, Touch ID).
- Авторизация — определение прав доступа после аутентификации (например, может ли пользователь просматривать определённые данные).
Встроенные возможности Apple
1. LocalAuthentication (Face ID / Touch ID)
Фреймворк LocalAuthentication позволяет использовать биометрические данные устройства для аутентификации.
import LocalAuthentication
func authenticateWithBiometrics() {
let context = LAContext()
var error: NSError?
// Проверяем, доступна ли биометрия
guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
print("Биометрия недоступна: \(error?.localizedDescription ?? "ошибка")")
return
}
// Запрашиваем аутентификацию
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Войдите для доступа к приложению") { success, authError in
DispatchQueue.main.async {
if success {
print("Аутентификация успешна")
} else {
print("Ошибка: \(authError?.localizedDescription ?? "неизвестная ошибка")")
}
}
}
}
2. Keychain Services
Keychain — безопасное хранилище для паролей и токенов. Используйте его для хранения учётных данных после аутентификации.
import Security
func saveToKeychain(service: String, account: String, password: String) {
guard let passwordData = password.data(using: .utf8) else { return }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecValueData as String: passwordData
]
// Удаляем старые данные, если есть
SecItemDelete(query as CFDictionary)
// Добавляем новые
let status = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
print("Данные сохранены в Keychain")
} else {
print("Ошибка сохранения: \(status)")
}
}
func readFromKeychain(service: String, account: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess, let data = item as? Data else {
return nil
}
return String(data: data, encoding: .utf8)
}
Популярные библиотеки для авторизации
1. Firebase Authentication
Firebase предоставляет готовое решение для аутентификации через email/пароль, Google, Apple, Facebook и другие провайдеры.
import FirebaseAuth
func signInWithEmail(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { result, error in
if let error = error {
print("Ошибка входа: \(error.localizedDescription)")
return
}
print("Пользователь вошёл: \(result?.user.uid ?? "нет")")
}
}
func signUpWithEmail(email: String, password: String) {
Auth.auth().createUser(withEmail: email, password: password) { result, error in
if let error = error {
print("Ошибка регистрации: \(error.localizedDescription)")
return
}
print("Пользователь зарегистрирован: \(result?.user.uid ?? "нет")")
}
}
2. Auth0
Auth0 — универсальная платформа для аутентификации с поддержкой OAuth 2.0, OpenID Connect и множества социальных провайдеров.
import Auth0
func loginWithAuth0() {
Auth0
.webAuth()
.scope("openid profile email")
.audience("https://your-api.com")
.start { result in
switch result {
case .success(let credentials):
print("Токен: \(credentials.accessToken)")
print("ID токен: \(credentials.idToken)")
case .failure(let error):
print("Ошибка: \(error.localizedDescription)")
}
}
}
Интеграция с SwiftUI
Современные приложения часто используют SwiftUI. Вот пример простого экрана входа с использованием @State и @