Войти с помощью apple - аутентифицировать последующие вызовы, не показывая вход в пользовательском интерфейсе (обновление маркера аутентификации) - PullRequest
2 голосов
/ 17 января 2020

Всякий раз, когда я запускаю свое приложение, я хочу убедиться, что вход в Apple по-прежнему действителен, но я также хочу иметь возможность подтвердить его на моем сервере.
После успешного входа в систему я можно использовать ASAuthorizationAppleIDProvider.getCredentialState, чтобы выяснить, действительны ли мои учетные данные для последующих входов в систему.
Это работает нормально, но нет никакого способа доказать моему серверу, что этот процесс был успешно выполнен, и любой, кто использует мой серверный API, может просто скажите серверу, чтобы он не беспокоился, и у сервера не будет возможности определить, является ли он реальным клиентом или нет.
Сервер также может использовать токен refre sh, чтобы убедиться, что пользователь по-прежнему действителен, выдав новый токен доступа (Apple говорит делать это не чаще одного раза в день, но пока нормально), но это тоже не помогает, поскольку я не хочу, чтобы секрет присутствовал в клиентском приложении, и, кроме того, даже если я получить новый токен доступа со стороны клиента - сервер пока не может использовать его ни для чего, поскольку в настоящее время не существует API, который делает что-либо с токеном доступа.

Однако мне требуется новый токен аутентификации - при вызове ASAuthorizationController.performRequests() с запросом Apple ID - пользовательский интерфейс снова отображается, а не просто вызывает ASAuthorizationControllerDelegate с новым токеном авторизации.
Я также попытался установить операцию запроса на refresh во второй попытке входа в систему:

    let request = appleIDProvider.createRequest()
    request.requestedOperation = .operationRefresh

Тот же результат, пользовательский интерфейс все еще показывает.
Есть ли способ для повторной аутентификации с Apple ID без показ пользовательского интерфейса и получение какого-то токена, который может использоваться сервером для проверки подлинности имени входа?
Пожалуйста, не предлагайте методы вне области видимости, такие как те, которые используют мой собственный механизм входа после Первоначальное подтверждение сервера и использование сервером токена refre sh с этого момента - я могу самостоятельно найти эти решения - я ищу решение для входа в Apple.

1 Ответ

1 голос
/ 28 января 2020

Согласно документации :

После проверки токена идентификации ваше приложение отвечает за управление сеансом пользователя. Вы можете сделать ie время жизни сеанса успешными вызовами getCredentialState (forUserID: завершение :) на устройствах Apple . Это локальный недорогой вызов, не связанный с сетью, и он включается системой Apple ID, которая поддерживает состояние Apple ID на устройстве синхронно c с серверами Apple.

В любое время требуется взаимодействие с пользователем запрашивается новый идентификационный токен. Пользовательские сеансы являются долгоживущими на устройстве, поэтому вызов нового идентификационного токена при каждом запуске или чаще, чем один раз в день, может привести к сбою вашего запроса из-за регулирования .

Если Apple ID пользователя изменяется в системе, вызовы getCredentialState (forUserID: завершение :) указывают, что пользователь изменился. Предположим, что другой пользователь вошел в систему и вышел из системы в настоящее время известным пользователем приложения.

Для приложений, работающих в других системах, используйте периодическую c успешную проверку refre sh токен для определения времени жизни пользовательского сеанса.

Так что это в основном означает, что вы должны проверять userIdentifier при получении результата от getCredentialState и убедиться, что это то же значение, что и у текущего пользователя. И вы не можете избежать взаимодействия с пользователем, о котором вы упоминаете в вопросе, если вы хотите пройти повторную аутентификацию в приложении.

Прежде всего, вы должны взять userIdentifier и код авторизации из приложения, войдя в систему. и отправьте его на ваш сервер. Также создайте длинный идентификатор сеанса и отправьте его на свой сервер тоже:

if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {

        let userIdentifier = appleIDCredential.user
        print("userIdentifier: \(userIdentifier)")

        let authorizationCode = String(data: appleIDCredential.authorizationCode!, encoding: .utf8)!
        print("authorizationCode: \(authorizationCode)")  

        let sessionID = veryLongToken

        //send authorizationCode, userIdentifier and sessionId to server
    }

На вашем сервере вы получаете identityToken при вызове: appleid.apple.com/token/auth

с:

#create token
import jwt  # pip install pyjwt
claims = {
    'iss': teamID,
    'iat': timeNow,
    'exp': time3Months,
    'aud': 'https://appleid.apple.com',
    'sub': app_id,
}
client_secret = jwt.encode(claims, private_key_from_developer_portal, algorithm='ES256', headers={'kid': kid})


data = {
    'client_id': app_id,
    'client_secret': client_secret,
    'grant_type': grant_type,
    'redirect_uri': redirect_uri,
    'code': authorizationCode,
}

headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
}

response = requests.request(
    method='POST',
    url='https://appleid.apple.com/auth/token',
    data=data,
    headers=headers,
)
#response will include refresh_token, access_token and id_token

Теперь вы можете получить электронную почту пользователя и userIdentifier из id_token:

result = jwt.decode(id_token, verify=False)
print("jwtResult: " + result)

userIdentifier = result["sub"]
email = result["email"]

Теперь из apple вы знаете, что это за пользователь. В соответствии с проверкой документации токена вы сначала используете authorization_code в grant_type для получения refresh_token и после этого используйте refresh_token в качестве grant_type

Это единственный способ проверить, что пользователь все еще аутентифицирован на сервере.

Поэтому сохраните sessionId вместе с некоторой информацией о входе Apple (refre sh token ...) на ваш сервер.

Вы можете заставить приложение отправлять sessionId на сервер, когда приложению требуются данные с сервера, и перед передачей некоторой информации приложению выполните проверку токена refre sh на сервере. Если аутентификация недействительна, то приложение должно удалить sessionId и выйти из системы.

Это единственный способ проверки на сервере, если аутентификация действительна.

Читая документацию, это, кажется, рекомендуемый способ, и то, что вы пытаетесь сделать, вызовет проблемы, и Apple не хочет, чтобы вы постоянно аутентифицировали пользователя в приложении.

You следует также проверить этот пример проекта от Apple для входа с яблоком.

пример проекта сока

...