Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multi-tenant authentication #1331

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/app_resources/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ android {
}
}
}
lintOptions {
abortOnError false
}
}

dependencies {
Expand Down
3 changes: 3 additions & 0 deletions app/google_api_resources/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ android {
}
}
}
lintOptions {
abortOnError false
}
}

dependencies {
Expand Down
3 changes: 3 additions & 0 deletions app/invites_resources/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ android {
}
}
}
lintOptions {
abortOnError false
}
}

dependencies {
Expand Down
3 changes: 3 additions & 0 deletions app_check/app_check_resources/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ android {
}
}
}
lintOptions {
abortOnError false
}
}

dependencies {
Expand Down
32 changes: 32 additions & 0 deletions auth/src/android/auth_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ using util::JniStringToString;
"()Ljava/lang/String;"), \
X(SetLanguageCode, "setLanguageCode", \
"(Ljava/lang/String;)V"), \
X(GetTenantId, "getTenantId", \
"()Ljava/lang/String;"), \
X(SetTenantId, "setTenantId", \
"(Ljava/lang/String;)V"), \
X(UseAppLanguage, "useAppLanguage", "()V"), \
X(AddAuthStateListener, "addAuthStateListener", \
"(Lcom/google/firebase/auth/FirebaseAuth$AuthStateListener;)V"), \
Expand Down Expand Up @@ -756,6 +760,34 @@ void Auth::set_language_code(const char* language_code) {
}
}

std::string Auth::tenant_id() const {
if (!auth_data_) return nullptr;
JNIEnv* env = Env(auth_data_);
jobject j_pending_result = env->CallObjectMethod(
AuthImpl(auth_data_), auth::GetMethodId(auth::kGetTenantId));
if (firebase::util::CheckAndClearJniExceptions(env) ||
j_pending_result == nullptr) {
return nullptr;
}
return util::JniStringToString(env, j_pending_result);
}

void Auth::set_tenant_id(const char* tenant_id) {
if (!auth_data_) return;
JNIEnv* env = Env(auth_data_);
jstring j_tenant_id = nullptr;
if (tenant_id != nullptr) {
j_tenant_id = env->NewStringUTF(tenant_id);
}
env->CallVoidMethod(AuthImpl(auth_data_),
auth::GetMethodId(auth::kSetTenantId),
j_tenant_id);
firebase::util::CheckAndClearJniExceptions(env);
if (j_tenant_id != nullptr) {
env->DeleteLocalRef(j_tenant_id);
}
}

void Auth::UseAppLanguage() {
if (!auth_data_) return;
JNIEnv* env = Env(auth_data_);
Expand Down
41 changes: 32 additions & 9 deletions auth/src/desktop/auth_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ Future<AuthResult> Auth::SignInWithCustomToken(const char* custom_token) {
// Note: std::make_unique is not supported by Visual Studio 2012, which is
// among our target compilers.
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), custom_token));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_),
custom_token, GetTenantId(*auth_data_)));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow<VerifyCustomTokenResponse>);
Expand All @@ -391,7 +392,7 @@ Future<User*> Auth::SignInWithCustomToken_DEPRECATED(
// Note: std::make_unique is not supported by Visual Studio 2012, which is
// among our target compilers.
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), custom_token));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), custom_token, nullptr));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow_DEPRECATED<VerifyCustomTokenResponse>);
Expand Down Expand Up @@ -468,7 +469,8 @@ Future<AuthResult> Auth::SignInAnonymously() {

typedef SignUpNewUserRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_)));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_),
nullptr, nullptr, nullptr, GetTenantId(*auth_data_)));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow<SignUpNewUserResponse>);
Expand All @@ -493,7 +495,8 @@ Future<User*> Auth::SignInAnonymously_DEPRECATED() {

typedef SignUpNewUserRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_)));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_),
GetTenantId(*auth_data_)));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow_DEPRECATED<SignUpNewUserResponse>);
Expand All @@ -509,7 +512,8 @@ Future<AuthResult> Auth::SignInWithEmailAndPassword(

typedef VerifyPasswordRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), email, password));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_),
email, password, GetTenantId(*auth_data_)));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow<VerifyPasswordResponse>);
Expand All @@ -525,7 +529,8 @@ Future<User*> Auth::SignInWithEmailAndPassword_DEPRECATED(

typedef VerifyPasswordRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), email, password));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_),
email, password, nullptr));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow_DEPRECATED<VerifyPasswordResponse>);
Expand All @@ -542,7 +547,7 @@ Future<AuthResult> Auth::CreateUserWithEmailAndPassword(
typedef SignUpNewUserRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), email, password,
""));
"", GetTenantId(*auth_data_)));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow<SignUpNewUserResponse>);
Expand All @@ -559,7 +564,7 @@ Future<User*> Auth::CreateUserWithEmailAndPassword_DEPRECATED(
typedef SignUpNewUserRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), email, password,
""));
"", nullptr));

