/* * Copyright 2016 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FIREBASE_AUTH_SRC_INCLUDE_FIREBASE_AUTH_H_ #define FIREBASE_AUTH_SRC_INCLUDE_FIREBASE_AUTH_H_ #include #include #include "firebase/app.h" #include "firebase/auth/user.h" #include "firebase/future.h" #include "firebase/internal/common.h" #if !defined(DOXYGEN) #ifndef SWIG FIREBASE_APP_REGISTER_CALLBACKS_REFERENCE(auth) #endif // SWIG #endif // !defined(DOXYGEN) namespace firebase { /// @brief Firebase Authentication API. /// /// Firebase Authentication provides backend services to securely authenticate /// users. It can authenticate users using passwords and federated identity /// provider credentials, and it can integrate with a custom auth backend. namespace auth { // Predeclarations. struct AuthData; class AuthStateListener; class IdTokenListener; class PhoneAuthProvider; class AuthRequest; struct AuthResultCompletionHandle; class FederatedAuthProvider; class FederatedOAuthProvider; /// @brief Firebase authentication object. /// /// /// @if swig_examples /// Firebase.Auth.FirebaseAuth is the gateway to the Firebase authentication /// API. With it, you can reference Firebase.Auth.FirebaseAuth objects to /// manage user accounts and credentials. /// /// Each Firebase.FirebaseApp has up to one Firebase.Auth.FirebaseAuth /// class. You acquire the Firebase.Auth.FirebaseAuth class through the static /// function Firebase.Auth.FirebaseAuth.GetAuth. /// /// For example: /// @code{.cs} /// // Get the Auth class for your App. /// Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.GetAuth(app); /// /// // Request anonymous sign-in and wait until asynchronous call completes. /// auth.SignInAnonymouslyAsync().ContinueWith((authTask) => { /// // Print sign in results. /// if (authTask.IsCanceled) { /// DebugLog("Sign-in canceled."); /// } else if (authTask.IsFaulted) { /// DebugLog("Sign-in encountered an error."); /// DebugLog(authTask.Exception.ToString()); /// } else if (authTask.IsCompleted) { /// Firebase.Auth.User user = authTask.Result; /// DebugLog(String.Format("Signed in as {0} user.", /// user.Anonymous ? "an anonymous" : "a non-anonymous")); /// DebugLog("Signing out."); /// auth.SignOut(); /// }); /// @endcode /// @endif /// /// @if cpp_examples /// /// firebase::auth::Auth is the gateway to the Firebase authentication API. /// With it, you can reference firebase::auth::User objects to manage user /// accounts and credentials. /// /// Each firebase::App has up to one firebase::auth::Auth class. You /// acquire the firebase::auth::Auth class through the static function /// firebase::auth::Auth::GetAuth. /// /// For example: /// @code{.cpp} /// /// // Get the Auth class for your App. /// firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app); /// /// // Request anonymous sign-in and wait until asynchronous call completes. /// firebase::Future sign_in_future = /// auth->SignInAnonymously(); /// while(sign_in_future.status() == firebase::kFutureStatusPending) { /// // when polling, like this, make sure you service your platform's /// // message loop /// // see https://github.com/firebase/quickstart-cpp for a sample /// ProcessEvents(300); /// std::cout << "Signing in...\n"; /// } /// /// const firebase::auth::AuthError error = /// static_cast(sign_in_future.error()); /// if (error != firebase::auth::kAuthErrorNone) { /// std::cout << "Sign in failed with error '" /// << sign_in_future.error_message() << "'\n"; /// } else { /// firebase::auth::User user = sign_in_future.result()->user; /// // is_anonymous from Anonymous /// std::cout << "Signed in as " /// << (user.is_anonymous() ? "an anonymous" : "a non-anonymous") /// << " user\n"; /// } /// @endcode /// @endif class Auth { public: /// @brief Results of calls FetchProvidersForEmail. /// /// /// @if swig_examples /// @see FirebaseAuth.FetchProvidersForEmailAsync(). /// @endif /// struct FetchProvidersResult { /// The IDPs (identity providers) that can be used for `email`. /// An array of length `num_providers` of null-terminated strings. /// /// The C# doc string is in the SWIG file because nested structs are /// causing problems b/35780150 /// std::vector providers; }; ~Auth(); /// Synchronously gets the cached current user, or returns an object where /// is_valid() == false if there is none. /// /// @note This function may block and wait until the Auth instance finishes /// loading the saved user's state. This should only happen for a short /// time after the Auth instance is created. User current_user(); /// The current user language code. This can be set to the app’s current /// language by calling set_language_code. The string must be a language code /// that follows BCP 47. This will return an empty string if the app default /// language code is being used. std::string language_code() const; /// Sets the user-facing language code for auth operations that can be /// internationalized, such as FirebaseUser.sendEmailVerification(). This /// language code should follow the conventions defined by the IETF in BCP 47. void set_language_code(const char* language_code); /// Sets the user-facing language code to be the default app language. This /// uses a language associated with the device's locale data. On desktop /// this will set the language code to the Firebase service's default. You /// may subsequently customize the language code again by invoking /// set_language_code(). void UseAppLanguage(); // ----- Providers ------------------------------------------------------- /// Asynchronously requests the IDPs (identity providers) that can be used /// for the given email address. /// /// Useful for an "identifier-first" login flow. /// /// @if cpp_examples /// The following sample code illustrates a possible login screen /// that allows the user to pick an identity provider. /// @code{.cpp} /// // This function is called every frame to display the login screen. /// // Returns the identity provider name, or "" if none selected. /// const char* DisplayIdentityProviders(firebase::auth::Auth& auth, /// const char* email) { /// // Get results of most recent call to FetchProvidersForEmail(). /// firebase::Future future = /// auth.FetchProvidersForEmailLastResult(); /// const firebase::auth::Auth::FetchProvidersResult* result = /// future.result(); /// /// // Header. /// ShowTextBox("Sign in %s", email); /// /// // Fetch providers from the server if we need to. /// const bool refetch = /// future.status() == firebase::kFutureStatusInvalid || /// (result != nullptr && strcmp(email, result->email.c_str()) != 0); /// if (refetch) { /// auth.FetchProvidersForEmail(email); /// } /// /// // Show a waiting icon if we're waiting for the asynchronous call to /// // complete. /// if (future.status() != firebase::kFutureStatusComplete) { /// ShowImage("waiting icon"); /// return ""; /// } /// /// // Show error code if the call failed. /// if (future.error() != firebase::auth::kAuthErrorNone) { /// ShowTextBox("Error fetching providers: %s", future.error_message()); /// } /// /// // Show a button for each provider available to this email. /// // Return the provider for the button that's pressed. /// for (size_t i = 0; i < result->providers.size(); ++i) { /// const bool selected = ShowTextButton(result->providers[i].c_str()); /// if (selected) return result->providers[i].c_str(); /// } /// return ""; /// } /// @endcode /// @endif Future FetchProvidersForEmail(const char* email); /// Get results of the most recent call to FetchProvidersForEmail. Future FetchProvidersForEmailLastResult() const; /// Asynchronously logs into Firebase with the given Auth token. /// /// An error is returned if the token is invalid, expired or otherwise not /// accepted by the server. Future SignInWithCustomToken(const char* custom_token); /// Get results of the most recent call to SignInWithCustomToken. Future SignInWithCustomTokenLastResult() const; /// Convenience method for SignInAndRetrieveDataWithCredential that /// doesn't return additional identity provider data. Future SignInWithCredential(const Credential& credential); /// Sign-in a user authenticated via a federated auth provider. /// /// @param[in] provider Contains information on the provider to authenticate /// with. /// /// @return A Future with the result of the sign-in request. /// /// @note: This operation is supported only on iOS, tvOS and Android /// platforms. On other platforms this method will return a Future with a /// preset error code: kAuthErrorUnimplemented. Future SignInWithProvider(FederatedAuthProvider* provider); /// Asynchronously logs into Firebase with the given credentials. /// /// For example, the credential could wrap a Facebook login access token or /// a Twitter token/token-secret pair. /// /// The AuthResult contains both a reference to the User (which is_valid() /// will return false if the sign in failed), and AdditionalUserInfo, which /// holds details specific to the Identity Provider used to sign in. /// /// An error is returned if the token is invalid, expired, or otherwise not /// accepted by the server. Future SignInAndRetrieveDataWithCredential( const Credential& credential); /// Get results of the most recent call to /// SignInAndRetrieveDataWithCredential. Future SignInAndRetrieveDataWithCredentialLastResult() const; /// Asynchronously creates and becomes an anonymous user. /// If there is already an anonymous user signed in, that user will be /// returned instead. /// If there is any other existing user, that user will be signed out. /// /// /// @if swig_examples /// @code{.cs} /// bool SignIn(Firebase.Auth.FirebaseAuth auth) { /// auth.SignInAnonymouslyAsync().ContinueWith((authTask) => { /// if (authTask.IsCanceled) { /// DebugLog("Anonymous sign in canceled."); /// } else if (authTask.IsFaulted) { /// DebugLog("Anonymous sign in encountered an error."); /// DebugLog(authTask.Exception.ToString()); /// } else if (authTask.IsCompleted) { /// DebugLog("Anonymous sign in successful!"); /// } /// }); /// } /// @endcode /// @endif /// /// @if cpp_examples /// The following sample code illustrates the sign-in flow that might be /// used by a game or some other program with a regular (for example, 30Hz) /// update loop. /// /// The sample calls SignIn() every frame. We don’t maintain our own /// Futures but instead call SignInAnonymouslyLastResult() to get the Future /// of our most recent call. /// /// @code{.cpp} /// // Try to ensure that we get logged in. /// // This function is called every frame. /// bool SignIn(firebase::auth::Auth& auth) { /// // Grab the result of the latest sign-in attempt. /// firebase::Future future = /// auth.SignInAnonymouslyLastResult(); /// /// // If we're in a state where we can try to sign in, do so. /// if (future.status() == firebase::kFutureStatusInvalid || /// (future.status() == firebase::kFutureStatusComplete && /// future.error() != firebase::auth::kAuthErrorNone)) { /// auth.SignInAnonymously(); /// } /// /// // We're signed in if the most recent result was successful. /// return future.status() == firebase::kFutureStatusComplete && /// future.error() == firebase::auth::kAuthErrorNone; /// } /// @endcode /// @endif Future SignInAnonymously(); /// Get results of the most recent call to SignInAnonymously. Future SignInAnonymouslyLastResult() const; /// Signs in using provided email address and password. /// An error is returned if the password is wrong or otherwise not accepted /// by the server. Future SignInWithEmailAndPassword(const char* email, const char* password); /// Get results of the most recent call to /// SignInWithEmailAndPassword. Future SignInWithEmailAndPasswordLastResult() const; /// Creates, and on success, logs in a user with the given email address /// and password. /// /// An error is returned when account creation is unsuccessful /// (due to another existing account, invalid password, etc.). Future CreateUserWithEmailAndPassword(const char* email, const char* password); /// Get results of the most recent call to /// CreateUserWithEmailAndPassword. Future CreateUserWithEmailAndPasswordLastResult() const; /// Removes any existing authentication credentials from this client. /// This function always succeeds. void SignOut(); // ----- Password Reset ------------------------------------------------- /// Initiates a password reset for the given email address. /// /// If the email address is not registered, then the returned task has a /// status of IsFaulted. /// /// /// @if swig_examples /// @code{.cs} /// void ResetPassword(string email) { /// auth.SendPasswordResetEmail(email).ContinueWith((authTask) => { /// if (authTask.IsCanceled) { /// DebugLog("Password reset was canceled."); /// } else if (authTask.IsFaulted) { /// DebugLog("Password reset encountered an error."); /// DebugLog(authTask.Exception.ToString()); /// } else if (authTask.IsCompleted) { /// DebugLog("Password reset successful!"); /// } /// }); /// } /// @endcode /// @endif /// /// @if cpp_examples /// The following sample code illustrating a possible password reset flow. /// Like in the Anonymous Sign-In example above, the ResetPasswordScreen() /// function is called once per frame (say 30 times per second). /// /// No state is persisted by the caller in this example. The state of the /// most recent calls are instead accessed through calls to functions like /// auth.SendPasswordResetEmailLastResult(). /// @code{.cpp} /// const char* ImageNameForStatus(const firebase::FutureBase& future) { /// assert(future.status() != firebase::kFutureStatusInvalid); /// return future.status() == firebase::kFutureStatusPending /// ? "waiting icon" /// : future.error() == firebase::auth::kAuthErrorNone /// ? "checkmark icon" /// : "x mark icon"; /// } /// /// // This function is called once per frame. /// void ResetPasswordScreen(firebase::auth::Auth& auth) { /// // Gather email address. /// // ShowInputBox() returns a value when `enter` is pressed. /// const std::string email = ShowInputBox("Enter e-mail"); /// if (email != "") { /// auth.SendPasswordResetEmail(email.c_str()); /// } /// /// // Show checkmark, X-mark, or waiting icon beside the /// // email input box, to indicate if email has been sent. /// firebase::Future send_future = /// auth.SendPasswordResetEmailLastResult(); /// ShowImage(ImageNameForStatus(send_future)); /// /// // Display error message if the e-mail could not be sent. /// if (send_future.status() == firebase::kFutureStatusComplete && /// send_future.error() != firebase::auth::kAuthErrorNone) { /// ShowTextBox(send_future.error_message()); /// } /// } /// @endcode /// @endif Future SendPasswordResetEmail(const char* email); /// Get results of the most recent call to SendPasswordResetEmail. Future SendPasswordResetEmailLastResult() const; #ifndef SWIG /// @brief Registers a listener to changes in the authentication state. /// /// There can be more than one listener registered at the same time. /// The listeners are called asynchronously, possibly on a different thread. /// /// Authentication state changes are: /// - Right after the listener has been registered /// - When a user signs in /// - When the current user signs out /// - When the current user changes /// /// It is a recommended practice to always listen to sign-out events, as you /// may want to prompt the user to sign in again and maybe restrict the /// information or actions they have access to. /// /// Use RemoveAuthStateListener to unregister a listener. /// /// @note The caller owns `listener` and is responsible for destroying it. /// When `listener` is destroyed, or when Auth is destroyed, /// RemoveAuthStateListener is called automatically. void AddAuthStateListener(AuthStateListener* listener); /// @brief Unregisters a listener of authentication changes. /// /// Listener must previously been added with AddAuthStateListener. /// /// Note that listeners unregister themselves automatically when they /// are destroyed, and the Auth class unregisters its listeners when the /// Auth class itself is destroyed, so this function does not normally need /// to be called explicitly. void RemoveAuthStateListener(AuthStateListener* listener); /// @brief Registers a listener to changes in the ID token state. /// /// There can be more than one listener registered at the same time. /// The listeners are called asynchronously, possibly on a different thread. /// /// Authentication state changes are: /// - Right after the listener has been registered /// - When a user signs in /// - When the current user signs out /// - When the current user changes /// - When there is a change in the current user's token /// /// Use RemoveIdTokenListener to unregister a listener. /// /// @note The caller owns `listener` and is responsible for destroying it. /// When `listener` is destroyed, or when Auth is destroyed, /// RemoveIdTokenListener is called automatically. void AddIdTokenListener(IdTokenListener* listener); /// @brief Unregisters a listener of ID token changes. /// /// Listener must previously been added with AddIdTokenListener. /// /// Note that listeners unregister themselves automatically when they /// are destroyed, and the Auth class unregisters its listeners when the /// Auth class itself is destroyed, so this function does not normally need /// to be called explicitly. void RemoveIdTokenListener(IdTokenListener* listener); #endif // not SWIG #if !defined(DOXYGEN) && !defined(SWIG) /// /// Modify this Auth instance to communicate with the Firebase Authentication /// emulator. /// void UseEmulator(std::string host, uint32_t port); #endif //! defined(DOXYGEN), to hide the api from public documentation. /// Gets the App this auth object is connected to. App& app(); /// Returns the Auth object for an App. Creates the Auth if required. /// /// To get the Auth object for the default app, use, /// GetAuth(GetDefaultFirebaseApp()); /// /// If the library Auth fails to initialize, init_result_out will be /// written with the result status (if a pointer is given). /// /// @param[in] app The App to use for the Auth object. /// @param[out] init_result_out Optional: If provided, write the init result /// here. Will be set to kInitResultSuccess if initialization succeeded, or /// kInitResultFailedMissingDependency on Android if Google Play services is /// not available on the current device. static Auth* GetAuth(App* app, InitResult* init_result_out = nullptr); private: /// @cond FIREBASE_APP_INTERNAL friend class ::firebase::App; friend class ::firebase::auth::PhoneAuthProvider; friend class ::firebase::auth::AuthRequest; friend class IdTokenRefreshListener; friend class IdTokenRefreshThread; friend class UserDataPersist; friend class UserDesktopTest; friend class AuthDesktopTest; #ifndef SWIG friend void EnableTokenAutoRefresh(AuthData* authData); friend void DisableTokenAutoRefresh(AuthData* authData); friend void ResetTokenRefreshCounter(AuthData* authData); friend void LogHeartbeat(Auth* auth); #endif // not SWIG /// @endcond // Find Auth instance using App. Return null if the instance does not exist. static Auth* FindAuth(App* app); // Provides access to the auth token for the current user. Returns the // current user's auth token, or an empty string, if there isn't one. // Note that this can potentially return an expired token from the cache. static bool GetAuthTokenForRegistry(App* app, void* /*unused*/, void* out); // Provides asynchronous access to the auth token for the current user. Allow // the caller to force-refresh the token. Even without force-refresh, this // ensure the future contain a fresh current user's auth token. This function // returns invalid future if user data is not available. static bool GetAuthTokenAsyncForRegistry(App* app, void* force_refresh, void* out_future); // Provides access to the current user's uid, equivalent to calling // this->current_user().uid(). Returns the current user's uid or // an empty string, if there isn't one. The out pointer is expected to point // to an instance of std::string. static bool GetCurrentUserUidForRegistry(App* app, void* /*unused*/, void* out); // Starts and stops a thread to ensure that the cached auth token is never // kept long enough for it to expire. Refcounted, so multiple classes can // register this without causing problems. static bool StartTokenRefreshThreadForRegistry(App* app, void* /*unused*/, void* /*unused*/); static bool StopTokenRefreshThreadForRegistry(App* app, void* /*unused*/, void* /*unused*/); // Adds an indirect auth state listener implemented as a callback and a // context object. // // @param callback a function pointer that takes a single void* argument and // returns void (i.e. it has type void (*)(void*)). // @param context a pointer to an arbitrary object that Auth will pass to // the callback when the auth state changes. static bool AddAuthStateListenerForRegistry(App* app, void* callback, void* context); // Removes the indirect auth state listener that was added with the same // arguments. static bool RemoveAuthStateListenerForRegistry(App* app, void* callback, void* context); // Init and Destroy the platform specific auth data. void InitPlatformAuth(AuthData* const auth_data); void DestroyPlatformAuth(AuthData* const auth_data); // Call GetAuth() to create an Auth object. // Constructors and destructors don't make any external calls. // They just initialize and deinitialize internal variables. Auth(App* app, void* auth_impl); // Delete the internal AuthData object. void DeleteInternal(); // This class uses the pimpl mechanism to avoid exposing platform-dependent // implementation. AuthData* auth_data_; }; #ifndef SWIG /// @brief Listener called when there is a change in the authentication state. /// /// Override base class method to handle authentication state changes. /// Methods are invoked asynchronously and may be invoked on other threads. class AuthStateListener { public: /// @note: Destruction of the listener automatically calls /// RemoveAuthStateListener() from the Auths this listener is registered with, /// if those Auths have not yet been destroyed. virtual ~AuthStateListener(); /// Called when the authentication state of `auth` changes. /// - Right after the listener has been registered /// - When a user is signed in /// - When the current user is signed out /// - When the current user changes /// /// @param[in] auth Disambiguates which Auth instance the event /// corresponds to, in the case where you are using more than one at the same /// time. virtual void OnAuthStateChanged(Auth* auth) = 0; private: /// @cond FIREBASE_APP_INTERNAL friend class Auth; /// @endcond /// The Auths with which this listener has been registered. std::vector auths_; }; #endif // not SWIG #ifndef SWIG /// @brief Listener called when there is a change in the ID token. /// /// Override base class method to handle ID token changes. /// Methods are invoked asynchronously and may be invoked on other threads. class IdTokenListener { public: /// @note: Destruction of the listener automatically calls /// RemoveIdTokenListener() from the Auths this listener is registered with, /// if those Auths have not yet been destroyed. virtual ~IdTokenListener(); /// Called when there is a change in the current user's token. /// - Right after the listener has been registered /// - When a user signs in /// - When the current user signs out /// - When the current user changes /// - When there is a change in the current user's token /// /// @param[in] auth Disambiguates which Auth instance the event /// corresponds to, in the case where you are using more than one at the same /// time. virtual void OnIdTokenChanged(Auth* auth) = 0; private: /// @cond FIREBASE_APP_INTERNAL friend class Auth; /// @endcond /// The Auths with which this listener has been registered. std::vector auths_; }; #endif // not SWIG /// @brief Used to authenticate with Federated Auth Providers. /// /// The federated auth provider implementation may facilitate multiple provider /// types in the future, with support for OAuth to start. class FederatedAuthProvider { public: #ifdef INTERNAL_EXPERIMENTAL #ifndef SWIG /// @brief Contains resulting information of a user authenticated by a /// Federated Auth Provider. This information will be used by the internal /// implementation to construct a corresponding User object. struct AuthenticatedUserData { /// The unique ID identifies the IdP account. const char* uid; /// [opt] The email of the account. const char* email; /// Whether the sign-in email is verified. bool is_email_verified; /// [opt] The display name for the account. const char* display_name; /// [opt] The username for the account. const char* user_name; /// [opt] The photo Url for the account, if one exists. const char* photo_url; /// The linked provider ID (e.g. "google.com" for the Google provider). const char* provider_id; /// A Firebase Auth ID token for the authenticated user. const char* access_token; /// A Firebase Auth refresh token for the authenticated user. const char* refresh_token; /// [opt] IdP user profile data corresponding to the provided credential. std::map raw_user_info; /// The number of seconds in which the ID token expires. uint64_t token_expires_in_seconds; }; /// @brief Handlers for client applications to facilitate federated auth /// requests on non-mobile systems. template class Handler { public: virtual ~Handler() {} /// @brief Application sign-in handler. /// /// Invoked in SignIn flows that use Auth::SignInWithProvider. /// /// The application must implement this method to handle federated auth user /// sign-in requests on non-mobile systems. /// /// @param[in] provider_data Contains information on the provider to /// authenticate with. /// @param[in] completion_handle Internal data pertaining to this operation /// which must be passed to SignInComplete once the handler has completed /// the sign in operation. /// /// @see Auth#SignInWithProvider /// @see SignInComplete virtual void OnSignIn(const T& provider_data, AuthResultCompletionHandle* completion_handle) {} /// Completion for OnSignIn events started by a call to /// Auth::SignInWithProvider. /// /// Invoke this method once the corresponding OnSignIn has been fulfilled. /// This method will trigger the associated Future previously /// returned from the Auth::SignInWithProvider method. /// /// @param[in] completion_handle The handle provided to the application's /// FederatedAuthProvider::Handler::OnSignIn method. /// @param[in] user_data The application's resulting Firebase user /// values following the authorization request. /// @param[in] auth_error The enumerated status code of the authorization /// request. /// @param[in] error_message An optional error message to be set in the /// Future. /// /// @see OnSignIn /// @see Auth::SignInWithProvider void SignInComplete(AuthResultCompletionHandle* completion_handle, const AuthenticatedUserData& user_data, AuthError auth_error, const char* error_message); /// @brief Application user account link handler. /// /// Invoked in Link flows that use User::LinkWithProvider. /// /// The application must implement this method to handle federated auth user /// link requests on non-mobile systems. /// /// @param[in] provider_data Contains information on the provider to /// authenticate with. /// @param[in] completion_handle Internal data pertaining to this operation /// which must be passed to LinkComplete once the handler has completed the /// user link operation. /// /// @see User#LinkWithProvider virtual void OnLink(const T& provider_data, AuthResultCompletionHandle* completion_handle) {} /// Completion for non-mobile user authorization handlers. /// /// Invoke this method once the OnLink process has been fulfilled. This /// method will trigger the associated Future previously /// returned from an invocation of User::LinkWithProvider. /// /// @param[in] completion_handle The handle provided to the /// application's FederatedAuthProvider::Handler::OnLink method. /// @param[in] user_data The application's resulting Firebase user /// values following the user link request. /// @param[in] auth_error The enumerated status code of the user link /// request. /// @param[in] error_message An optional error message to be set in the /// Future. /// /// @see OnLink /// @see User#LinkWithProvider void LinkComplete(AuthResultCompletionHandle* completion_handle, const AuthenticatedUserData& user_data, AuthError auth_error, const char* error_message); /// @brief Application user re-authentication handler. /// /// The application must implement this method to handle federated auth user /// re-authentication requests on non-mobile systems. /// /// @param[in] provider_data Contains information on the provider to /// authenticate with. /// @param[in] completion_handle Internal data pertaining to this operation /// which must be passed to ReauthenticateComplete once the handler has /// completed the reauthentication operation. /// /// @see User#ReauthenticateWithProviderComplete virtual void OnReauthenticate( const T& provider_data, AuthResultCompletionHandle* completion_handle) { } /// Completion for non-mobile user authorization handlers. /// /// Invoke this method once the OnReauthenticate process has been /// fulfilled. This method will trigger the associated Future /// previously returned from an invocation of /// User::ReauthenticateWithProvider. /// /// @param[in] completion_handle The handle provided to the application's /// FederatedAuthProvider::Handler::OnReauthenticate method. /// @param[in] user_data The application's resulting Firebase user /// values following the user re-authentication request. /// @param[in] auth_error The enumerated status code of the reauthentication /// request. /// @param[in] error_message An optional error message to be set in the /// Future. /// /// @see OnReauthenticate /// @see User#ReuthenticateWithProvider void ReauthenticateComplete(AuthResultCompletionHandle* completion_handle, const AuthenticatedUserData& user_data, AuthError auth_error, const char* error_message); }; #endif // not SWIG #endif // INTERNAL_EXPERIMENTAL FederatedAuthProvider() {} virtual ~FederatedAuthProvider() {} #if !defined(DOXYGEN) virtual Future SignIn(AuthData* auth_data) = 0; virtual Future Link(AuthData* auth_data) = 0; virtual Future Reauthenticate(AuthData* auth_data) = 0; #endif // !defined(DOXYGEN) private: friend class ::firebase::auth::Auth; friend class ::firebase::auth::User; }; /// @brief Authenticates with Federated OAuth Providers via the /// firebase::auth::Auth and firebase::auth::User classes. /// /// Once configured with a provider id, and with OAuth scope and OAuth custom /// parameters via an FedeartedOAuthProviderData structure, an object of /// this class may be used via Auth::SignInWithProvider to sign-in users, or via /// User::LinkWithProvider and User::ReauthenticateWithProvider for cross /// account linking and user reauthentication, respectively. class FederatedOAuthProvider : public FederatedAuthProvider { public: #ifdef INTERNAL_EXPERIMENTAL #ifndef SWIG /// @brief A FederatedAuthProvider typed specifically for OAuth Authentication /// handling. /// /// To be used on non-mobile environments for custom OAuth implementations and /// UI flows. typedef FederatedAuthProvider::Handler AuthHandler; #endif // !SWIG #endif // INTERNAL_EXPERIMENTAL /// Constructs an unconfigured provider. FederatedOAuthProvider(); /// Constructs a FederatedOAuthProvider preconfigured with provider data. /// /// @param[in] provider_data Contains the federated provider id and OAuth /// scopes and OAuth custom parameters required for user authentication and /// user linking. explicit FederatedOAuthProvider( const FederatedOAuthProviderData& provider_data); #ifdef INTERNAL_EXPERIMENTAL #ifndef SWIG /// @brief Constructs a provider with the required information to authenticate /// using an OAuth Provider. /// /// An AuthHandler is required on desktop platforms to facilitate custom /// implementations of OAuth authentication. The AuthHandler must outlive the /// instance of this OAuthProvider on desktop systems and is ignored on iOS, /// tvOS, and Android platforms. /// /// @param[in] provider_data Contains information on the provider to /// authenticate with. /// @param[in] handler An FederatedOAuthProviderData typed /// FederatedAuthProvider::Handler which be invoked on non-mobile systems /// to handle authentication requests. FederatedOAuthProvider(const FederatedOAuthProviderData& provider_data, AuthHandler* handler); #endif // !SWIG #endif // INTERNAL_EXPERIMENTAL ~FederatedOAuthProvider() override; /// @brief Configures the provider with OAuth provider information. /// /// @param[in] provider_data Contains the federated provider id and OAuth /// scopes and OAuth custom parameters required for user authentication and /// user linking. void SetProviderData(const FederatedOAuthProviderData& provider_data); #ifdef INTERNAL_EXPERIMENTAL #ifndef SWIG /// @brief Configures the use of an AuthHandler for non-mobile systems. /// /// The existence of a handler is required for non-mobile systems, and is /// ignored on iOS, tvOS and Android platforms. /// /// @param[in] handler An FederatedOAuthProviderData typed /// FederatedAuthProvider::Handler which be invoked on non-mobile systems /// to handle authentication requests. The handler must outlive the instance /// of this FederatedOAuthProvider. void SetAuthHandler(AuthHandler* handler); #endif // !SWIG #endif // INTERNAL_EXPERIMENTAL private: friend class ::firebase::auth::Auth; #if !defined(DOXYGEN) Future SignIn(AuthData* auth_data) override; Future Link(AuthData* auth_data) override; Future Reauthenticate(AuthData* auth_data) override; #endif // !defined(DOXYGEN) FederatedOAuthProviderData provider_data_; #ifdef INTERNAL_EXPERIMENTAL AuthHandler* handler_; #endif // INTERNAL_EXPERIMENTAL }; } // namespace auth } // namespace firebase #endif // FIREBASE_AUTH_SRC_INCLUDE_FIREBASE_AUTH_H_