OAuth клиент для Swift (iOS/macOS): полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Библиотека OAuth клиента для Swift (iOS/macOS)

OAuth (Open Authorization) — это открытый протокол авторизации, который позволяет приложениям получать ограниченный доступ к ресурсам пользователя без передачи его логина и пароля. В экосистеме Apple (iOS, macOS, watchOS, tvOS) реализация OAuth 2.0 является стандартом для интеграции с такими сервисами, как Google, Facebook, GitHub, Twitter и многими другими. Для Swift-разработчиков существует несколько проверенных библиотек, упрощающих процесс аутентификации и управления токенами.

В этой статье мы рассмотрим одну из наиболее популярных и гибких библиотек — OAuthSwift, а также обсудим альтернативу — AppAuth-iOS (рекомендуемую Google). Вы узнаете, как подключить библиотеку, выполнить авторизацию, получить access token, refresh token и безопасно их хранить.

Основные возможности OAuthSwift

  • Поддержка OAuth 1.0 и OAuth 2.0
  • Встроенная работа с WebView (SFSafariViewController, WKWebView)
  • Автоматическое получение и обновление access token
  • Поддержка различных грантов (Authorization Code, Implicit, Client Credentials, Resource Owner Password)
  • Простая интеграция с Alamofire, URLSession и другими сетевыми фреймворками
  • Асинхронные колбэки (completion handlers) и поддержка Combine (через расширения)
  • Безопасное хранение токенов через Keychain

Установка OAuthSwift

Библиотека устанавливается через Swift Package Manager (SPM) или CocoaPods. Пример для SPM:

// В Xcode: File → Add Packages...
// URL: https://github.com/OAuthSwift/OAuthSwift.git
// Версия: от 2.2.0 и выше

Или через Package.swift:

dependencies: [
    .package(url: "https://github.com/OAuthSwift/OAuthSwift.git", from: "2.2.0")
]

Пример интеграции с OAuth 2.0 (Google)

Рассмотрим типовой сценарий — авторизация через Google с получением access token. Предварительно необходимо зарегистрировать приложение в Google Cloud Console и получить client_id и client_secret.

Шаг 1. Настройка URL scheme

В файле Info.plist добавьте схему для обратного вызова:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>com.googleusercontent.apps.YOUR_CLIENT_ID</string>
        </array>
    </dict>
</array>

Шаг 2. Код авторизации

import OAuthSwift

let oauthswift = OAuth2Swift(
    consumerKey:    "YOUR_CLIENT_ID",
    consumerSecret: "YOUR_CLIENT_SECRET",
    authorizeUrl:   "https://accounts.google.com/o/oauth2/auth",
    accessTokenUrl: "https://oauth2.googleapis.com/token",
    responseType:   "code"
)

// Сохраняем ссылку на контроллер для презентации WebView
let handler = SafariURLHandler(viewController: self, oauthSwift: oauthswift)
oauthswift.authorizeURLHandler = handler

let state = generateState(withLength: 20)
oauthswift.authorize(
    withCallbackURL: URL(string: "com.googleusercontent.apps.YOUR_CLIENT_ID:/oauth2callback")!,
    scope: "https://www.googleapis.com/auth/userinfo.email",
    state: state,
    parameters: [:]) { result in
    switch result {
    case .success(let (credential, response, parameters)):
        print("Access Token: \(credential.oauthToken)")
        print("Refresh Token: \(credential.oauthRefreshToken)")
        // Сохраняем токены в Keychain
        KeychainWrapper.standard.set(credential.oauthToken, forKey: "access_token")
        KeychainWrapper.standard.set(credential.oauthRefreshToken, forKey: "refresh_token")
    case .failure(let error):
        print("Ошибка авторизации: \(error.localizedDescription)")
    }
}

Шаг 3. Обновление токена (refresh)

Когда access token истекает, используйте refresh token для получения нового:

oauthswift.renewAccessToken(
    withRefreshToken: "YOUR_REFRESH_TOKEN",
    parameters: [:]) { result in
    switch result {
    case .success(let (credential, response, parameters)):
        print("Новый access token: \(credential.oauthToken)")
        // Обновляем в Keychain
        KeychainWrapper.standard.set(credential.oauthToken, forKey: "access_token")
    case .failure(let error):
        print("Не удалось обновить токен: \(error)")
    }
}

Безопасное хранение токенов

Никогда не храните токены в

Рекомендаций