ユーザーの認証 - Swift SDK
項目一覧
ログイン
匿名ユーザー
App Services UI で匿名認証を有効にした場合、ユーザーは識別情報を提供せずにアプリにすぐにログインできます。 次のコードは、これを行う方法を示しています。
let anonymousCredentials = Credentials.anonymous app.login(credentials: anonymousCredentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
メール/パスワード ユーザー
メール/パスワード認証を有効にしている場合は、次のコードを使用してログインできます。
let email = "skroob@example.com" let password = "12345" app.login(credentials: Credentials.emailPassword(email: email, password: password)) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
API キー ユーザー
API キー認証を有効にしている場合は、次のコードを使用してログインできます。
let credentials = Credentials.userAPIKey("<api-key>") app.login(credentials: credentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
カスタム関数ユーザー
カスタム関数認証プロバイダを有効にした場合は、次のコードを使用してログインできます。
let params: Document = ["username": "bob"] app.login(credentials: Credentials.function(payload: params)) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
カスタムJSON web tokenユーザー
カスタムJSON web token認証プロバイダを有効にした場合は、次のコードを使用してログインできます。
let credentials = Credentials.jwt(token: "<jwt>") app.login(credentials: credentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Facebook ユーザー
Facebook認証プロバイダーは、既存の Facebook アカウントを使用して Facebook アプリを通じてユーザーを認証することを可能にします。
重要
Facebook 認証プロバイダーを有効にする
ユーザーを既存の Facebook アカウントでログインするには、アプリケーションのFacebook 認証プロバイダを設定して有効にする必要があります。
重要
Facebook プロファイル画像 URL を保存しないでください
Facebook のプロファイル画像 URL には、画像の使用許可を付与するためのユーザーのアクセス トークンが含まれます。 セキュリティを確保するために、ユーザーのアクセストークンを含む URL を保存しないでください。 代わりに、画像を取得する必要がある場合は、ユーザーのメタデータ フィールドから URL に直接アクセスします。
iOSの公式Facebookログイン クイック スタート アプリケーションの認証フローを設定します 。ログイン完了ハンドラーで、ログインユーザーの アクセストークン文字列 を使用して App Services Facebookの認証情報を作成します をクリックし、ユーザーを App Servicesアプリにログさせます。
// This example demonstrates login logic for FBSDK version 13.x. If you're using // a different version of FBSDK, you'll need to adapt this example for your version. let loginManager = LoginManager() loginManager.logIn(permissions: [ .email ]) { loginResult in switch loginResult { case .success(let grantedPermissions, let declinedPermissions, let accessToken): let credentials = Credentials.facebook(accessToken: accessToken!.tokenString) app.login(credentials: credentials) { result in DispatchQueue.main.async { switch result { case .failure(let error): print("Failed to log in to MongoDB Realm: \(error)") case .success(let user): print("Successfully logged in to MongoDB Realm using Facebook OAuth.") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } } } case .failed(let error): print("Facebook login failed: \(error)") case .cancelled: print("The user cancelled the login flow.") } }
Google ユーザー
重要
ユーザーを既存の Google アカウントでログインするには、アプリケーションのGoogle 認証プロバイダを設定して有効にする必要があります。
公式 の「iOS 統合ガイド」に 従う アプリケーションの認証フローを設定します。ログイン完了ハンドラーで、App Services Google の認証情報を作成し、ユーザーをApp Services Appにログインします。
認証情報に渡す値は、プロバイダーに対してOpenID Connect を有効にしているかどうかによって異なります。
OpenID Connect が有効になっている場合
id_token
は、Google OAuth 応答に含まれる を渡します に 認証情報.googleId(token:)OpenID Connect が有効になっていない場合は、ユーザーの サーバー認証コード を渡します に 認証情報.google(serverAuthCode:)
func sign(_ signIn: GIDSignIn!, didSignInFor googleUser: GIDGoogleUser!, withError error: Error!) { if let error = error { print("\(error.localizedDescription)") return } // Get the ID token for the authenticated user so you can pass it to Realm let idToken = googleUser.authentication.idToken! let credentials = Credentials.googleId(token: idToken) app.login(credentials: credentials) { result in DispatchQueue.main.async { switch result { case .failure(let error): print("Failed to log in to MongoDB Realm: \(error)") case .success(let user): print("Successfully logged in to MongoDB Realm using Google OAuth.") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } } } }
func sign(_ signIn: GIDSignIn!, didSignInFor googleUser: GIDGoogleUser!, withError error: Error!) { if let error = error { print("\(error.localizedDescription)") return } // Upon first successful sign-in, forward serverAuthCode credentials to MongoDB Realm. // Upon subsequent sign-ins, this returns nil. let credentials = Credentials.google(serverAuthCode: googleUser.serverAuthCode!) app.login(credentials: credentials) { result in DispatchQueue.main.async { switch result { case .failure(let error): print("Failed to log in to MongoDB Realm: \(error)") case .success(let user): print("Successfully logged in to MongoDB Realm using Google OAuth.") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } } } }
Apple ユーザー
Sign in with Apple 認証 を有効にしている場合は、次のコードを使用してログインできます。
// Fetch IDToken via the Apple SDK let credentials = Credentials.apple(idToken: "<token>") app.login(credentials: credentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Tip
Login failed
というエラーが発生した場合は、 のtoken contains
an invalid number of segments
UTF-8string でエンコードされたJSON web token バージョンを渡していることを確認してください。
Async/Await ログイン
バージョン 10.15.0 の新機能。
App.loginメソッドの async/await バージョンは非同期に ユーザー または エラーを返します。
func login() async { do { let app = App(id: YOUR_APP_SERVICES_APP_ID) // Authenticate with the instance of the app that points // to your backend. Here, we're using anonymous login. let user = try await app.login(credentials: Credentials.anonymous) print("Successfully logged in user: \(user)") } catch { print("Failed to log in user: \(error.localizedDescription)") } }
Realm Swift SDK バージョン 10.15.0 および 10.16.0 以降では、Realm API の多くが Swift async/await 構文をサポートしています。 プロジェクトは、次の要件を満たしている必要があります。
Swift SDK バージョン | Swift バージョン要件 | サポートされている OS |
---|---|---|
10.25.0 | Swift 5.6 | iOS 13.x |
10.15.0 または 10.16.0 | Swift 5.5 | iOS 15.x |
アプリがasync/await
コンテキストで Realm にアクセスする場合は、スレッド関連のクラッシュを回避するためにコードを@MainActor
でマークします。
オフライン ログイン
Realm アプリケーションはユーザーを認証する際、ユーザーの認証情報をキャッシュします。 既存のユーザー認証情報を確認して、ログイン フローをバイパスし、キャッシュされたユーザーにアクセスできます。 これを使用して、Realm をオフラインで開きます。
注意
最初のログインにはネットワーク接続が必要です
ユーザーがアプリにサインアップしたり、クライアントに既存のアカウントを使用して初めてログインする場合、クライアントにはネットワーク接続が必要です。 キャッシュされたユーザー認証情報を確認すると、ユーザーが以前にオンライン時にログインしたことがある場合にのみ、オフラインで Realm を開くことができます。
// Log the user into the backend app. // The first time you login, the user must have a network connection. func getUser() async throws -> User { // Check for an existing user. // If the user is offline but credentials are // cached, this returns the existing user. if let user = app.currentUser { return user } else { // If the device has no cached user // credentials, log them in. let app = App(id: YOUR_APP_SERVICES_APP_ID) let loggedInUser = try await app.login(credentials: Credentials.anonymous) return loggedInUser } } let user = try await getUser() var configuration = user.configuration(partitionValue: "Some Partition Value") // Open a Realm with this configuration. // If you do not require the app to download updates // before opening the realm, the realm just opens, even if // offline. let realm = try await Realm(configuration: configuration) print("Successfully opened realm: \(realm)")
ユーザー アクセス トークンを取得する
Realm SDK はアクセス トークンを自動的に管理し、有効期限が切れると更新し、リクエストごとに現在のユーザーの有効なアクセス トークンを含めます。
SDK 外でリクエストを送信する場合は、各リクエストにユーザーのアクセス トークンを含める必要があります。 このシナリオでは、トークンの有効期限が切れたときにトークンを手動で更新する必要があります。 アクセス トークンは30分後に期限切れになります。
ログインしたユーザーで.refreshCustomData()を呼び出して、ユーザーの認証セッションを更新できます。 次に、コードで使用できるstringとして .accessToken
を返します。 アクセストークンを取得するには、次のような関数を使用できます。
func getValidAccessToken(user: User) async throws -> String { // An already logged in user's access token might be stale. To // guarantee that the token is valid, refresh it if necessary. try await user.refreshCustomData() return user.accessToken! }
これにはログインユーザーが必要です。
let app = App(id: YOUR_APP_SERVICES_APP_ID) let user = try await app.login(credentials: Credentials.anonymous) let accessToken = try await getValidAccessToken(user: user)
リフレッシュ トークンの有効期限
リフレッシュ トークンは一定期間後に期限切れになります。 更新トークンの有効期限が切れると、アクセス トークンの更新ができなくなり、ユーザーは再度ログインする必要があります。
Realm が開いた後に更新トークンの有効期限が切れると、ユーザーが再度ログインするまでデバイスは同期できなくなります。 同期エラー ハンドラーには、同期試行時にトークンの期限切れエラーを検出し、ユーザーをログイン フローにリダイレクトするロジックを実装する必要があります。
リフレッシュ トークンの有効期限の設定の詳細については、App Services ドキュメントの「ユーザー セッションの管理」を参照してください。
ログアウト
ログインすると、以下のログアウトが可能になります。
警告
ユーザーがログアウトすると、ユーザーが開いた同期された Realm でデータの読み取りも書き込みもできなくなります。 その結果、開始ユーザーがログアウトする前にまだ完了していない操作は正常に完了できず、エラーが発生する可能性が高くなります。 このように失敗した書込み操作のデータは失われます。
app.currentUser?.logOut { (error) in // user is logged out or there was an error }