iOS и Android
Нативные приложения выполняют вход через Lobby своей среды в системном браузере, а не во встроенном веб-представлении (web view): люди пользуются своими ключами входа, сохраненными паролями и сеансом Usher, а приложение никогда не видит пароль. Остальную часть OpenID Connect за вас выполняют SDK, и они же хранят токены на устройстве.
Зарегистрируйте приложение
В Usher Console откройте среду, затем Приложения → Новое приложение → Мобильное или настольное. Укажите для него адрес перенаправления с частной схемой, составленной из вашего домена, например com.example.notes:/oauth/callback. Приложение получит ID клиента и не получит секрета: приложение на телефоне не может хранить его в тайне, поэтому вместо секрета используется PKCE. Console показывает настройку для обеих платформ.
iOS и macOS
import UsherKit
let usher = UsherClient(configuration: .init(
issuer: URL(string: "https://login.example.com")!,
clientID: "…",
redirectURI: URL(string: "com.example.notes:/oauth/callback")!))
let session = try await usher.signIn()
var request = URLRequest(url: URL(string: "https://api.example.com/notes")!)
try await usher.authorize(&request)Токены хранятся в Связке ключей, только на этом устройстве.
Android
// build.gradle.kts: manifestPlaceholders["usherRedirectScheme"] = "com.example.notes"
val usher = Usher.client(context, UsherConfiguration(
issuer = "https://login.example.com",
clientId = "…",
redirectUri = "com.example.notes:/oauth/callback"))
val session = usher.signIn(Usher.customTabs(activity))Вход открывается в Custom Tab. Сеанс зашифрован ключом из Android Keystore.
Что проверяют SDK
- PKCE, state и nonce при каждом входе, а также издателя, указанного в ответе (RFC 9207).
- Подпись ID-токена по ключам вашей среды, а также его издателя, аудиторию и срок действия.
- Токены обновления меняются: каждый используется один раз. При выходе токен отзывается в Usher.
- DPoP, если вы его включите: токены привязаны к ключу на устройстве и бесполезны, если их скопировать куда-то еще.
Чтобы вызывать свой API с токеном доступа, укажите API и запросите доступ к нему через resources: см. Ваши API.