Pull to refresh

Внедряем Sign in with Apple в свое iOS приложение

Reading time2 min
Views11K
На WWDC 2019 Apple в очередной раз нарушила покой iOS разработчиков — представила новую систему авторизации пользователей Sign in with Apple. Теперь все iOS приложения, которые используют сторонние системы авторизации (Facebook, Twitter, etc.), должны в обязательном порядке реализовать Sign in with Apple, иначе выгонят из AppStore. Мы решили не испытывать судьбу и побежали внедрять эту фичу. Как именно мы это сделали — узнаете под катом.

Пишем сервис авторизации через Apple


В своей работе мы используем архитектуру VIPER+SOA, поэтому авторизацию через Apple мы сделали как отдельный сервис. Сначала мы оборачиваем данные в enum, чтобы удобно расширять типы авторизации (фейсбук, вк, гугл и т.д.):

enum AuthToken {
    case apple(code: String, name: String)
}

Результат наружу будем передавать с помощью Observable из RxSwift:

protocol AuthProviderProtocol {
    var authResult: Observable<AuthToken> { get }

    func login()
    func logout()
}

Реализация протокола:

import AuthenticationServices
import Foundation
import RxSwift

@available(iOS 13.0, *)
class AppleAuthService: AuthProviderProtocol {

    private let authResultSubject = PublishSubject<AuthToken>()
    var authResult: Observable<AuthToken> {
        return authResultSubject.asObservable()
    }

    func login() {
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        let request = appleIDProvider.createRequest()
        request.requestedScopes = [.fullName, .email]

        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.performRequests()
    }

}

@available(iOS 13.0, *)
extension AppleAuthService: ASAuthorizationControllerDelegate {

    func authorizationController(
        controller: ASAuthorizationController,
        didCompleteWithAuthorization authorization: ASAuthorization
    ) {
        guard
            let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
            let tokenData = credential.authorizationCode,
            let token = String(data: tokenData, encoding: .utf8)
        else { return }

        let firstName = credential.fullName?.givenName
        let lastName = credential.fullName?.familyName

        authResultSubject.onNext(.apple(code: token, name: firstName + lastName))
    }

}

Нюансы, о которых нужно знать


  1. У Sign in with Apple нету функции logout в классическом понимании этого слова. Библиотека не хранит никакие данные, в отличие от других библиотек входа, поэтому нет необходимости стирать данные, полученные при логине.
  2. Sign in with Apple получает имя и фамилию пользователя только один раз при самом первом логине. У сервера нет доступа к этим данным. При последующих попытках входа вам будут приходить только authorizationCode из ASAuthorizationAppleIDCredential. Поэтому мы на клиентской стороне храним имя и фамилию пользователя до тех пор, пока регистрация на сервере не завершится успешно.
  3. Sign in with Apple позволяет пользователю подменить свой e-mail. На подмененный e-mail можно написать только с тех доменов, которые вы укажете в настройках на developer.apple.com

  4. В этой статье описано то, как мы реализовали back-end часть.

Статья получилось небольшой, но надеемся что она была полезной для вас.

Благодарим за внимание!
Tags:
Hubs:
Total votes 12: ↑9 and ↓3+6
Comments15

Articles

Information

Website
www.sports.ru
Registered
Founded
Employees
201–500 employees
Location
Россия