return CallAsync(auth_data_, promise, std::move(request),
PerformSignInFlow_DEPRECATED<SignUpNewUserResponse>);
Expand Down Expand Up @@ -592,7 +597,8 @@ Future<Auth::FetchProvidersResult> Auth::FetchProvidersForEmail(

typedef CreateAuthUriRequest RequestT;
auto request = std::unique_ptr<RequestT>( // NOLINT
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), email));
new RequestT(*auth_data_->app, GetApiKey(*auth_data_), email,
GetTenantId(*auth_data_)));

const auto callback =
[](AuthDataHandle<FetchProvidersResult, RequestT>* handle) {
Expand Down Expand Up @@ -709,6 +715,23 @@ void Auth::set_language_code(const char* language_code) {
auth_impl->language_code = code;
}

void Auth::set_tenant_id(const char* tenant_id) {
if (!auth_data_) return;

auto auth_impl = static_cast<AuthImpl*>(auth_data_->auth_impl);
std::string code;
if (tenant_id != nullptr) {
code.assign(tenant_id);
}
auth_impl->tenant_id = code;
}

std::string Auth::tenant_id() const {
if (!auth_data_) return nullptr;
auto auth_impl = static_cast<AuthImpl*>(auth_data_->auth_impl);
return auth_impl->tenant_id;
}

void Auth::UseAppLanguage() {
if (!auth_data_) return;
auto auth_impl = static_cast<AuthImpl*>(auth_data_->auth_impl);
Expand Down
3 changes: 3 additions & 0 deletions auth/src/desktop/auth_desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ struct AuthImpl {
// The current user language code. This can be set to the app’s current
// language by calling SetLanguageCode.
std::string language_code;

// The tenant id used for multi tenant authentication
std::string tenant_id;
};

// Constant, describing how often we automatically fetch a new auth token.
Expand Down
5 changes: 3 additions & 2 deletions auth/src/desktop/auth_providers/facebook_auth_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ class FacebookAuthCredential : public IdentityProviderCredential {
std::string GetProvider() const override { return kFacebookAuthProviderId; }

std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* const api_key) const override {
::firebase::App& app, const char* const api_key,
char const* tenant_id) const override {
return VerifyAssertionRequest::FromAccessToken(
app, api_key, GetProvider().c_str(), access_token_.c_str());
app, api_key, GetProvider().c_str(), access_token_.c_str(), tenant_id);
}

private:
Expand Down
5 changes: 3 additions & 2 deletions auth/src/desktop/auth_providers/github_auth_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ class GitHubAuthCredential : public IdentityProviderCredential {
std::string GetProvider() const override { return kGitHubAuthProviderId; }

std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* const api_key) const override {
::firebase::App& app, const char* const api_key,
const char* tenant_id) const override {
return VerifyAssertionRequest::FromAccessToken(
app, api_key, GetProvider().c_str(), token_.c_str());
app, api_key, GetProvider().c_str(), token_.c_str(), tenant_id);
}

private:
Expand Down
7 changes: 4 additions & 3 deletions auth/src/desktop/auth_providers/google_auth_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ class GoogleAuthCredential : public IdentityProviderCredential {
std::string GetProvider() const override { return kGoogleAuthProviderId; }

std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* const api_key) const override {
::firebase::App& app, const char* const api_key,
const char* tenant_id) const override {
if (!id_token_.empty()) {
return VerifyAssertionRequest::FromIdToken(
app, api_key, GetProvider().c_str(), id_token_.c_str());
app, api_key, GetProvider().c_str(), id_token_.c_str(), tenant_id);
} else {
return VerifyAssertionRequest::FromAccessToken(
app, api_key, GetProvider().c_str(), access_token_.c_str());
app, api_key, GetProvider().c_str(), access_token_.c_str(), tenant_id);
}
}

Expand Down
9 changes: 6 additions & 3 deletions auth/src/desktop/auth_providers/oauth_auth_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ class OAuthCredential : public IdentityProviderCredential {
std::string GetProvider() const override { return provider_id_; }

std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* const api_key) const override {
::firebase::App& app, const char* const api_key,
const char* tenant_id) const override {
const char* raw_nonce =
(!raw_nonce_.empty()) ? raw_nonce_.c_str() : nullptr;
if (!id_token_.empty()) {
return VerifyAssertionRequest::FromIdToken(
app, api_key, provider_id_.c_str(), id_token_.c_str(), raw_nonce);
app, api_key, provider_id_.c_str(), id_token_.c_str(), raw_nonce,
tenant_id);
} else {
return VerifyAssertionRequest::FromAccessToken(
app, api_key, provider_id_.c_str(), access_token_.c_str(), raw_nonce);
app, api_key, provider_id_.c_str(), access_token_.c_str(), raw_nonce,
tenant_id);
}
}

