All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.firebase.auth.AbstractFirebaseAuth Maven / Gradle / Ivy

/*
 * Copyright 2020 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.
 */

package com.google.firebase.auth;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.firebase.auth.internal.Utils.isEmulatorMode;

import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.Clock;
import com.google.api.core.ApiFuture;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseUserManager.EmailLinkType;
import com.google.firebase.auth.FirebaseUserManager.UserImportRequest;
import com.google.firebase.auth.ListProviderConfigsPage.DefaultOidcProviderConfigSource;
import com.google.firebase.auth.ListProviderConfigsPage.DefaultSamlProviderConfigSource;
import com.google.firebase.auth.ListUsersPage.DefaultUserSource;
import com.google.firebase.auth.internal.FirebaseTokenFactory;
import com.google.firebase.internal.CallableOperation;
import com.google.firebase.internal.NonNull;
import com.google.firebase.internal.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * This is the abstract class for server-side Firebase Authentication actions.
 */
public abstract class AbstractFirebaseAuth {

  private final Object lock = new Object();
  private final AtomicBoolean destroyed = new AtomicBoolean(false);

  private final FirebaseApp firebaseApp;
  private final Supplier tokenFactory;
  private final Supplier idTokenVerifier;
  private final Supplier cookieVerifier;
  private final Supplier userManager;
  private final JsonFactory jsonFactory;

  protected AbstractFirebaseAuth(Builder builder) {
    this.firebaseApp = checkNotNull(builder.firebaseApp);
    this.tokenFactory = threadSafeMemoize(builder.tokenFactory);
    this.idTokenVerifier = threadSafeMemoize(builder.idTokenVerifier);
    this.cookieVerifier = threadSafeMemoize(builder.cookieVerifier);
    this.userManager = threadSafeMemoize(builder.userManager);
    this.jsonFactory = firebaseApp.getOptions().getJsonFactory();
  }

