![JAR search and dependency download from the Maven repository](/logo.png)
com.google.firebase.auth.FirebaseUserManager Maven / Gradle / Ivy
/*
* Copyright 2017 Google Inc.
*
* 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 com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpResponseInterceptor;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.Key;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.firebase.ErrorCode;
import com.google.firebase.FirebaseApp;
import com.google.firebase.ImplFirebaseTrampolines;
import com.google.firebase.IncomingHttpResponse;
import com.google.firebase.auth.internal.AuthHttpClient;
import com.google.firebase.auth.internal.BatchDeleteResponse;
import com.google.firebase.auth.internal.DownloadAccountResponse;
import com.google.firebase.auth.internal.GetAccountInfoRequest;
import com.google.firebase.auth.internal.GetAccountInfoResponse;
import com.google.firebase.auth.internal.ListOidcProviderConfigsResponse;
import com.google.firebase.auth.internal.ListSamlProviderConfigsResponse;
import com.google.firebase.auth.internal.UploadAccountResponse;
import com.google.firebase.auth.internal.Utils;
import com.google.firebase.internal.ApiClientUtils;
import com.google.firebase.internal.HttpRequestInfo;
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;
/**
* FirebaseUserManager provides methods for interacting with the Google Identity Toolkit via its
* REST API. This class does not hold any mutable state, and is thread safe.
*
* @see
* Google Identity Toolkit
*/
final class FirebaseUserManager {
static final int MAX_LIST_PROVIDER_CONFIGS_RESULTS = 100;
static final int MAX_GET_ACCOUNTS_BATCH_SIZE = 100;
static final int MAX_DELETE_ACCOUNTS_BATCH_SIZE = 1000;
static final int MAX_LIST_USERS_RESULTS = 1000;
static final int MAX_IMPORT_USERS = 1000;
static final List RESERVED_CLAIMS = ImmutableList.of(
"amr", "at_hash", "aud", "auth_time", "azp", "cnf", "c_hash", "exp", "iat",
"iss", "jti", "nbf", "nonce", "sub", "firebase");
private static final String ID_TOOLKIT_URL =
"https://identitytoolkit.googleapis.com/%s/projects/%s";
private static final String ID_TOOLKIT_URL_EMULATOR =
"http://%s/identitytoolkit.googleapis.com/%s/projects/%s";
private final String userMgtBaseUrl;
private final String idpConfigMgtBaseUrl;
private final JsonFactory jsonFactory;
private final AuthHttpClient httpClient;
private FirebaseUserManager(Builder builder) {
String projectId = builder.projectId;
checkArgument(!Strings.isNullOrEmpty(projectId),
"Project ID is required to access the auth service. Use a service account credential or "
+ "set the project ID explicitly via FirebaseOptions. Alternatively you can also "
+ "set the project ID via the GOOGLE_CLOUD_PROJECT environment variable.");
this.jsonFactory = checkNotNull(builder.jsonFactory, "JsonFactory must not be null");
final String idToolkitUrlV1 = getIdToolkitUrl(projectId, "v1");
final String idToolkitUrlV2 = getIdToolkitUrl(projectId, "v2");
final String tenantId = builder.tenantId;
if (tenantId == null) {
this.userMgtBaseUrl = idToolkitUrlV1;
this.idpConfigMgtBaseUrl = idToolkitUrlV2;
} else {
checkArgument(!tenantId.isEmpty(), "Tenant ID must not be empty.");
this.userMgtBaseUrl = idToolkitUrlV1 + "/tenants/" + tenantId;
this.idpConfigMgtBaseUrl = idToolkitUrlV2 + "/tenants/" + tenantId;
}
this.httpClient = new AuthHttpClient(jsonFactory, builder.requestFactory);
}
private String getIdToolkitUrl(String projectId, String version) {
if (Utils.isEmulatorMode()) {
return String.format(ID_TOOLKIT_URL_EMULATOR, Utils.getEmulatorHost(), version, projectId);
}
return String.format(ID_TOOLKIT_URL, version, projectId);
}
@VisibleForTesting
void setInterceptor(HttpResponseInterceptor interceptor) {
httpClient.setInterceptor(interceptor);
}
UserRecord getUserById(String uid) throws FirebaseAuthException {
final Map payload = ImmutableMap.of(
"localId", ImmutableList.of(uid));
return lookupUserAccount(payload, "user ID: " + uid);
}
UserRecord getUserByEmail(String email) throws FirebaseAuthException {
final Map payload = ImmutableMap.of(
"email", ImmutableList.of(email));
return lookupUserAccount(payload, "email: " + email);
}
UserRecord getUserByPhoneNumber(String phoneNumber) throws FirebaseAuthException {
final Map payload = ImmutableMap.of(
"phoneNumber", ImmutableList.of(phoneNumber));
return lookupUserAccount(payload, "phone number: " + phoneNumber);
}
Set getAccountInfo(@NonNull Collection identifiers)
throws FirebaseAuthException {
if (identifiers.isEmpty()) {
return new HashSet<>();
}
GetAccountInfoRequest payload = new GetAccountInfoRequest();
for (UserIdentifier id : identifiers) {
id.populate(payload);
}
GetAccountInfoResponse response = post(
"/accounts:lookup", payload, GetAccountInfoResponse.class);
Set results = new HashSet<>();
if (response.getUsers() != null) {
for (GetAccountInfoResponse.User user : response.getUsers()) {
results.add(new UserRecord(user, jsonFactory));
}
}
return results;
}
UserRecord getUserByProviderUid(
String providerId, String uid) throws FirebaseAuthException {
final Map payload = ImmutableMap.of(
"federatedUserId", ImmutableList.of(
ImmutableMap.builder()
.put("rawId", uid).put("providerId", providerId).build()));
return lookupUserAccount(payload, uid);
}
String createUser(UserRecord.CreateRequest request) throws FirebaseAuthException {
GenericJson response = post("/accounts", request.getProperties(), GenericJson.class);
return (String) response.get("localId");
}
void updateUser(UserRecord.UpdateRequest request, JsonFactory jsonFactory)
throws FirebaseAuthException {
post("/accounts:update", request.getProperties(jsonFactory), GenericJson.class);
}
void deleteUser(String uid) throws FirebaseAuthException {
final Map payload = ImmutableMap.of("localId", uid);
post("/accounts:delete", payload, GenericJson.class);
}
DeleteUsersResult deleteUsers(@NonNull List uids) throws FirebaseAuthException {
final Map payload = ImmutableMap.of(
"localIds", uids,
"force", true);
BatchDeleteResponse response = post(
"/accounts:batchDelete", payload, BatchDeleteResponse.class);
return new DeleteUsersResult(uids.size(), response);
}
DownloadAccountResponse listUsers(int maxResults, String pageToken) throws FirebaseAuthException {
ImmutableMap.Builder builder = ImmutableMap.builder()
.put("maxResults", maxResults);
if (pageToken != null) {
checkArgument(!pageToken.equals(ListUsersPage.END_OF_LIST), "invalid end of list page token");
builder.put("nextPageToken", pageToken);
}
String url = userMgtBaseUrl + "/accounts:batchGet";
HttpRequestInfo requestInfo = HttpRequestInfo.buildGetRequest(url)
.addAllParameters(builder.build());
return httpClient.sendRequest(requestInfo, DownloadAccountResponse.class);
}
UserImportResult importUsers(UserImportRequest request) throws FirebaseAuthException {
checkNotNull(request);
UploadAccountResponse response = post(
"/accounts:batchCreate", request, UploadAccountResponse.class);
return new UserImportResult(request.getUsersCount(), response);
}
String createSessionCookie(String idToken,
SessionCookieOptions options) throws FirebaseAuthException {
final Map payload = ImmutableMap.of(
"idToken", idToken, "validDuration", options.getExpiresInSeconds());
GenericJson response = post(":createSessionCookie", payload, GenericJson.class);
return (String) response.get("sessionCookie");
}
String getEmailActionLink(EmailLinkType type, String email,
@Nullable ActionCodeSettings settings) throws FirebaseAuthException {
ImmutableMap.Builder payload = ImmutableMap.builder()
.put("requestType", type.name())
.put("email", email)
.put("returnOobLink", true);
if (settings != null) {
payload.putAll(settings.getProperties());
}
GenericJson response = post("/accounts:sendOobCode", payload.build(), GenericJson.class);
return (String) response.get("oobLink");
}
private UserRecord lookupUserAccount(
Map payload, String identifier) throws FirebaseAuthException {
HttpRequestInfo requestInfo = HttpRequestInfo.buildJsonPostRequest(
userMgtBaseUrl + "/accounts:lookup", payload);
IncomingHttpResponse response = httpClient.sendRequest(requestInfo);
GetAccountInfoResponse parsed = httpClient.parse(response, GetAccountInfoResponse.class);
if (parsed.getUsers() == null || parsed.getUsers().isEmpty()) {
throw new FirebaseAuthException(ErrorCode.NOT_FOUND,
"No user record found for the provided " + identifier,
null,
response,
AuthErrorCode.USER_NOT_FOUND);
}
return new UserRecord(parsed.getUsers().get(0), jsonFactory);
}
OidcProviderConfig createOidcProviderConfig(
OidcProviderConfig.CreateRequest request) throws FirebaseAuthException {
String url = idpConfigMgtBaseUrl + "/oauthIdpConfigs";
HttpRequestInfo requestInfo = HttpRequestInfo.buildJsonPostRequest(url, request.getProperties())
.addParameter("oauthIdpConfigId", request.getProviderId());
return httpClient.sendRequest(requestInfo, OidcProviderConfig.class);
}
SamlProviderConfig createSamlProviderConfig(
SamlProviderConfig.CreateRequest request) throws FirebaseAuthException {
String url = idpConfigMgtBaseUrl + "/inboundSamlConfigs";
HttpRequestInfo requestInfo = HttpRequestInfo.buildJsonPostRequest(url, request.getProperties())
.addParameter("inboundSamlConfigId", request.getProviderId());
return httpClient.sendRequest(requestInfo, SamlProviderConfig.class);
}
OidcProviderConfig updateOidcProviderConfig(OidcProviderConfig.UpdateRequest request)
throws FirebaseAuthException {
Map properties = request.getProperties();
String url = idpConfigMgtBaseUrl + getOidcUrlSuffix(request.getProviderId());
HttpRequestInfo requestInfo = HttpRequestInfo.buildJsonPatchRequest(url, properties)
.addParameter("updateMask", Joiner.on(",").join(AuthHttpClient.generateMask(properties)));
return httpClient.sendRequest(requestInfo, OidcProviderConfig.class);
}
SamlProviderConfig updateSamlProviderConfig(SamlProviderConfig.UpdateRequest request)
throws FirebaseAuthException {
Map properties = request.getProperties();
String url = idpConfigMgtBaseUrl + getSamlUrlSuffix(request.getProviderId());
HttpRequestInfo requestInfo = HttpRequestInfo.buildJsonPatchRequest(url, properties)
.addParameter("updateMask", Joiner.on(",").join(AuthHttpClient.generateMask(properties)));
return httpClient.sendRequest(requestInfo, SamlProviderConfig.class);
}
OidcProviderConfig getOidcProviderConfig(String providerId) throws FirebaseAuthException {
String url = idpConfigMgtBaseUrl + getOidcUrlSuffix(providerId);
return httpClient.sendRequest(HttpRequestInfo.buildGetRequest(url), OidcProviderConfig.class);
}
SamlProviderConfig getSamlProviderConfig(String providerId) throws FirebaseAuthException {
String url = idpConfigMgtBaseUrl + getSamlUrlSuffix(providerId);
return httpClient.sendRequest(HttpRequestInfo.buildGetRequest(url), SamlProviderConfig.class);
}
ListOidcProviderConfigsResponse listOidcProviderConfigs(int maxResults, String pageToken)
throws FirebaseAuthException {
ImmutableMap.Builder builder =
ImmutableMap.builder().put("pageSize", maxResults);
if (pageToken != null) {
checkArgument(!pageToken.equals(
ListProviderConfigsPage.END_OF_LIST), "Invalid end of list page token.");
builder.put("nextPageToken", pageToken);
}
String url = idpConfigMgtBaseUrl + "/oauthIdpConfigs";
HttpRequestInfo requestInfo = HttpRequestInfo.buildGetRequest(url)
.addAllParameters(builder.build());
return httpClient.sendRequest(requestInfo, ListOidcProviderConfigsResponse.class);
}
ListSamlProviderConfigsResponse listSamlProviderConfigs(int maxResults, String pageToken)
throws FirebaseAuthException {
ImmutableMap.Builder builder =
ImmutableMap.builder().put("pageSize", maxResults);
if (pageToken != null) {
checkArgument(!pageToken.equals(
ListProviderConfigsPage.END_OF_LIST), "Invalid end of list page token.");
builder.put("nextPageToken", pageToken);
}
String url = idpConfigMgtBaseUrl + "/inboundSamlConfigs";
HttpRequestInfo requestInfo = HttpRequestInfo.buildGetRequest(url)
.addAllParameters(builder.build());
return httpClient.sendRequest(requestInfo, ListSamlProviderConfigsResponse.class);
}
void deleteOidcProviderConfig(String providerId) throws FirebaseAuthException {
String url = idpConfigMgtBaseUrl + getOidcUrlSuffix(providerId);
httpClient.sendRequest(HttpRequestInfo.buildDeleteRequest(url));
}
void deleteSamlProviderConfig(String providerId) throws FirebaseAuthException {
String url = idpConfigMgtBaseUrl + getSamlUrlSuffix(providerId);
httpClient.sendRequest(HttpRequestInfo.buildDeleteRequest(url));
}
private static String getOidcUrlSuffix(String providerId) {
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
return "/oauthIdpConfigs/" + providerId;
}
private static String getSamlUrlSuffix(String providerId) {
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
return "/inboundSamlConfigs/" + providerId;
}
private T post(String path, Object content, Class clazz) throws FirebaseAuthException {
checkArgument(!Strings.isNullOrEmpty(path), "path must not be null or empty");
checkNotNull(content, "content must not be null for POST requests");
String url = userMgtBaseUrl + path;
return httpClient.sendRequest(HttpRequestInfo.buildJsonPostRequest(url, content), clazz);
}
static class UserImportRequest extends GenericJson {
@Key("users")
private final List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy