Skip to content

Commit 2c6bf1e

Browse files
Googlera-maurice
authored andcommitted
Adding an overloaded GetCredential member function to OAuthProvider which takes a nonce, and an optional access token, closing the parity game between our OAuthProvider implementation and those of the phone SDKs.
This also opens up the use of our C++ and Unity SDK to do Apple provider signin which requires a nonce when constructing the credential. PiperOrigin-RevId: 286431312
1 parent af1e034 commit 2c6bf1e

File tree

8 files changed

+193
-17
lines changed

8 files changed

+193
-17
lines changed

auth/src/android/credential_android.cc

Lines changed: 114 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,12 @@ METHOD_LOOKUP_DEFINITION(twittercred,
124124
X(NewBuilder, "newBuilder", \
125125
"(Ljava/lang/String;Lcom/google/firebase/auth/FirebaseAuth;)" \
126126
"Lcom/google/firebase/auth/OAuthProvider$Builder;", \
127+
util::kMethodTypeStatic), \
128+
X(NewCredentialBuilder, "newCredentialBuilder", \
129+
"(Ljava/lang/String;)" \
130+
"Lcom/google/firebase/auth/OAuthProvider$CredentialBuilder;", \
127131
util::kMethodTypeStatic)
132+
128133
// clang-format on
129134
METHOD_LOOKUP_DECLARATION(oauthprovider, OAUTHPROVIDER_METHODS)
130135
METHOD_LOOKUP_DEFINITION(oauthprovider,
@@ -180,6 +185,29 @@ METHOD_LOOKUP_DEFINITION(oauthprovider_builder,
180185
PROGUARD_KEEP_CLASS
181186
"com/google/firebase/auth/OAuthProvider$Builder",
182187
OAUTHPROVIDER_BUILDER_METHODS)
188+
189+
// clang-format off
190+
#define OAUTHPROVIDER_CREDENTIALBUILDER_METHODS(X) \
191+
X(SetAccessToken, "setAccessToken", \
192+
"(Ljava/lang/String;)" \
193+
"Lcom/google/firebase/auth/OAuthProvider$CredentialBuilder;"), \
194+
X(SetIdToken, "setIdToken", \
195+
"(Ljava/lang/String;)" \
196+
"Lcom/google/firebase/auth/OAuthProvider$CredentialBuilder;"), \
197+
X(SetIdTokenWithRawNonce, "setIdTokenWithRawNonce", \
198+
"(Ljava/lang/String;Ljava/lang/String;)" \
199+
"Lcom/google/firebase/auth/OAuthProvider$CredentialBuilder;"), \
200+
X(Build, "build", "()Lcom/google/firebase/auth/AuthCredential;")
201+
// clang-format on
202+
203+
METHOD_LOOKUP_DECLARATION(oauthprovider_credentialbuilder,
204+
OAUTHPROVIDER_CREDENTIALBUILDER_METHODS)
205+
METHOD_LOOKUP_DEFINITION(
206+
oauthprovider_credentialbuilder,
207+
PROGUARD_KEEP_CLASS
208+
"com/google/firebase/auth/OAuthProvider$CredentialBuilder",
209+
OAUTHPROVIDER_CREDENTIALBUILDER_METHODS)
210+
183211
// clang-format off
184212
#define AUTH_IDP_METHODS(X) \
185213
X(StartActivityForSignInWithProvider, "startActivityForSignInWithProvider", \
@@ -275,19 +303,21 @@ bool CacheCredentialMethodIds(
275303
return false;
276304
}
277305

278-
g_methods_cached = credential::CacheMethodIds(env, activity) &&
279-
emailcred::CacheMethodIds(env, activity) &&
280-
facebookcred::CacheMethodIds(env, activity) &&
281-
githubcred::CacheMethodIds(env, activity) &&
282-
googlecred::CacheMethodIds(env, activity) &&
283-
oauthprovider::CacheMethodIds(env, activity) &&
284-
oauthprovider_builder::CacheMethodIds(env, activity) &&
285-
auth_idp::CacheMethodIds(env, activity) &&
286-
user_idp::CacheMethodIds(env, activity) &&
287-
phonecred::CacheMethodIds(env, activity) &&
288-
timeunit::CacheFieldIds(env, activity) &&
289-
playgamescred::CacheMethodIds(env, activity) &&
290-
twittercred::CacheMethodIds(env, activity);
306+
g_methods_cached =
307+
credential::CacheMethodIds(env, activity) &&
308+
emailcred::CacheMethodIds(env, activity) &&
309+
facebookcred::CacheMethodIds(env, activity) &&
310+
githubcred::CacheMethodIds(env, activity) &&
311+
googlecred::CacheMethodIds(env, activity) &&
312+
oauthprovider::CacheMethodIds(env, activity) &&
313+
oauthprovider_builder::CacheMethodIds(env, activity) &&
314+
oauthprovider_credentialbuilder::CacheMethodIds(env, activity) &&
315+
auth_idp::CacheMethodIds(env, activity) &&
316+
user_idp::CacheMethodIds(env, activity) &&
317+
phonecred::CacheMethodIds(env, activity) &&
318+
timeunit::CacheFieldIds(env, activity) &&
319+
playgamescred::CacheMethodIds(env, activity) &&
320+
twittercred::CacheMethodIds(env, activity);
291321

292322
return g_methods_cached;
293323
}
@@ -303,6 +333,7 @@ void ReleaseCredentialClasses(JNIEnv* env) {
303333
jniphone::ReleaseClass(env);
304334
oauthprovider::ReleaseClass(env);
305335
oauthprovider_builder::ReleaseClass(env);
336+
oauthprovider_credentialbuilder::ReleaseClass(env);
306337
phonecred::ReleaseClass(env);
307338
timeunit::ReleaseClass(env);
308339
twittercred::ReleaseClass(env);
@@ -549,6 +580,76 @@ Credential OAuthProvider::GetCredential(const char* provider_id,
549580
return Credential(CredentialLocalToGlobalRef(j_cred));
550581
}
551582

583+
584+
// static
585+
Credential OAuthProvider::GetCredential(const char* provider_id,
586+
const char* id_token,
587+
const char* raw_nonce,
588+
const char* access_token) {
589+
FIREBASE_ASSERT_RETURN(Credential(),
590+
provider_id && id_token && raw_nonce );
591+
FIREBASE_ASSERT_MESSAGE_RETURN(Credential(), g_methods_cached,
592+
kMethodsNotCachedError);
593+
594+
JNIEnv* env = GetJniEnv();
595+
jstring j_provider_id = env->NewStringUTF(provider_id);
596+
jstring j_id_token = env->NewStringUTF(id_token);
597+
jstring j_raw_nonce = env->NewStringUTF(raw_nonce);
598+
599+
jobject j_cred_builder = env->CallStaticObjectMethod(
600+
oauthprovider::GetClass(),
601+
oauthprovider::GetMethodId(oauthprovider::kNewCredentialBuilder),
602+
j_provider_id);
603+
604+
jobject j_cred = nullptr;
605+
if (!firebase::util::CheckAndClearJniExceptions(env)) {
606+
jobject builder_return_ref = env->CallObjectMethod(
607+
j_cred_builder,
608+
oauthprovider_credentialbuilder::GetMethodId(
609+
oauthprovider_credentialbuilder::kSetIdTokenWithRawNonce),
610+
j_id_token, j_raw_nonce);
611+
612+
if (!firebase::util::CheckAndClearJniExceptions(env)) {
613+
env->DeleteLocalRef(builder_return_ref);
614+
// add the access token, if it exists.
615+
if (access_token != nullptr) {
616+
jobject j_access_token = env->NewStringUTF(access_token);
617+
builder_return_ref = env->CallObjectMethod(
618+
j_cred_builder,
619+
oauthprovider_credentialbuilder::GetMethodId(
620+
oauthprovider_credentialbuilder::kSetAccessToken),
621+
j_access_token);
622+
623+
env->DeleteLocalRef(j_access_token);
624+
if (!firebase::util::CheckAndClearJniExceptions(env)) {
625+
env->DeleteLocalRef(builder_return_ref);
626+
} else {
627+
env->DeleteLocalRef(j_cred_builder);
628+
j_cred_builder = nullptr;
629+
}
630+
}
631+
}
632+
633+
// If we have a valid credential builder, build a credential.
634+
if (j_cred_builder != nullptr) {
635+
j_cred = env->CallObjectMethod(
636+
j_cred_builder, oauthprovider_credentialbuilder::GetMethodId(
637+
oauthprovider_credentialbuilder::kBuild));
638+
if (firebase::util::CheckAndClearJniExceptions(env)) {
639+
j_cred = nullptr;
640+
}
641+
642+
env->DeleteLocalRef(j_cred_builder);
643+
}
644+
}
645+
646+
env->DeleteLocalRef(j_provider_id);
647+
env->DeleteLocalRef(j_raw_nonce);
648+
env->DeleteLocalRef(j_id_token);
649+
650+
return Credential(CredentialLocalToGlobalRef(j_cred));
651+
}
652+
552653
// static
553654
Future<Credential> GameCenterAuthProvider::GetCredential() {
554655
// Game Center is not available on Android

auth/src/desktop/auth_providers/oauth_auth_credential.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,28 @@ class OAuthCredential : public IdentityProviderCredential {
3232

3333
std::unique_ptr<VerifyAssertionRequest> CreateVerifyAssertionRequest(
3434
const char* const api_key) const override {
35+
const char* raw_nonce =
36+
(!raw_nonce_.empty()) ? raw_nonce_.c_str() : nullptr;
3537
if (!id_token_.empty()) {
3638
return VerifyAssertionRequest::FromIdToken(api_key, provider_id_.c_str(),
37-
id_token_.c_str());
39+
id_token_.c_str(), raw_nonce);
3840
} else {
3941
return VerifyAssertionRequest::FromAccessToken(
40-
api_key, provider_id_.c_str(), access_token_.c_str());
42+
api_key, provider_id_.c_str(), access_token_.c_str(), raw_nonce);
4143
}
4244
}
4345

4446
private:
4547
OAuthCredential(const std::string& provider_id, const std::string& id_token,
46-
const std::string& access_token)
48+
const std::string& raw_nonce, const std::string& access_token)
4749
: provider_id_(provider_id),
4850
id_token_(id_token),
51+
raw_nonce_(raw_nonce),
4952
access_token_(access_token) {}
5053

5154
const std::string provider_id_;
5255
const std::string id_token_;
56+
const std::string raw_nonce_;
5357
const std::string access_token_;
5458

5559
friend class OAuthProvider;

auth/src/desktop/auth_providers/oauth_auth_provider.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,21 @@ Credential OAuthProvider::GetCredential(const char* const provider_id,
2727
const char* const id_token,
2828
const char* const access_token) {
2929
FIREBASE_ASSERT_RETURN(Credential(), provider_id && id_token && access_token);
30+
return Credential{new CredentialImpl{new OAuthCredential{
31+
provider_id, id_token, /*raw_nonce=*/"", access_token}}};
32+
}
33+
34+
// static
35+
Credential OAuthProvider::GetCredential(const char* provider_id,
36+
const char* id_token,
37+
const char* raw_nonce,
38+
const char* access_token) {
39+
FIREBASE_ASSERT_RETURN(Credential(), provider_id && id_token && raw_nonce);
40+
if (access_token == nullptr) {
41+
access_token = "";
42+
}
3043
return Credential{new CredentialImpl{
31-
new OAuthCredential{provider_id, id_token, access_token}}};
44+
new OAuthCredential{provider_id, id_token, raw_nonce, access_token}}};
3245
}
3346

3447
} // namespace auth

auth/src/desktop/rpcs/request.fbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ table Request {
5555
photoUrl:string;
5656
deleteAttribute:[string];
5757
deleteProvider:[string];
58+
59+
nonce:string;
5860
}
5961

6062
root_type Request;

auth/src/desktop/rpcs/verify_assertion_request.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ VerifyAssertionRequest::VerifyAssertionRequest(const char* const api_key,
4545
std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromIdToken(
4646
const char* const api_key, const char* const provider_id,
4747
const char* const id_token) {
48+
return FromIdToken(api_key, provider_id, id_token, /*nonce=*/nullptr);
49+
}
50+
51+
std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromIdToken(
52+
const char* const api_key, const char* const provider_id,
53+
const char* const id_token, const char* nonce) {
4854
auto request = std::unique_ptr<VerifyAssertionRequest>( // NOLINT
4955
new VerifyAssertionRequest{api_key, provider_id});
5056

@@ -54,6 +60,10 @@ std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromIdToken(
5460
LogError("No id token given");
5561
}
5662

63+
if (nonce) {
64+
request->post_body_ += std::string{"&nonce="} + nonce;
65+
}
66+
5767
request->application_data_->postBody = request->post_body_;
5868
request->UpdatePostFields();
5969
return request;
@@ -62,6 +72,13 @@ std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromIdToken(
6272
std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromAccessToken(
6373
const char* const api_key, const char* const provider_id,
6474
const char* const access_token) {
75+
return FromAccessToken(api_key, provider_id, access_token,
76+
/*nonce=*/nullptr);
77+
}
78+
79+
std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromAccessToken(
80+
const char* const api_key, const char* const provider_id,
81+
const char* const access_token, const char* nonce) {
6582
auto request = std::unique_ptr<VerifyAssertionRequest>( // NOLINT
6683
new VerifyAssertionRequest{api_key, provider_id});
6784

@@ -71,6 +88,10 @@ std::unique_ptr<VerifyAssertionRequest> VerifyAssertionRequest::FromAccessToken(
7188
LogError("No access token given");
7289
}
7390

91+
if (nonce) {
92+
request->post_body_ += std::string{"&nonce="} + nonce;
93+
}
94+
7495
request->application_data_->postBody = request->post_body_;
7596
request->UpdatePostFields();
7697
return request;

auth/src/desktop/rpcs/verify_assertion_request.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@ class VerifyAssertionRequest : public AuthRequest {
3232
public:
3333
static std::unique_ptr<VerifyAssertionRequest> FromIdToken(
3434
const char* api_key, const char* provider_id, const char* id_token);
35+
static std::unique_ptr<VerifyAssertionRequest> FromIdToken(
36+
const char* api_key, const char* provider_id, const char* id_token,
37+
const char* nonce);
3538
static std::unique_ptr<VerifyAssertionRequest> FromAccessToken(
3639
const char* api_key, const char* provider_id, const char* access_token);
40+
static std::unique_ptr<VerifyAssertionRequest> FromAccessToken(
41+
const char* api_key, const char* provider_id, const char* access_token,
42+
const char* nonce);
3743
static std::unique_ptr<VerifyAssertionRequest> FromAccessTokenAndOAuthSecret(
3844
const char* api_key, const char* provider_id, const char* access_token,
3945
const char* oauth_secret);

auth/src/include/firebase/auth/credential.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ class OAuthProvider {
224224
/// from Android and iOS implementations).
225225
static Credential GetCredential(const char* provider_id, const char* id_token,
226226
const char* access_token);
227+
228+
/// Generate a credential for an OAuth2 provider.
229+
///
230+
/// @param provider_id Name of the OAuth2 provider.
231+
/// @param id_token The authentication token (OIDC only).
232+
/// @param raw_nonce The raw nonce associated with the Auth credential being
233+
/// created.
234+
/// @param access_token The access token associated with the Auth credential
235+
/// to be created, if available. This value may be null.
236+
static Credential GetCredential(const char* provider_id, const char* id_token,
237+
const char* raw_nonce,
238+
const char* access_token);
227239
};
228240

229241
/// @brief Use phone number text messages to authenticate.

auth/src/ios/credential_ios.mm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,23 @@ @implementation PhoneListenerDataObjC
144144
return Credential(new FIRAuthCredentialPointer(credential));
145145
}
146146

147+
// static
148+
Credential OAuthProvider::GetCredential(const char* provider_id,
149+
const char* id_token,
150+
const char* raw_nonce,
151+
const char* access_token) {
152+
FIREBASE_ASSERT_RETURN(Credential(), provider_id && id_token && raw_nonce);
153+
154+
NSString* access_token_string =
155+
(access_token != nullptr) ? util::CStringToNSString(access_token) : nullptr;
156+
FIRAuthCredential* credential =
157+
(FIRAuthCredential*)[FIROAuthProvider credentialWithProviderID:@(provider_id)
158+
IDToken:@(id_token)
159+
rawNonce:@(raw_nonce)
160+
accessToken:access_token_string];
161+
return Credential(new FIRAuthCredentialPointer(credential));
162+
}
163+
147164
// static
148165
Future<Credential> GameCenterAuthProvider::GetCredential() {
149166
auto future_api = GetCredentialFutureImpl();

0 commit comments

Comments
 (0)