Expand Down
4 changes: 2 additions & 2 deletions auth/src/desktop/auth_providers/playgames_auth_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class PlayGamesAuthCredential : public IdentityProviderCredential {
std::string GetProvider() const override { return kPlayGamesAuthProviderId; }

std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* const api_key) const override {
::firebase::App& app, const char* const api_key, const char* tenant_id) const override {
return VerifyAssertionRequest::FromAuthCode(
app, api_key, GetProvider().c_str(), server_auth_code_.c_str());
app, api_key, GetProvider().c_str(), server_auth_code_.c_str(), tenant_id);
}

private:
Expand Down
6 changes: 4 additions & 2 deletions auth/src/desktop/auth_providers/twitter_auth_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ class TwitterAuthCredential : public IdentityProviderCredential {
std::string GetProvider() const override { return kTwitterAuthProviderId; }

std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* const api_key) const override {
::firebase::App& app, const char* const api_key,
const char* tenant_id) const override {
return VerifyAssertionRequest::FromAccessTokenAndOAuthSecret(
app, api_key, GetProvider().c_str(), token_.c_str(), secret_.c_str());
app, api_key, GetProvider().c_str(), token_.c_str(), secret_.c_str(),
tenant_id);
}

private:
Expand Down
9 changes: 9 additions & 0 deletions auth/src/desktop/auth_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ const char* GetApiKey(const AuthData& auth_data) {
return static_cast<const AuthImpl*>(auth_data.auth_impl)->api_key.c_str();
}

const char* GetTenantId(const AuthData& auth_data){
FIREBASE_ASSERT_RETURN(nullptr, auth_data.auth_impl);
auto auth_impl = static_cast<AuthImpl*>(auth_data.auth_impl);
if (auth_impl->tenant_id.empty()){
return auth_impl->tenant_id.c_str();
}
return nullptr;
}

void CompletePromise(Promise<User*>* const promise,
const SignInResult& sign_in_result) {
FIREBASE_ASSERT_RETURN_VOID(promise);
Expand Down
3 changes: 3 additions & 0 deletions auth/src/desktop/auth_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ using firebase::callback::NewCallback;

const char* GetApiKey(const AuthData& auth_data);

const char* GetTenantId(const AuthData& auth_data);


/// @deprecated
// Completes the given promise by translating the AuthenticationResult. If the
// AuthenticationResult is successful, promise will be completed successfully
Expand Down
6 changes: 4 additions & 2 deletions auth/src/desktop/credential_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
const auto* idp_credential = static_cast<const IdentityProviderCredential*>(
credential_impl->auth_credential.get());
return idp_credential->CreateVerifyAssertionRequest(*auth_data.app,
GetApiKey(auth_data));
GetApiKey(auth_data),
GetTenantId(auth_data));
}

std::unique_ptr<rest::Request> CreateRequestFromCredential(
Expand All @@ -48,7 +49,8 @@ std::unique_ptr<rest::Request> CreateRequestFromCredential(
return std::unique_ptr<rest::Request>( // NOLINT
new VerifyPasswordRequest(*auth_data->app, GetApiKey(*auth_data),
email_credential->GetEmail().c_str(),
email_credential->GetPassword().c_str()));
email_credential->GetPassword().c_str(),
GetTenantId(*auth_data)));
}

return CreateVerifyAssertionRequest(*auth_data, raw_credential);
Expand Down
2 changes: 1 addition & 1 deletion auth/src/desktop/identity_provider_credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace auth {
class IdentityProviderCredential : public AuthCredential {
public:
virtual std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
::firebase::App& app, const char* api_key) const = 0;
::firebase::App& app, const char* api_key, const char* tenant_id) const = 0;
};

} // namespace auth
Expand Down
7 changes: 6 additions & 1 deletion auth/src/desktop/rpcs/create_auth_uri_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ namespace auth {

CreateAuthUriRequest::CreateAuthUriRequest(::firebase::App& app,
const char* api_key,
const char* identifier)
const char* identifier,
const char* tenant_id)
: AuthRequest(app, request_resource_data, true) {
FIREBASE_ASSERT_RETURN_VOID(api_key);

Expand All @@ -42,6 +43,10 @@ CreateAuthUriRequest::CreateAuthUriRequest(::firebase::App& app,
LogError("No identifier given.");
}

if (tenant_id != nullptr){
application_data_->tenantId = tenant_id;
}

// This parameter is only relevant for the web SDK; for desktop, it can have
// any value as long as it passes the backend validation for a valid URL.
application_data_->continueUri = "http://localhost";
Expand Down
2 changes: 1 addition & 1 deletion auth/src/desktop/rpcs/create_auth_uri_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace auth {
class CreateAuthUriRequest : public AuthRequest {
public:
CreateAuthUriRequest(::firebase::App& app, const char* api_key,
const char* identifier);
const char* identifier, const char* tenant_id);
};

} // namespace auth
Expand Down
Loading