func (c *baseClient) GetUserByPhoneNumber(ctx context.Context, phone string) (*UserRecord, error) {
	if err := validatePhone(phone); err != nil {
		return nil, err
	}
	return c.getUser(ctx, &userQuery{
		field: "phoneNumber",
		value: phone,
		label: "phone number",
	})
}
GetUserByPhoneNumber gets the user data corresponding to the specified user phone number.
package auth
import (
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
	"firebase.google.com/go/v4/internal"
)
const (
	maxLenPayloadCC     = 1000
	defaultProviderID   = "firebase"
	idToolkitV1Endpoint = "https://identitytoolkit.googleapis.com/v1"
	maxGetAccountsBatchSize = 100
	maxDeleteAccountsBatchSize = 1000
)
var b64Redacted = base64.StdEncoding.EncodeToString([]byte("REDACTED"))
type UserInfo struct {
	DisplayName string `json:"displayName,omitempty"`
	Email       string `json:"email,omitempty"`
	PhoneNumber string `json:"phoneNumber,omitempty"`
	PhotoURL    string `json:"photoUrl,omitempty"`
	ProviderID string `json:"providerId,omitempty"`
	UID        string `json:"rawId,omitempty"`
}
type multiFactorInfoResponse struct {
	MFAEnrollmentID string `json:"mfaEnrollmentId,omitempty"`
	DisplayName     string `json:"displayName,omitempty"`
	PhoneInfo       string `json:"phoneInfo,omitempty"`
	EnrolledAt      string `json:"enrolledAt,omitempty"`
}
type MultiFactorInfo struct {
	UID                 string
	DisplayName         string
	EnrollmentTimestamp int64
	FactorID            string
	PhoneNumber         string
}
type MultiFactorSettings struct {
	EnrolledFactors []*MultiFactorInfo
}
type UserMetadata struct {
	CreationTimestamp  int64
	LastLogInTimestamp int64
	LastRefreshTimestamp int64
}
type UserRecord struct {
	*UserInfo
	CustomClaims           map[string]interface{}
	Disabled               bool
	EmailVerified          bool
	ProviderUserInfo       []*UserInfo
	TokensValidAfterMillis int64  
	UserMetadata           *UserMetadata
	TenantID               string
	MultiFactor            *MultiFactorSettings
}
type UserToCreate struct {
	params map[string]interface{}
}
func (u *UserToCreate) Disabled(disabled bool) *UserToCreate {
	return u.set("disabled", disabled)
}
func (u *UserToCreate) DisplayName(name string) *UserToCreate {
	return u.set("displayName", name)
}
func (u *UserToCreate) Email(email string) *UserToCreate {
	return u.set("email", email)
}
func (u *UserToCreate) EmailVerified(verified bool) *UserToCreate {
	return u.set("emailVerified", verified)
}
func (u *UserToCreate) Password(pw string) *UserToCreate {
	return u.set("password", pw)
}
func (u *UserToCreate) PhoneNumber(phone string) *UserToCreate {
	return u.set("phoneNumber", phone)
}
func (u *UserToCreate) PhotoURL(url string) *UserToCreate {
	return u.set("photoUrl", url)
}
func (u *UserToCreate) UID(uid string) *UserToCreate {
	return u.set("localId", uid)
}
func (u *UserToCreate) set(key string, value interface{}) *UserToCreate {
	if u.params == nil {
		u.params = make(map[string]interface{})
	}
	u.params[key] = value
	return u
}
func (u *UserToCreate) validatedRequest() (map[string]interface{}, error) {
	req := make(map[string]interface{})
	for k, v := range u.params {
		req[k] = v
	}
	if uid, ok := req["localId"]; ok {
		if err := validateUID(uid.(string)); err != nil {
			return nil, err
		}
	}
	if name, ok := req["displayName"]; ok {
		if err := validateDisplayName(name.(string)); err != nil {
			return nil, err
		}
	}
	if email, ok := req["email"]; ok {
		if err := validateEmail(email.(string)); err != nil {
			return nil, err
		}
	}
	if phone, ok := req["phoneNumber"]; ok {
		if err := validatePhone(phone.(string)); err != nil {
			return nil, err
		}
	}
	if url, ok := req["photoUrl"]; ok {
		if err := validatePhotoURL(url.(string)); err != nil {
			return nil, err
		}
	}
	if pw, ok := req["password"]; ok {
		if err := validatePassword(pw.(string)); err != nil {
			return nil, err
		}
	}
	return req, nil
}
type UserToUpdate struct {
	params map[string]interface{}
}
func (u *UserToUpdate) CustomClaims(claims map[string]interface{}) *UserToUpdate {
	return u.set("customClaims", claims)
}
func (u *UserToUpdate) Disabled(disabled bool) *UserToUpdate {
	return u.set("disableUser", disabled)
}
func (u *UserToUpdate) DisplayName(name string) *UserToUpdate {
	return u.set("displayName", name)
}
func (u *UserToUpdate) Email(email string) *UserToUpdate {
	return u.set("email", email)
}
func (u *UserToUpdate) EmailVerified(verified bool) *UserToUpdate {
	return u.set("emailVerified", verified)
}
func (u *UserToUpdate) Password(pw string) *UserToUpdate {
	return u.set("password", pw)
}
func (u *UserToUpdate) PhoneNumber(phone string) *UserToUpdate {
	return u.set("phoneNumber", phone)
}
func (u *UserToUpdate) PhotoURL(url string) *UserToUpdate {
	return u.set("photoUrl", url)
}
func (u *UserToUpdate) ProviderToLink(userProvider *UserProvider) *UserToUpdate {
	return u.set("linkProviderUserInfo", userProvider)
}
func (u *UserToUpdate) ProvidersToDelete(providerIds []string) *UserToUpdate {
	if len(providerIds) == 0 {
		if u.params == nil {
			return u
		}
		if _, ok := u.params["providersToDelete"]; !ok {
			return u
		}
	}
	return u.set("providersToDelete", providerIds)
}
func (u *UserToUpdate) revokeRefreshTokens() *UserToUpdate {
	return u.set("validSince", strconv.FormatInt(time.Now().Unix(), 10))
}
func (u *UserToUpdate) set(key string, value interface{}) *UserToUpdate {
	if u.params == nil {
		u.params = make(map[string]interface{})
	}
	u.params[key] = value
	return u
}
func (u *UserToUpdate) validatedRequest() (map[string]interface{}, error) {
	if len(u.params) == 0 {
		return nil, fmt.Errorf("update parameters must not be nil or empty")
	}
	req := make(map[string]interface{})
	for k, v := range u.params {
		req[k] = v
	}
	if email, ok := req["email"]; ok {
		if err := validateEmail(email.(string)); err != nil {
			return nil, err
		}
	}
	handleDeletion := func(key, deleteKey, deleteVal string) {
		var deleteList []string
		list, ok := req[deleteKey]
		if ok {
			deleteList = list.([]string)
		}
		req[deleteKey] = append(deleteList, deleteVal)
		delete(req, key)
	}
	if name, ok := req["displayName"]; ok {
		if name == "" {
			handleDeletion("displayName", "deleteAttribute", "DISPLAY_NAME")
		} else if err := validateDisplayName(name.(string)); err != nil {
			return nil, err
		}
	}
	if url, ok := req["photoUrl"]; ok {
		if url == "" {
			handleDeletion("photoUrl", "deleteAttribute", "PHOTO_URL")
		} else if err := validatePhotoURL(url.(string)); err != nil {
			return nil, err
		}
	}
	if phone, ok := req["phoneNumber"]; ok {
		if phone == "" {
			handleDeletion("phoneNumber", "deleteProvider", "phone")
		} else if err := validatePhone(phone.(string)); err != nil {
			return nil, err
		}
	}
	if claims, ok := req["customClaims"]; ok {
		cc, err := marshalCustomClaims(claims.(map[string]interface{}))
		if err != nil {
			return nil, err
		}
		req["customAttributes"] = cc
		delete(req, "customClaims")
	}
	if pw, ok := req["password"]; ok {
		if err := validatePassword(pw.(string)); err != nil {
			return nil, err
		}
	}
	if linkProviderUserInfo, ok := req["linkProviderUserInfo"]; ok {
		userProvider := linkProviderUserInfo.(*UserProvider)
		if err := validateProviderUserInfo(userProvider); err != nil {
			return nil, err
		}
		if userProvider.ProviderID == "email" {
			if _, ok := req["email"]; ok {
				return nil, errors.New(
					"both UserToUpdate.Email and UserToUpdate.ProviderToLink.ProviderID='email' " +
						"were set; to link to the email/password provider, only specify the " +
						"UserToUpdate.Email field")
			}
			req["email"] = userProvider.UID
			delete(req, "linkProviderUserInfo")
		} else if userProvider.ProviderID == "phone" {
			if _, ok := req["phoneNumber"]; ok {
				return nil, errors.New(
					"both UserToUpdate.PhoneNumber and UserToUpdate.ProviderToLink.ProviderID='phone' " +
						"were set; to link to the phone provider, only specify the " +
						"UserToUpdate.PhoneNumber field")
			}
			req["phoneNumber"] = userProvider.UID
			delete(req, "linkProviderUserInfo")
		}
	}
	if providersToDelete, ok := req["providersToDelete"]; ok {
		var deleteProvider []string
		list, ok := req["deleteProvider"]
		if ok {
			deleteProvider = list.([]string)
		}
		for _, providerToDelete := range providersToDelete.([]string) {
			if providerToDelete == "" {
				return nil, errors.New("providersToDelete must not include empty strings")
			}
			if providerToDelete == "phone" {
				for _, prov := range deleteProvider {
					if prov == "phone" {
						return nil, errors.New("both UserToUpdate.PhoneNumber='' and " +
							"UserToUpdate.ProvidersToDelete=['phone'] were set; to unlink from a " +
							"phone provider, only specify the UserToUpdate.PhoneNumber='' field")
					}
				}
			}
			deleteProvider = append(deleteProvider, providerToDelete)
		}
		req["deleteProvider"] = deleteProvider
		delete(req, "providersToDelete")
	}
	return req, nil
}
func marshalCustomClaims(claims map[string]interface{}) (string, error) {
	for _, key := range reservedClaims {
		if _, ok := claims[key]; ok {
			return "", fmt.Errorf("claim %q is reserved and must not be set", key)
		}
	}
	b, err := json.Marshal(claims)
	if err != nil {
		return "", fmt.Errorf("custom claims marshaling error: %v", err)
	}
	s := string(b)
	if s == "null" {
		s = "{}"  
	}
	if len(s) > maxLenPayloadCC {
		return "", fmt.Errorf("serialized custom claims must not exceed %d characters", maxLenPayloadCC)
	}
	return s, nil
}
const (
	configurationNotFound    = "CONFIGURATION_NOT_FOUND"
	emailAlreadyExists       = "EMAIL_ALREADY_EXISTS"
	emailNotFound            = "EMAIL_NOT_FOUND"
	invalidDynamicLinkDomain = "INVALID_DYNAMIC_LINK_DOMAIN"
	phoneNumberAlreadyExists = "PHONE_NUMBER_ALREADY_EXISTS"
	tenantNotFound           = "TENANT_NOT_FOUND"
	uidAlreadyExists         = "UID_ALREADY_EXISTS"
	unauthorizedContinueURI  = "UNAUTHORIZED_CONTINUE_URI"
	userNotFound             = "USER_NOT_FOUND"
)
func IsConfigurationNotFound(err error) bool {
	return hasAuthErrorCode(err, configurationNotFound)
}
func IsEmailAlreadyExists(err error) bool {
	return hasAuthErrorCode(err, emailAlreadyExists)
}
func IsEmailNotFound(err error) bool {
	return hasAuthErrorCode(err, emailNotFound)
}
func IsInsufficientPermission(err error) bool {
	return false
}
func IsInvalidDynamicLinkDomain(err error) bool {
	return hasAuthErrorCode(err, invalidDynamicLinkDomain)
}
func IsInvalidEmail(err error) bool {
	return false
}
func IsPhoneNumberAlreadyExists(err error) bool {
	return hasAuthErrorCode(err, phoneNumberAlreadyExists)
}
func IsProjectNotFound(err error) bool {
	return false
}
func IsTenantNotFound(err error) bool {
	return hasAuthErrorCode(err, tenantNotFound)
}
func IsUIDAlreadyExists(err error) bool {
	return hasAuthErrorCode(err, uidAlreadyExists)
}
func IsUnauthorizedContinueURI(err error) bool {
	return hasAuthErrorCode(err, unauthorizedContinueURI)
}
func IsUnknown(err error) bool {
	return false
}
func IsUserNotFound(err error) bool {
	return hasAuthErrorCode(err, userNotFound)
}
func validateDisplayName(val string) error {
	if val == "" {
		return fmt.Errorf("display name must be a non-empty string")
	}
	return nil
}
func validatePhotoURL(val string) error {
	if val == "" {
		return fmt.Errorf("photo url must be a non-empty string")
	}
	return nil
}
func validateEmail(email string) error {
	if email == "" {
		return fmt.Errorf("email must be a non-empty string")
	}
	if parts := strings.Split(email, "@"); len(parts) != 2 || parts[0] == "" || parts[1] == "" {
		return fmt.Errorf("malformed email string: %q", email)
	}
	return nil
}
func validatePassword(val string) error {
	if len(val) < 6 {
		return fmt.Errorf("password must be a string at least 6 characters long")
	}
	return nil
}
func validateUID(uid string) error {
	if uid == "" {
		return fmt.Errorf("uid must be a non-empty string")
	}
	if len(uid) > 128 {
		return fmt.Errorf("uid string must not be longer than 128 characters")
	}
	return nil
}
func validatePhone(phone string) error {
	if phone == "" {
		return fmt.Errorf("phone number must be a non-empty string")
	}
	if !regexp.MustCompile(`\+.*[0-9A-Za-z]`).MatchString(phone) {
		return fmt.Errorf("phone number must be a valid, E.164 compliant identifier")
	}
	return nil
}
func validateProviderUserInfo(p *UserProvider) error {
	if p.UID == "" {
		return fmt.Errorf("user provider must specify a uid")
	}
	if p.ProviderID == "" {
		return fmt.Errorf("user provider must specify a provider ID")
	}
	return nil
}
func validateProvider(providerID string, providerUID string) error {
	if providerID == "" {
		return fmt.Errorf("providerID must be a non-empty string")
	} else if providerUID == "" {
		return fmt.Errorf("providerUID must be a non-empty string")
	}
	return nil
}
func (c *baseClient) GetUser(ctx context.Context, uid string) (*UserRecord, error) {
	return c.getUser(ctx, &userQuery{
		field: "localId",
		value: uid,
		label: "uid",
	})
}
func (c *baseClient) GetUserByEmail(ctx context.Context, email string) (*UserRecord, error) {
	if err := validateEmail(email); err != nil {
		return nil, err
	}
	return c.getUser(ctx, &userQuery{
		field: "email",
		value: email,
	})
}