  /**
   * Creates a Firebase custom token for the given UID. This token can then be sent back to a client
   * application to be used with the signInWithCustomToken
   * authentication API.
   *
   * 

{@link FirebaseApp} must have been initialized with service account credentials to use call * this method. * * @param uid The UID to store in the token. This identifies the user to other Firebase services * (Realtime Database, Firebase Auth, etc.). Should be less than 128 characters. * @return A Firebase custom token string. * @throws IllegalArgumentException If the specified uid is null or empty, or if the app has not * been initialized with service account credentials. * @throws FirebaseAuthException If an error occurs while generating the custom token. */ public String createCustomToken(@NonNull String uid) throws FirebaseAuthException { return createCustomToken(uid, null); } /** * Creates a Firebase custom token for the given UID, containing the specified additional claims. * This token can then be sent back to a client application to be used with the signInWithCustomToken * authentication API. * *

This method attempts to generate a token using: * *

    *
  1. the private key of {@link FirebaseApp}'s service account credentials, if provided at * initialization. *
  2. the IAM * service if a service account email was specified via {@link * com.google.firebase.FirebaseOptions.Builder#setServiceAccountId(String)}. *
  3. the App * Identity service if the code is deployed in the Google App Engine standard * environment. *
  4. the local * Metadata server if the code is deployed in a different GCP-managed environment like * Google Compute Engine. *
* *

This method throws an exception when all the above fail. * * @param uid The UID to store in the token. This identifies the user to other Firebase services * (Realtime Database, Firebase Auth, etc.). Should be less than 128 characters. * @param developerClaims Additional claims to be stored in the token (and made available to * security rules in Database, Storage, etc.). These must be able to be serialized to JSON * (e.g. contain only Maps, Arrays, Strings, Booleans, Numbers, etc.) * @return A Firebase custom token string. * @throws IllegalArgumentException If the specified uid is null or empty. * @throws IllegalStateException If the SDK fails to discover a viable approach for signing * tokens. * @throws FirebaseAuthException If an error occurs while generating the custom token. */ public String createCustomToken( @NonNull String uid, @Nullable Map developerClaims) throws FirebaseAuthException { return createCustomTokenOp(uid, developerClaims).call(); } /** * Similar to {@link #createCustomToken(String)} but performs the operation asynchronously. * * @param uid The UID to store in the token. This identifies the user to other Firebase services * (Realtime Database, Firebase Auth, etc.). Should be less than 128 characters. * @return An {@code ApiFuture} which will complete successfully with the created Firebase custom * token, or unsuccessfully with the failure Exception. * @throws IllegalArgumentException If the specified uid is null or empty, or if the app has not * been initialized with service account credentials. */ public ApiFuture createCustomTokenAsync(@NonNull String uid) { return createCustomTokenAsync(uid, null); } /** * Similar to {@link #createCustomToken(String, Map)} but performs the operation asynchronously. * * @param uid The UID to store in the token. This identifies the user to other Firebase services * (Realtime Database, Storage, etc.). Should be less than 128 characters. * @param developerClaims Additional claims to be stored in the token (and made available to * security rules in Database, Storage, etc.). These must be able to be serialized to JSON * (e.g. contain only Maps, Arrays, Strings, Booleans, Numbers, etc.) * @return An {@code ApiFuture} which will complete successfully with the created Firebase custom * token, or unsuccessfully with the failure Exception. * @throws IllegalArgumentException If the specified uid is null or empty, or if the app has not * been initialized with service account credentials. */ public ApiFuture createCustomTokenAsync( @NonNull String uid, @Nullable Map developerClaims) { return createCustomTokenOp(uid, developerClaims).callAsync(firebaseApp); } private CallableOperation createCustomTokenOp( final String uid, final Map developerClaims) { checkArgument(!Strings.isNullOrEmpty(uid), "uid must not be null or empty"); final FirebaseTokenFactory tokenFactory = this.tokenFactory.get(); return new CallableOperation() { @Override public String execute() throws FirebaseAuthException { return tokenFactory.createSignedCustomAuthTokenForUser(uid, developerClaims); } }; } /** * Creates a new Firebase session cookie from the given ID token and options. The returned JWT can * be set as a server-side session cookie with a custom cookie policy. * * @param idToken The Firebase ID token to exchange for a session cookie. * @param options Additional options required to create the cookie. * @return A Firebase session cookie string. * @throws IllegalArgumentException If the ID token is null or empty, or if options is null. * @throws FirebaseAuthException If an error occurs while generating the session cookie. */ public String createSessionCookie(@NonNull String idToken, @NonNull SessionCookieOptions options) throws FirebaseAuthException { return createSessionCookieOp(idToken, options).call(); } /** * Similar to {@link #createSessionCookie(String, SessionCookieOptions)} but performs the * operation asynchronously. * * @param idToken The Firebase ID token to exchange for a session cookie. * @param options Additional options required to create the cookie. * @return An {@code ApiFuture} which will complete successfully with a session cookie string. If * an error occurs while generating the cookie or if the specified ID token is invalid, the * future throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the ID token is null or empty, or if options is null. */ public ApiFuture createSessionCookieAsync( @NonNull String idToken, @NonNull SessionCookieOptions options) { return createSessionCookieOp(idToken, options).callAsync(firebaseApp); } private CallableOperation createSessionCookieOp( final String idToken, final SessionCookieOptions options) { checkArgument(!Strings.isNullOrEmpty(idToken), "idToken must not be null or empty"); checkNotNull(options, "options must not be null"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected String execute() throws FirebaseAuthException { return userManager.createSessionCookie(idToken, options); } }; } /** * Parses and verifies a Firebase ID Token. * *

A Firebase application can identify itself to a trusted backend server by sending its * Firebase ID Token (accessible via the {@code getToken} API in the Firebase Authentication * client) with its requests. The backend server can then use the {@code verifyIdToken()} method * to verify that the token is valid. This method ensures that the token is correctly signed, has * not expired, and it was issued to the Firebase project associated with this {@link * FirebaseAuth} instance. * *

This method does not check whether a token has been revoked. Use {@link * #verifyIdToken(String, boolean)} to perform an additional revocation check. * * @param idToken A Firebase ID token string to parse and verify. * @return A {@link FirebaseToken} representing the verified and decoded token. * @throws IllegalArgumentException If the token is null, empty, or if the {@link FirebaseApp} * instance does not have a project ID associated with it. * @throws FirebaseAuthException If an error occurs while parsing or validating the token. */ public FirebaseToken verifyIdToken(@NonNull String idToken) throws FirebaseAuthException { return verifyIdToken(idToken, false); } /** * Parses and verifies a Firebase ID Token. * *

A Firebase application can identify itself to a trusted backend server by sending its * Firebase ID Token (accessible via the {@code getToken} API in the Firebase Authentication * client) with its requests. The backend server can then use the {@code verifyIdToken()} method * to verify that the token is valid. This method ensures that the token is correctly signed, has * not expired, and it was issued to the Firebase project associated with this {@link * FirebaseAuth} instance. * *

If {@code checkRevoked} is set to true, this method performs an additional check to see if * the ID token has been revoked since it was issues. This requires making an additional remote * API call. * * @param idToken A Firebase ID token string to parse and verify. * @param checkRevoked A boolean denoting whether to check if the tokens were revoked or if * the user is disabled. * @return A {@link FirebaseToken} representing the verified and decoded token. * @throws IllegalArgumentException If the token is null, empty, or if the {@link FirebaseApp} * instance does not have a project ID associated with it. * @throws FirebaseAuthException If an error occurs while parsing or validating the token, or if * the user is disabled. */ public FirebaseToken verifyIdToken(@NonNull String idToken, boolean checkRevoked) throws FirebaseAuthException { return verifyIdTokenOp(idToken, checkRevoked).call(); } /** * Similar to {@link #verifyIdToken(String)} but performs the operation asynchronously. * * @param idToken A Firebase ID Token to verify and parse. * @return An {@code ApiFuture} which will complete successfully with the parsed token, or * unsuccessfully with a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the token is null, empty, or if the {@link FirebaseApp} * instance does not have a project ID associated with it. */ public ApiFuture verifyIdTokenAsync(@NonNull String idToken) { return verifyIdTokenAsync(idToken, false); } /** * Similar to {@link #verifyIdToken(String, boolean)} but performs the operation asynchronously. * * @param idToken A Firebase ID Token to verify and parse. * @param checkRevoked A boolean denoting whether to check if the tokens were revoked. * @return An {@code ApiFuture} which will complete successfully with the parsed token, or * unsuccessfully with a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the token is null, empty, or if the {@link FirebaseApp} * instance does not have a project ID associated with it. */ public ApiFuture verifyIdTokenAsync(@NonNull String idToken, boolean checkRevoked) { return verifyIdTokenOp(idToken, checkRevoked).callAsync(firebaseApp); } private CallableOperation verifyIdTokenOp( final String idToken, final boolean checkRevoked) { checkArgument(!Strings.isNullOrEmpty(idToken), "ID token must not be null or empty"); final FirebaseTokenVerifier verifier = getIdTokenVerifier(checkRevoked); return new CallableOperation() { @Override protected FirebaseToken execute() throws FirebaseAuthException { return verifier.verifyToken(idToken); } }; } @VisibleForTesting FirebaseTokenVerifier getIdTokenVerifier(boolean checkRevoked) { FirebaseTokenVerifier verifier = idTokenVerifier.get(); if (checkRevoked || isEmulatorMode()) { FirebaseUserManager userManager = getUserManager(); verifier = RevocationCheckDecorator.decorateIdTokenVerifier(verifier, userManager); } return verifier; } /** * Parses and verifies a Firebase session cookie. * *

If verified successfully, returns a parsed version of the cookie from which the UID and the * other claims can be read. If the cookie is invalid, throws a {@link FirebaseAuthException}. * *

This method does not check whether the cookie has been revoked. See {@link * #verifySessionCookie(String, boolean)}. * * @param cookie A Firebase session cookie string to verify and parse. * @return A {@link FirebaseToken} representing the verified and decoded cookie. */ public FirebaseToken verifySessionCookie(String cookie) throws FirebaseAuthException { return verifySessionCookie(cookie, false); } /** * Parses and verifies a Firebase session cookie. * *

If {@code checkRevoked} is true, additionally verifies that the cookie has not been revoked. * *

If verified successfully, returns a parsed version of the cookie from which the UID and the * other claims can be read. If the cookie is invalid or has been revoked while {@code * checkRevoked} is true, throws a {@link FirebaseAuthException}. * * @param cookie A Firebase session cookie string to verify and parse. * @param checkRevoked A boolean indicating whether to check if the cookie was explicitly revoked * or if the user is disabled. * @return A {@link FirebaseToken} representing the verified and decoded cookie. * @throws FirebaseAuthException If an error occurs while parsing or validating the token, or if * the user is disabled. */ public FirebaseToken verifySessionCookie(String cookie, boolean checkRevoked) throws FirebaseAuthException { return verifySessionCookieOp(cookie, checkRevoked).call(); } /** * Similar to {@link #verifySessionCookie(String)} but performs the operation asynchronously. * * @param cookie A Firebase session cookie string to verify and parse. * @return An {@code ApiFuture} which will complete successfully with the parsed cookie, or * unsuccessfully with the failure Exception. */ public ApiFuture verifySessionCookieAsync(String cookie) { return verifySessionCookieAsync(cookie, false); } /** * Similar to {@link #verifySessionCookie(String, boolean)} but performs the operation * asynchronously. * * @param cookie A Firebase session cookie string to verify and parse. * @param checkRevoked A boolean indicating whether to check if the cookie was explicitly revoked. * @return An {@code ApiFuture} which will complete successfully with the parsed cookie, or * unsuccessfully with the failure Exception. */ public ApiFuture verifySessionCookieAsync(String cookie, boolean checkRevoked) { return verifySessionCookieOp(cookie, checkRevoked).callAsync(firebaseApp); } private CallableOperation verifySessionCookieOp( final String cookie, final boolean checkRevoked) { checkArgument(!Strings.isNullOrEmpty(cookie), "Session cookie must not be null or empty"); final FirebaseTokenVerifier sessionCookieVerifier = getSessionCookieVerifier(checkRevoked); return new CallableOperation() { @Override public FirebaseToken execute() throws FirebaseAuthException { return sessionCookieVerifier.verifyToken(cookie); } }; } @VisibleForTesting FirebaseTokenVerifier getSessionCookieVerifier(boolean checkRevoked) { FirebaseTokenVerifier verifier = cookieVerifier.get(); if (checkRevoked || isEmulatorMode()) { FirebaseUserManager userManager = getUserManager(); verifier = RevocationCheckDecorator.decorateSessionCookieVerifier(verifier, userManager); } return verifier; } /** * Revokes all refresh tokens for the specified user. * *

Updates the user's tokensValidAfterTimestamp to the current UTC time expressed in * milliseconds since the epoch and truncated to 1 second accuracy. It is important that the * server on which this is called has its clock set correctly and synchronized. * *

While this will revoke all sessions for a specified user and disable any new ID tokens for * existing sessions from getting minted, existing ID tokens may remain active until their natural * expiration (one hour). To verify that ID tokens are revoked, use {@link * #verifyIdTokenAsync(String, boolean)}. * * @param uid The user id for which tokens are revoked. * @throws IllegalArgumentException If the user ID is null or empty. * @throws FirebaseAuthException If an error occurs while revoking tokens. */ public void revokeRefreshTokens(@NonNull String uid) throws FirebaseAuthException { revokeRefreshTokensOp(uid).call(); } /** * Similar to {@link #revokeRefreshTokens(String)} but performs the operation asynchronously. * * @param uid The user id for which tokens are revoked. * @return An {@code ApiFuture} which will complete successfully or fail with a {@link * FirebaseAuthException} in the event of an error. * @throws IllegalArgumentException If the user ID is null or empty. */ public ApiFuture revokeRefreshTokensAsync(@NonNull String uid) { return revokeRefreshTokensOp(uid).callAsync(firebaseApp); } private CallableOperation revokeRefreshTokensOp(final String uid) { checkArgument(!Strings.isNullOrEmpty(uid), "uid must not be null or empty"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected Void execute() throws FirebaseAuthException { int currentTimeSeconds = (int) (System.currentTimeMillis() / 1000); UserRecord.UpdateRequest request = new UserRecord.UpdateRequest(uid).setValidSince(currentTimeSeconds); userManager.updateUser(request, jsonFactory); return null; } }; } /** * Gets the user data corresponding to the specified user ID. * * @param uid A user ID string. * @return A {@link UserRecord} instance. * @throws IllegalArgumentException If the user ID string is null or empty. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public UserRecord getUser(@NonNull String uid) throws FirebaseAuthException { return getUserOp(uid).call(); } /** * Similar to {@link #getUser(String)} but performs the operation asynchronously. * * @param uid A user ID string. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance. If an error occurs while retrieving user data or if the specified user ID does * not exist, the future throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the user ID string is null or empty. */ public ApiFuture getUserAsync(@NonNull String uid) { return getUserOp(uid).callAsync(firebaseApp); } private CallableOperation getUserOp(final String uid) { checkArgument(!Strings.isNullOrEmpty(uid), "uid must not be null or empty"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserRecord execute() throws FirebaseAuthException { return userManager.getUserById(uid); } }; } /** * Gets the user data corresponding to the specified user email. * * @param email A user email address string. * @return A {@link UserRecord} instance. * @throws IllegalArgumentException If the email is null or empty. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public UserRecord getUserByEmail(@NonNull String email) throws FirebaseAuthException { return getUserByEmailOp(email).call(); } /** * Similar to {@link #getUserByEmail(String)} but performs the operation asynchronously. * * @param email A user email address string. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance. If an error occurs while retrieving user data or if the email address does not * correspond to a user, the future throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the email is null or empty. */ public ApiFuture getUserByEmailAsync(@NonNull String email) { return getUserByEmailOp(email).callAsync(firebaseApp); } private CallableOperation getUserByEmailOp( final String email) { checkArgument(!Strings.isNullOrEmpty(email), "email must not be null or empty"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserRecord execute() throws FirebaseAuthException { return userManager.getUserByEmail(email); } }; } /** * Gets the user data corresponding to the specified user phone number. * * @param phoneNumber A user phone number string. * @return A a {@link UserRecord} instance. * @throws IllegalArgumentException If the phone number is null or empty. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public UserRecord getUserByPhoneNumber(@NonNull String phoneNumber) throws FirebaseAuthException { return getUserByPhoneNumberOp(phoneNumber).call(); } /** * Gets the user data corresponding to the specified user phone number. * * @param phoneNumber A user phone number string. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance. If an error occurs while retrieving user data or if the phone number does not * correspond to a user, the future throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the phone number is null or empty. */ public ApiFuture getUserByPhoneNumberAsync(@NonNull String phoneNumber) { return getUserByPhoneNumberOp(phoneNumber).callAsync(firebaseApp); } private CallableOperation getUserByPhoneNumberOp( final String phoneNumber) { checkArgument(!Strings.isNullOrEmpty(phoneNumber), "phone number must not be null or empty"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserRecord execute() throws FirebaseAuthException { return userManager.getUserByPhoneNumber(phoneNumber); } }; } /** * Gets the user data for the user corresponding to a given provider ID. * * @param providerId Identifier for the given federated provider: for example, * "google.com" for the Google provider. * @param uid The user identifier with the given provider. * @return A {@link UserRecord} instance. * @throws IllegalArgumentException If the uid is null or empty, or if * the providerId is null, empty, or does not belong to a federated provider. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public UserRecord getUserByProviderUid( @NonNull String providerId, @NonNull String uid) throws FirebaseAuthException { return getUserByProviderUidOp(providerId, uid).call(); } /** * Gets the user data for the user corresponding to a given provider ID. * * @param providerId Identifer for the given federated provider: for example, * "google.com" for the Google provider. * @param uid The user identifier with the given provider. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance. If an error occurs while retrieving user data or if the provider ID and uid * do not correspond to a user, the future throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the uid is null or empty, or if * the provider ID is null, empty, or does not belong to a federated provider. */ public ApiFuture getUserByProviderUidAsync( @NonNull String providerId, @NonNull String uid) { return getUserByProviderUidOp(providerId, uid).callAsync(firebaseApp); } private CallableOperation getUserByProviderUidOp( final String providerId, final String uid) { checkArgument(!Strings.isNullOrEmpty(providerId), "providerId must not be null or empty"); checkArgument(!Strings.isNullOrEmpty(uid), "uid must not be null or empty"); // Although we don't really advertise it, we want to also handle // non-federated idps with this call. So if we detect one of them, we'll // reroute this request appropriately. if (providerId == "phone") { return this.getUserByPhoneNumberOp(uid); } else if (providerId == "email") { return this.getUserByEmailOp(uid); } checkArgument(!providerId.equals("password") && !providerId.equals("anonymous"), "providerId must belong to a federated provider"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserRecord execute() throws FirebaseAuthException { return userManager.getUserByProviderUid(providerId, uid); } }; } /** * Gets a page of users starting from the specified {@code pageToken}. Page size is limited to * 1000 users. * * @param pageToken A non-empty page token string, or null to retrieve the first page of users. * @return A {@link ListUsersPage} instance. * @throws IllegalArgumentException If the specified page token is empty. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public ListUsersPage listUsers(@Nullable String pageToken) throws FirebaseAuthException { return listUsers(pageToken, FirebaseUserManager.MAX_LIST_USERS_RESULTS); } /** * Gets a page of users starting from the specified {@code pageToken}. * * @param pageToken A non-empty page token string, or null to retrieve the first page of users. * @param maxResults Maximum number of users to include in the returned page. This may not exceed * 1000. * @return A {@link ListUsersPage} instance. * @throws IllegalArgumentException If the specified page token is empty, or max results value is * invalid. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public ListUsersPage listUsers(@Nullable String pageToken, int maxResults) throws FirebaseAuthException { return listUsersOp(pageToken, maxResults).call(); } /** * Similar to {@link #listUsers(String)} but performs the operation asynchronously. * * @param pageToken A non-empty page token string, or null to retrieve the first page of users. * @return An {@code ApiFuture} which will complete successfully with a {@link ListUsersPage} * instance. If an error occurs while retrieving user data, the future throws an exception. * @throws IllegalArgumentException If the specified page token is empty. */ public ApiFuture listUsersAsync(@Nullable String pageToken) { return listUsersAsync(pageToken, FirebaseUserManager.MAX_LIST_USERS_RESULTS); } /** * Similar to {@link #listUsers(String, int)} but performs the operation asynchronously. * * @param pageToken A non-empty page token string, or null to retrieve the first page of users. * @param maxResults Maximum number of users to include in the returned page. This may not exceed * 1000. * @return An {@code ApiFuture} which will complete successfully with a {@link ListUsersPage} * instance. If an error occurs while retrieving user data, the future throws an exception. * @throws IllegalArgumentException If the specified page token is empty, or max results value is * invalid. */ public ApiFuture listUsersAsync(@Nullable String pageToken, int maxResults) { return listUsersOp(pageToken, maxResults).callAsync(firebaseApp); } private CallableOperation listUsersOp( @Nullable final String pageToken, final int maxResults) { final FirebaseUserManager userManager = getUserManager(); final DefaultUserSource source = new DefaultUserSource(userManager, jsonFactory); final ListUsersPage.Factory factory = new ListUsersPage.Factory(source, maxResults, pageToken); return new CallableOperation() { @Override protected ListUsersPage execute() throws FirebaseAuthException { return factory.create(); } }; } /** * Creates a new user account with the attributes contained in the specified {@link * UserRecord.CreateRequest}. * * @param request A non-null {@link UserRecord.CreateRequest} instance. * @return A {@link UserRecord} instance corresponding to the newly created account. * @throws NullPointerException if the provided request is null. * @throws FirebaseAuthException if an error occurs while creating the user account. */ public UserRecord createUser(@NonNull UserRecord.CreateRequest request) throws FirebaseAuthException { return createUserOp(request).call(); } /** * Similar to {@link #createUser} but performs the operation asynchronously. * * @param request A non-null {@link UserRecord.CreateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance corresponding to the newly created account. If an error occurs while creating the * user account, the future throws a {@link FirebaseAuthException}. * @throws NullPointerException if the provided request is null. */ public ApiFuture createUserAsync(@NonNull UserRecord.CreateRequest request) { return createUserOp(request).callAsync(firebaseApp); } private CallableOperation createUserOp( final UserRecord.CreateRequest request) { checkNotNull(request, "create request must not be null"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserRecord execute() throws FirebaseAuthException { String uid = userManager.createUser(request); return userManager.getUserById(uid); } }; } /** * Updates an existing user account with the attributes contained in the specified {@link * UserRecord.UpdateRequest}. * * @param request A non-null {@link UserRecord.UpdateRequest} instance. * @return A {@link UserRecord} instance corresponding to the updated user account. * @throws NullPointerException if the provided update request is null. * @throws FirebaseAuthException if an error occurs while updating the user account. */ public UserRecord updateUser(@NonNull UserRecord.UpdateRequest request) throws FirebaseAuthException { return updateUserOp(request).call(); } /** * Similar to {@link #updateUser} but performs the operation asynchronously. * * @param request A non-null {@link UserRecord.UpdateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance corresponding to the updated user account. If an error occurs while updating the * user account, the future throws a {@link FirebaseAuthException}. */ public ApiFuture updateUserAsync(@NonNull UserRecord.UpdateRequest request) { return updateUserOp(request).callAsync(firebaseApp); } private CallableOperation updateUserOp( final UserRecord.UpdateRequest request) { checkNotNull(request, "update request must not be null"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserRecord execute() throws FirebaseAuthException { userManager.updateUser(request, jsonFactory); return userManager.getUserById(request.getUid()); } }; } /** * Sets the specified custom claims on an existing user account. A null claims value removes any * claims currently set on the user account. The claims should serialize into a valid JSON string. * The serialized claims must not be larger than 1000 characters. * * @param uid A user ID string. * @param claims A map of custom claims or null. * @throws FirebaseAuthException If an error occurs while updating custom claims. * @throws IllegalArgumentException If the user ID string is null or empty, or the claims payload * is invalid or too large. */ public void setCustomUserClaims(@NonNull String uid, @Nullable Map claims) throws FirebaseAuthException { setCustomUserClaimsOp(uid, claims).call(); } /** * @deprecated Use {@link #setCustomUserClaims(String, Map)} instead. */ public void setCustomClaims(@NonNull String uid, @Nullable Map claims) throws FirebaseAuthException { setCustomUserClaims(uid, claims); } /** * Similar to {@link #setCustomUserClaims(String, Map)} but performs the operation asynchronously. * * @param uid A user ID string. * @param claims A map of custom claims or null. * @return An {@code ApiFuture} which will complete successfully when the user account has been * updated. If an error occurs while deleting the user account, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the user ID string is null or empty. */ public ApiFuture setCustomUserClaimsAsync( @NonNull String uid, @Nullable Map claims) { return setCustomUserClaimsOp(uid, claims).callAsync(firebaseApp); } private CallableOperation setCustomUserClaimsOp( final String uid, final Map claims) { checkArgument(!Strings.isNullOrEmpty(uid), "uid must not be null or empty"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected Void execute() throws FirebaseAuthException { final UserRecord.UpdateRequest request = new UserRecord.UpdateRequest(uid).setCustomClaims(claims); userManager.updateUser(request, jsonFactory); return null; } }; } /** * Deletes the user identified by the specified user ID. * * @param uid A user ID string. * @throws IllegalArgumentException If the user ID string is null or empty. * @throws FirebaseAuthException If an error occurs while deleting the user. */ public void deleteUser(@NonNull String uid) throws FirebaseAuthException { deleteUserOp(uid).call(); } /** * Similar to {@link #deleteUser(String)} but performs the operation asynchronously. * * @param uid A user ID string. * @return An {@code ApiFuture} which will complete successfully when the specified user account * has been deleted. If an error occurs while deleting the user account, the future throws a * {@link FirebaseAuthException}. * @throws IllegalArgumentException If the user ID string is null or empty. */ public ApiFuture deleteUserAsync(String uid) { return deleteUserOp(uid).callAsync(firebaseApp); } private CallableOperation deleteUserOp(final String uid) { checkArgument(!Strings.isNullOrEmpty(uid), "uid must not be null or empty"); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected Void execute() throws FirebaseAuthException { userManager.deleteUser(uid); return null; } }; } /** * Imports the provided list of users into Firebase Auth. At most 1000 users can be imported at a * time. This operation is optimized for bulk imports and will ignore checks on identifier * uniqueness which could result in duplications. * *

{@link UserImportOptions} is required to import users with passwords. See {@link * #importUsers(List, UserImportOptions)}. * * @param users A non-empty list of users to be imported. Length must not exceed 1000. * @return A {@link UserImportResult} instance. * @throws IllegalArgumentException If the users list is null, empty or has more than 1000 * elements. Or if at least one user specifies a password. * @throws FirebaseAuthException If an error occurs while importing users. */ public UserImportResult importUsers(List users) throws FirebaseAuthException { return importUsers(users, null); } /** * Imports the provided list of users into Firebase Auth. At most 1000 users can be imported at a * time. This operation is optimized for bulk imports and will ignore checks on identifier * uniqueness which could result in duplications. * * @param users A non-empty list of users to be imported. Length must not exceed 1000. * @param options a {@link UserImportOptions} instance or null. Required when importing users with * passwords. * @return A {@link UserImportResult} instance. * @throws IllegalArgumentException If the users list is null, empty or has more than 1000 * elements. Or if at least one user specifies a password, and options is null. * @throws FirebaseAuthException If an error occurs while importing users. */ public UserImportResult importUsers( List users, @Nullable UserImportOptions options) throws FirebaseAuthException { return importUsersOp(users, options).call(); } /** * Similar to {@link #importUsers(List)} but performs the operation asynchronously. * * @param users A non-empty list of users to be imported. Length must not exceed 1000. * @return An {@code ApiFuture} which will complete successfully when the user accounts are * imported. If an error occurs while importing the users, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the users list is null, empty or has more than 1000 * elements. Or if at least one user specifies a password. */ public ApiFuture importUsersAsync(List users) { return importUsersAsync(users, null); } /** * Similar to {@link #importUsers(List, UserImportOptions)} but performs the operation * asynchronously. * * @param users A non-empty list of users to be imported. Length must not exceed 1000. * @param options a {@link UserImportOptions} instance or null. Required when importing users with * passwords. * @return An {@code ApiFuture} which will complete successfully when the user accounts are * imported. If an error occurs while importing the users, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the users list is null, empty or has more than 1000 * elements. Or if at least one user specifies a password, and options is null. */ public ApiFuture importUsersAsync( List users, @Nullable UserImportOptions options) { return importUsersOp(users, options).callAsync(firebaseApp); } private CallableOperation importUsersOp( final List users, final UserImportOptions options) { final UserImportRequest request = new UserImportRequest(users, options, jsonFactory); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected UserImportResult execute() throws FirebaseAuthException { return userManager.importUsers(request); } }; } /** * Gets the user data corresponding to the specified identifiers. * *

There are no ordering guarantees; in particular, the nth entry in the users result list is * not guaranteed to correspond to the nth entry in the input parameters list. * *

A maximum of 100 identifiers may be specified. If more than 100 identifiers are * supplied, this method throws an {@code IllegalArgumentException}. * * @param identifiers The identifiers used to indicate which user records should be returned. Must * have 100 or fewer entries. * @return The corresponding user records. * @throws IllegalArgumentException If any of the identifiers are invalid or if more than 100 * identifiers are specified. * @throws NullPointerException If the identifiers parameter is null. * @throws FirebaseAuthException If an error occurs while retrieving user data. */ public GetUsersResult getUsers(@NonNull Collection identifiers) throws FirebaseAuthException { return getUsersOp(identifiers).call(); } /** * Gets the user data corresponding to the specified identifiers. * *

There are no ordering guarantees; in particular, the nth entry in the users result list is * not guaranteed to correspond to the nth entry in the input parameters list. * *

A maximum of 100 identifiers may be specified. If more than 100 identifiers are * supplied, this method throws an {@code IllegalArgumentException}. * * @param identifiers The identifiers used to indicate which user records should be returned. * Must have 100 or fewer entries. * @return An {@code ApiFuture} that resolves to the corresponding user records. * @throws IllegalArgumentException If any of the identifiers are invalid or if more than 100 * identifiers are specified. * @throws NullPointerException If the identifiers parameter is null. */ public ApiFuture getUsersAsync(@NonNull Collection identifiers) { return getUsersOp(identifiers).callAsync(firebaseApp); } private CallableOperation getUsersOp( @NonNull final Collection identifiers) { checkNotNull(identifiers, "identifiers must not be null"); checkArgument(identifiers.size() <= FirebaseUserManager.MAX_GET_ACCOUNTS_BATCH_SIZE, "identifiers parameter must have <= " + FirebaseUserManager.MAX_GET_ACCOUNTS_BATCH_SIZE + " entries."); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected GetUsersResult execute() throws FirebaseAuthException { Set users = userManager.getAccountInfo(identifiers); Set notFound = new HashSet<>(); for (UserIdentifier id : identifiers) { if (!isUserFound(id, users)) { notFound.add(id); } } return new GetUsersResult(users, notFound); } }; } private boolean isUserFound(UserIdentifier id, Collection userRecords) { for (UserRecord userRecord : userRecords) { if (id.matches(userRecord)) { return true; } } return false; } /** * Deletes the users specified by the given identifiers. * *

Deleting a non-existing user does not generate an error (the method is idempotent). * Non-existing users are considered to be successfully deleted and are therefore included in the * DeleteUsersResult.getSuccessCount() value. * *

A maximum of 1000 identifiers may be supplied. If more than 1000 identifiers are * supplied, this method throws an {@code IllegalArgumentException}. * *

This API has a rate limit of 1 QPS. Exceeding the limit may result in a quota exceeded * error. If you want to delete more than 1000 users, we suggest adding a delay to ensure you * don't exceed this limit. * * @param uids The uids of the users to be deleted. Must have <= 1000 entries. * @return The total number of successful/failed deletions, as well as the array of errors that * correspond to the failed deletions. * @throws IllegalArgumentException If any of the identifiers are invalid or if more than 1000 * identifiers are specified. * @throws FirebaseAuthException If an error occurs while deleting users. */ public DeleteUsersResult deleteUsers(List uids) throws FirebaseAuthException { return deleteUsersOp(uids).call(); } /** * Similar to {@link #deleteUsers(List)} but performs the operation asynchronously. * * @param uids The uids of the users to be deleted. Must have <= 1000 entries. * @return An {@code ApiFuture} that resolves to the total number of successful/failed * deletions, as well as the array of errors that correspond to the failed deletions. If an * error occurs while deleting the user account, the future throws a * {@link FirebaseAuthException}. * @throws IllegalArgumentException If any of the identifiers are invalid or if more than 1000 * identifiers are specified. */ public ApiFuture deleteUsersAsync(List uids) { return deleteUsersOp(uids).callAsync(firebaseApp); } private CallableOperation deleteUsersOp( final List uids) { checkNotNull(uids, "uids must not be null"); for (String uid : uids) { UserRecord.checkUid(uid); } checkArgument(uids.size() <= FirebaseUserManager.MAX_DELETE_ACCOUNTS_BATCH_SIZE, "uids parameter must have <= " + FirebaseUserManager.MAX_DELETE_ACCOUNTS_BATCH_SIZE + " entries."); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected DeleteUsersResult execute() throws FirebaseAuthException { return userManager.deleteUsers(uids); } }; } /** * Generates the out-of-band email action link for password reset flows for the specified email * address. * * @param email The email of the user whose password is to be reset. * @return A password reset link. * @throws IllegalArgumentException If the email address is null or empty. * @throws FirebaseAuthException If an error occurs while generating the link. */ public String generatePasswordResetLink(@NonNull String email) throws FirebaseAuthException { return generatePasswordResetLink(email, null); } /** * Generates the out-of-band email action link for password reset flows for the specified email * address. * * @param email The email of the user whose password is to be reset. * @param settings The action code settings object which defines whether the link is to be handled * by a mobile app and the additional state information to be passed in the deep link. * @return A password reset link. * @throws IllegalArgumentException If the email address is null or empty. * @throws FirebaseAuthException If an error occurs while generating the link. */ public String generatePasswordResetLink( @NonNull String email, @Nullable ActionCodeSettings settings) throws FirebaseAuthException { return generateEmailActionLinkOp(EmailLinkType.PASSWORD_RESET, email, settings).call(); } /** * Similar to {@link #generatePasswordResetLink(String)} but performs the operation * asynchronously. * * @param email The email of the user whose password is to be reset. * @return An {@code ApiFuture} which will complete successfully with the generated email action * link. If an error occurs while generating the link, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the email address is null or empty. */ public ApiFuture generatePasswordResetLinkAsync(@NonNull String email) { return generatePasswordResetLinkAsync(email, null); } /** * Similar to {@link #generatePasswordResetLink(String, ActionCodeSettings)} but performs the * operation asynchronously. * * @param email The email of the user whose password is to be reset. * @param settings The action code settings object which defines whether the link is to be handled * by a mobile app and the additional state information to be passed in the deep link. * @return An {@code ApiFuture} which will complete successfully with the generated email action * link. If an error occurs while generating the link, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the email address is null or empty. */ public ApiFuture generatePasswordResetLinkAsync( @NonNull String email, @Nullable ActionCodeSettings settings) { return generateEmailActionLinkOp(EmailLinkType.PASSWORD_RESET, email, settings) .callAsync(firebaseApp); } /** * Generates the out-of-band email action link for email verification flows for the specified * email address. * * @param email The email of the user to be verified. * @return An email verification link. * @throws IllegalArgumentException If the email address is null or empty. * @throws FirebaseAuthException If an error occurs while generating the link. */ public String generateEmailVerificationLink(@NonNull String email) throws FirebaseAuthException { return generateEmailVerificationLink(email, null); } /** * Generates the out-of-band email action link for email verification flows for the specified * email address, using the action code settings provided. * * @param email The email of the user to be verified. * @return An email verification link. * @throws IllegalArgumentException If the email address is null or empty. * @throws FirebaseAuthException If an error occurs while generating the link. */ public String generateEmailVerificationLink( @NonNull String email, @Nullable ActionCodeSettings settings) throws FirebaseAuthException { return generateEmailActionLinkOp(EmailLinkType.VERIFY_EMAIL, email, settings).call(); } /** * Similar to {@link #generateEmailVerificationLink(String)} but performs the operation * asynchronously. * * @param email The email of the user to be verified. * @return An {@code ApiFuture} which will complete successfully with the generated email action * link. If an error occurs while generating the link, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the email address is null or empty. */ public ApiFuture generateEmailVerificationLinkAsync(@NonNull String email) { return generateEmailVerificationLinkAsync(email, null); } /** * Similar to {@link #generateEmailVerificationLink(String, ActionCodeSettings)} but performs the * operation asynchronously. * * @param email The email of the user to be verified. * @param settings The action code settings object which defines whether the link is to be handled * by a mobile app and the additional state information to be passed in the deep link. * @return An {@code ApiFuture} which will complete successfully with the generated email action * link. If an error occurs while generating the link, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the email address is null or empty. */ public ApiFuture generateEmailVerificationLinkAsync( @NonNull String email, @Nullable ActionCodeSettings settings) { return generateEmailActionLinkOp(EmailLinkType.VERIFY_EMAIL, email, settings) .callAsync(firebaseApp); } /** * Generates the out-of-band email action link for email link sign-in flows, using the action code * settings provided. * * @param email The email of the user signing in. * @param settings The action code settings object which defines whether the link is to be handled * by a mobile app and the additional state information to be passed in the deep link. * @return An email verification link. * @throws IllegalArgumentException If the email address is null or empty. * @throws FirebaseAuthException If an error occurs while generating the link. */ public String generateSignInWithEmailLink( @NonNull String email, @NonNull ActionCodeSettings settings) throws FirebaseAuthException { return generateEmailActionLinkOp(EmailLinkType.EMAIL_SIGNIN, email, settings).call(); } /** * Similar to {@link #generateSignInWithEmailLink(String, ActionCodeSettings)} but performs the * operation asynchronously. * * @param email The email of the user signing in. * @param settings The action code settings object which defines whether the link is to be handled * by a mobile app and the additional state information to be passed in the deep link. * @return An {@code ApiFuture} which will complete successfully with the generated email action * link. If an error occurs while generating the link, the future throws a {@link * FirebaseAuthException}. * @throws IllegalArgumentException If the email address is null or empty. * @throws NullPointerException If the settings is null. */ public ApiFuture generateSignInWithEmailLinkAsync( String email, @NonNull ActionCodeSettings settings) { return generateEmailActionLinkOp(EmailLinkType.EMAIL_SIGNIN, email, settings) .callAsync(firebaseApp); } private CallableOperation generateEmailActionLinkOp( final EmailLinkType type, final String email, final ActionCodeSettings settings) { checkArgument(!Strings.isNullOrEmpty(email), "email must not be null or empty"); if (type == EmailLinkType.EMAIL_SIGNIN) { checkNotNull(settings, "ActionCodeSettings must not be null when generating sign-in links"); } final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected String execute() throws FirebaseAuthException { return userManager.getEmailActionLink(type, email, settings); } }; } /** * Creates a new OpenID Connect auth provider config with the attributes contained in the * specified {@link OidcProviderConfig.CreateRequest}. * * @param request A non-null {@link OidcProviderConfig.CreateRequest} instance. * @return An {@link OidcProviderConfig} instance corresponding to the newly created provider * config. * @throws NullPointerException if the provided request is null. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not * prefixed with 'oidc.'. * @throws FirebaseAuthException if an error occurs while creating the provider config. */ public OidcProviderConfig createOidcProviderConfig( @NonNull OidcProviderConfig.CreateRequest request) throws FirebaseAuthException { return createOidcProviderConfigOp(request).call(); } /** * Similar to {@link #createOidcProviderConfig} but performs the operation asynchronously. * * @param request A non-null {@link OidcProviderConfig.CreateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link OidcProviderConfig} * instance corresponding to the newly created provider config. If an error occurs while * creating the provider config, the future throws a {@link FirebaseAuthException}. * @throws NullPointerException if the provided request is null. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not * prefixed with 'oidc.'. */ public ApiFuture createOidcProviderConfigAsync( @NonNull OidcProviderConfig.CreateRequest request) { return createOidcProviderConfigOp(request).callAsync(firebaseApp); } private CallableOperation createOidcProviderConfigOp(final OidcProviderConfig.CreateRequest request) { checkNotNull(request, "Create request must not be null."); OidcProviderConfig.checkOidcProviderId(request.getProviderId()); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected OidcProviderConfig execute() throws FirebaseAuthException { return userManager.createOidcProviderConfig(request); } }; } /** * Updates an existing OpenID Connect auth provider config with the attributes contained in the * specified {@link OidcProviderConfig.UpdateRequest}. * * @param request A non-null {@link OidcProviderConfig.UpdateRequest} instance. * @return A {@link OidcProviderConfig} instance corresponding to the updated provider config. * @throws NullPointerException if the provided update request is null. * @throws IllegalArgumentException If the provided update request is invalid. * @throws FirebaseAuthException if an error occurs while updating the provider config. */ public OidcProviderConfig updateOidcProviderConfig( @NonNull OidcProviderConfig.UpdateRequest request) throws FirebaseAuthException { return updateOidcProviderConfigOp(request).call(); } /** * Similar to {@link #updateOidcProviderConfig} but performs the operation asynchronously. * * @param request A non-null {@link OidcProviderConfig.UpdateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link OidcProviderConfig} * instance corresponding to the updated provider config. If an error occurs while updating * the provider config, the future throws a {@link FirebaseAuthException}. * @throws NullPointerException if the provided update request is null. * @throws IllegalArgumentException If the provided update request is invalid. */ public ApiFuture updateOidcProviderConfigAsync( @NonNull OidcProviderConfig.UpdateRequest request) { return updateOidcProviderConfigOp(request).callAsync(firebaseApp); } private CallableOperation updateOidcProviderConfigOp( final OidcProviderConfig.UpdateRequest request) { checkNotNull(request, "Update request must not be null."); checkArgument(!request.getProperties().isEmpty(), "Update request must have at least one property set."); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected OidcProviderConfig execute() throws FirebaseAuthException { return userManager.updateOidcProviderConfig(request); } }; } /** * Gets the OpenID Connect auth provider corresponding to the specified provider ID. * * @param providerId A provider ID string. * @return An {@link OidcProviderConfig} instance. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with 'oidc'. * @throws FirebaseAuthException If an error occurs while retrieving the provider config. */ public OidcProviderConfig getOidcProviderConfig(@NonNull String providerId) throws FirebaseAuthException { return getOidcProviderConfigOp(providerId).call(); } /** * Similar to {@link #getOidcProviderConfig(String)} but performs the operation asynchronously. * Page size is limited to 100 provider configs. * * @param providerId A provider ID string. * @return An {@code ApiFuture} which will complete successfully with an * {@link OidcProviderConfig} instance. If an error occurs while retrieving the provider * config or if the specified provider ID does not exist, the future throws a * {@link FirebaseAuthException}. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not * prefixed with 'oidc.'. */ public ApiFuture getOidcProviderConfigAsync(@NonNull String providerId) { return getOidcProviderConfigOp(providerId).callAsync(firebaseApp); } private CallableOperation getOidcProviderConfigOp(final String providerId) { OidcProviderConfig.checkOidcProviderId(providerId); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected OidcProviderConfig execute() throws FirebaseAuthException { return userManager.getOidcProviderConfig(providerId); } }; } /** * Gets a page of OpenID Connect auth provider configs starting from the specified * {@code pageToken}. Page size is limited to 100 provider configs. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @return A {@link ListProviderConfigsPage} instance. * @throws IllegalArgumentException If the specified page token is empty * @throws FirebaseAuthException If an error occurs while retrieving provider config data. */ public ListProviderConfigsPage listOidcProviderConfigs( @Nullable String pageToken) throws FirebaseAuthException { int maxResults = FirebaseUserManager.MAX_LIST_PROVIDER_CONFIGS_RESULTS; return listOidcProviderConfigsOp(pageToken, maxResults).call(); } /** * Gets a page of OpenID Connect auth provider configs starting from the specified * {@code pageToken}. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @param maxResults Maximum number of provider configs to include in the returned page. This may * not exceed 100. * @return A {@link ListProviderConfigsPage} instance. * @throws IllegalArgumentException If the specified page token is empty, or max results value is * invalid. * @throws FirebaseAuthException If an error occurs while retrieving provider config data. */ public ListProviderConfigsPage listOidcProviderConfigs( @Nullable String pageToken, int maxResults) throws FirebaseAuthException { return listOidcProviderConfigsOp(pageToken, maxResults).call(); } /** * Similar to {@link #listOidcProviderConfigs(String)} but performs the operation asynchronously. * Page size is limited to 100 provider configs. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @return An {@code ApiFuture} which will complete successfully with a * {@link ListProviderConfigsPage} instance. If an error occurs while retrieving provider * config data, the future throws an exception. * @throws IllegalArgumentException If the specified page token is empty. */ public ApiFuture> listOidcProviderConfigsAsync( @Nullable String pageToken) { int maxResults = FirebaseUserManager.MAX_LIST_PROVIDER_CONFIGS_RESULTS; return listOidcProviderConfigsAsync(pageToken, maxResults); } /** * Similar to {@link #listOidcProviderConfigs(String, int)} but performs the operation * asynchronously. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @param maxResults Maximum number of provider configs to include in the returned page. This may * not exceed 100. * @return An {@code ApiFuture} which will complete successfully with a * {@link ListProviderConfigsPage} instance. If an error occurs while retrieving provider * config data, the future throws an exception. * @throws IllegalArgumentException If the specified page token is empty, or max results value is * invalid. */ public ApiFuture> listOidcProviderConfigsAsync( @Nullable String pageToken, int maxResults) { return listOidcProviderConfigsOp(pageToken, maxResults).callAsync(firebaseApp); } private CallableOperation, FirebaseAuthException> listOidcProviderConfigsOp(@Nullable final String pageToken, final int maxResults) { final FirebaseUserManager userManager = getUserManager(); final DefaultOidcProviderConfigSource source = new DefaultOidcProviderConfigSource(userManager); final ListProviderConfigsPage.Factory factory = new ListProviderConfigsPage.Factory(source, maxResults, pageToken); return new CallableOperation, FirebaseAuthException>() { @Override protected ListProviderConfigsPage execute() throws FirebaseAuthException { return factory.create(); } }; } /** * Deletes the OpenID Connect auth provider config identified by the specified provider ID. * * @param providerId A provider ID string. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with 'oidc'. * @throws FirebaseAuthException If an error occurs while deleting the provider config. */ public void deleteOidcProviderConfig(@NonNull String providerId) throws FirebaseAuthException { deleteOidcProviderConfigOp(providerId).call(); } /** * Similar to {@link #deleteOidcProviderConfig} but performs the operation asynchronously. * * @param providerId A provider ID string. * @return An {@code ApiFuture} which will complete successfully when the specified provider * config has been deleted. If an error occurs while deleting the provider config, the future * throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with "oidc.". */ public ApiFuture deleteOidcProviderConfigAsync(String providerId) { return deleteOidcProviderConfigOp(providerId).callAsync(firebaseApp); } private CallableOperation deleteOidcProviderConfigOp( final String providerId) { OidcProviderConfig.checkOidcProviderId(providerId); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected Void execute() throws FirebaseAuthException { userManager.deleteOidcProviderConfig(providerId); return null; } }; } /** * Creates a new SAML Auth provider config with the attributes contained in the specified * {@link SamlProviderConfig.CreateRequest}. * * @param request A non-null {@link SamlProviderConfig.CreateRequest} instance. * @return An {@link SamlProviderConfig} instance corresponding to the newly created provider * config. * @throws NullPointerException if the provided request is null. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with 'saml'. * @throws FirebaseAuthException if an error occurs while creating the provider config. */ public SamlProviderConfig createSamlProviderConfig( @NonNull SamlProviderConfig.CreateRequest request) throws FirebaseAuthException { return createSamlProviderConfigOp(request).call(); } /** * Similar to {@link #createSamlProviderConfig} but performs the operation asynchronously. * * @param request A non-null {@link SamlProviderConfig.CreateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link SamlProviderConfig} * instance corresponding to the newly created provider config. If an error occurs while * creating the provider config, the future throws a {@link FirebaseAuthException}. * @throws NullPointerException if the provided request is null. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with 'saml'. */ public ApiFuture createSamlProviderConfigAsync( @NonNull SamlProviderConfig.CreateRequest request) { return createSamlProviderConfigOp(request).callAsync(firebaseApp); } private CallableOperation createSamlProviderConfigOp(final SamlProviderConfig.CreateRequest request) { checkNotNull(request, "Create request must not be null."); SamlProviderConfig.checkSamlProviderId(request.getProviderId()); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected SamlProviderConfig execute() throws FirebaseAuthException { return userManager.createSamlProviderConfig(request); } }; } /** * Updates an existing SAML Auth provider config with the attributes contained in the specified * {@link SamlProviderConfig.UpdateRequest}. * * @param request A non-null {@link SamlProviderConfig.UpdateRequest} instance. * @return A {@link SamlProviderConfig} instance corresponding to the updated provider config. * @throws NullPointerException if the provided update request is null. * @throws IllegalArgumentException If the provided update request is invalid. * @throws FirebaseAuthException if an error occurs while updating the provider config. */ public SamlProviderConfig updateSamlProviderConfig( @NonNull SamlProviderConfig.UpdateRequest request) throws FirebaseAuthException { return updateSamlProviderConfigOp(request).call(); } /** * Similar to {@link #updateSamlProviderConfig} but performs the operation asynchronously. * * @param request A non-null {@link SamlProviderConfig.UpdateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link SamlProviderConfig} * instance corresponding to the updated provider config. If an error occurs while updating * the provider config, the future throws a {@link FirebaseAuthException}. * @throws NullPointerException if the provided update request is null. * @throws IllegalArgumentException If the provided update request is invalid. */ public ApiFuture updateSamlProviderConfigAsync( @NonNull SamlProviderConfig.UpdateRequest request) { return updateSamlProviderConfigOp(request).callAsync(firebaseApp); } private CallableOperation updateSamlProviderConfigOp( final SamlProviderConfig.UpdateRequest request) { checkNotNull(request, "Update request must not be null."); checkArgument(!request.getProperties().isEmpty(), "Update request must have at least one property set."); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected SamlProviderConfig execute() throws FirebaseAuthException { return userManager.updateSamlProviderConfig(request); } }; } /** * Gets the SAML Auth provider config corresponding to the specified provider ID. * * @param providerId A provider ID string. * @return An {@link SamlProviderConfig} instance. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with 'saml'. * @throws FirebaseAuthException If an error occurs while retrieving the provider config. */ public SamlProviderConfig getSamlProviderConfig(@NonNull String providerId) throws FirebaseAuthException { return getSamlProviderConfigOp(providerId).call(); } /** * Similar to {@link #getSamlProviderConfig(String)} but performs the operation asynchronously. * Page size is limited to 100 provider configs. * * @param providerId A provider ID string. * @return An {@code ApiFuture} which will complete successfully with an * {@link SamlProviderConfig} instance. If an error occurs while retrieving the provider * config or if the specified provider ID does not exist, the future throws a * {@link FirebaseAuthException}. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with 'saml'. */ public ApiFuture getSamlProviderConfigAsync(@NonNull String providerId) { return getSamlProviderConfigOp(providerId).callAsync(firebaseApp); } private CallableOperation getSamlProviderConfigOp(final String providerId) { SamlProviderConfig.checkSamlProviderId(providerId); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected SamlProviderConfig execute() throws FirebaseAuthException { return userManager.getSamlProviderConfig(providerId); } }; } /** * Gets a page of SAML Auth provider configs starting from the specified {@code pageToken}. Page * size is limited to 100 provider configs. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @return A {@link ListProviderConfigsPage} instance. * @throws IllegalArgumentException If the specified page token is empty. * @throws FirebaseAuthException If an error occurs while retrieving provider config data. */ public ListProviderConfigsPage listSamlProviderConfigs( @Nullable String pageToken) throws FirebaseAuthException { return listSamlProviderConfigs( pageToken, FirebaseUserManager.MAX_LIST_PROVIDER_CONFIGS_RESULTS); } /** * Gets a page of SAML Auth provider configs starting from the specified {@code pageToken}. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @param maxResults Maximum number of provider configs to include in the returned page. This may * not exceed 100. * @return A {@link ListProviderConfigsPage} instance. * @throws IllegalArgumentException If the specified page token is empty, or max results value is * invalid. * @throws FirebaseAuthException If an error occurs while retrieving provider config data. */ public ListProviderConfigsPage listSamlProviderConfigs( @Nullable String pageToken, int maxResults) throws FirebaseAuthException { return listSamlProviderConfigsOp(pageToken, maxResults).call(); } /** * Similar to {@link #listSamlProviderConfigs(String)} but performs the operation asynchronously. * Page size is limited to 100 provider configs. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @return An {@code ApiFuture} which will complete successfully with a * {@link ListProviderConfigsPage} instance. If an error occurs while retrieving provider * config data, the future throws an exception. * @throws IllegalArgumentException If the specified page token is empty. */ public ApiFuture> listSamlProviderConfigsAsync( @Nullable String pageToken) { int maxResults = FirebaseUserManager.MAX_LIST_PROVIDER_CONFIGS_RESULTS; return listSamlProviderConfigsAsync(pageToken, maxResults); } /** * Similar to {@link #listSamlProviderConfigs(String, int)} but performs the operation * asynchronously. * * @param pageToken A non-empty page token string, or null to retrieve the first page of provider * configs. * @param maxResults Maximum number of provider configs to include in the returned page. This may * not exceed 100. * @return An {@code ApiFuture} which will complete successfully with a * {@link ListProviderConfigsPage} instance. If an error occurs while retrieving provider * config data, the future throws an exception. * @throws IllegalArgumentException If the specified page token is empty, or max results value is * invalid. */ public ApiFuture> listSamlProviderConfigsAsync( @Nullable String pageToken, int maxResults) { return listSamlProviderConfigsOp(pageToken, maxResults).callAsync(firebaseApp); } private CallableOperation, FirebaseAuthException> listSamlProviderConfigsOp(@Nullable final String pageToken, final int maxResults) { final FirebaseUserManager userManager = getUserManager(); final DefaultSamlProviderConfigSource source = new DefaultSamlProviderConfigSource(userManager); final ListProviderConfigsPage.Factory factory = new ListProviderConfigsPage.Factory(source, maxResults, pageToken); return new CallableOperation, FirebaseAuthException>() { @Override protected ListProviderConfigsPage execute() throws FirebaseAuthException { return factory.create(); } }; } /** * Deletes the SAML Auth provider config identified by the specified provider ID. * * @param providerId A provider ID string. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with "saml.". * @throws FirebaseAuthException If an error occurs while deleting the provider config. */ public void deleteSamlProviderConfig(@NonNull String providerId) throws FirebaseAuthException { deleteSamlProviderConfigOp(providerId).call(); } /** * Similar to {@link #deleteSamlProviderConfig} but performs the operation asynchronously. * * @param providerId A provider ID string. * @return An {@code ApiFuture} which will complete successfully when the specified provider * config has been deleted. If an error occurs while deleting the provider config, the future * throws a {@link FirebaseAuthException}. * @throws IllegalArgumentException If the provider ID string is null or empty, or is not prefixed * with "saml.". */ public ApiFuture deleteSamlProviderConfigAsync(String providerId) { return deleteSamlProviderConfigOp(providerId).callAsync(firebaseApp); } private CallableOperation deleteSamlProviderConfigOp( final String providerId) { SamlProviderConfig.checkSamlProviderId(providerId); final FirebaseUserManager userManager = getUserManager(); return new CallableOperation() { @Override protected Void execute() throws FirebaseAuthException { userManager.deleteSamlProviderConfig(providerId); return null; } }; } FirebaseUserManager getUserManager() { return this.userManager.get(); } Supplier threadSafeMemoize(final Supplier supplier) { return Suppliers.memoize( new Supplier() { @Override public T get() { checkNotNull(supplier); synchronized (lock) { return supplier.get(); } } }); } protected abstract static class Builder> { private FirebaseApp firebaseApp; private Supplier tokenFactory; private Supplier idTokenVerifier; private Supplier cookieVerifier; private Supplier userManager; protected abstract T getThis(); public FirebaseApp getFirebaseApp() { return firebaseApp; } public T setFirebaseApp(FirebaseApp firebaseApp) { this.firebaseApp = firebaseApp; return getThis(); } public T setIdTokenVerifier(Supplier idTokenVerifier) { this.idTokenVerifier = idTokenVerifier; return getThis(); } public T setCookieVerifier(Supplier cookieVerifier) { this.cookieVerifier = cookieVerifier; return getThis(); } T setUserManager(Supplier userManager) { this.userManager = userManager; return getThis(); } T setTokenFactory(Supplier tokenFactory) { this.tokenFactory = tokenFactory; return getThis(); } } protected static > T populateBuilderFromApp( Builder builder, final FirebaseApp app, @Nullable final String tenantId) { return builder.setFirebaseApp(app) .setTokenFactory( new Supplier() { @Override public FirebaseTokenFactory get() { return FirebaseTokenUtils.createTokenFactory(app, Clock.SYSTEM, tenantId); } }) .setIdTokenVerifier( new Supplier() { @Override public FirebaseTokenVerifier get() { return FirebaseTokenUtils.createIdTokenVerifier(app, Clock.SYSTEM, tenantId); } }) .setCookieVerifier( new Supplier() { @Override public FirebaseTokenVerifier get() { return FirebaseTokenUtils.createSessionCookieVerifier(app, Clock.SYSTEM, tenantId); } }) .setUserManager( new Supplier() { @Override public FirebaseUserManager get() { return FirebaseUserManager.createUserManager(app, tenantId); } }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy