Skip to content

Commit a8343ab

Browse files
authored
Merge pull request #9 from anotherdev/pk/feature-google-sign-in-on-hms
Feature: Google Sign-In on HMS
2 parents 8291c94 + 7143610 commit a8343ab

File tree

7 files changed

+131
-34
lines changed

7 files changed

+131
-34
lines changed

app/build.gradle

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ android {
55
def APP_NAME = "AuthRest"
66
def APP_TITLE = "Firebase Auth REST API"
77

8+
Properties properties = new Properties()
9+
def propertiesFile = file('../local.properties')
10+
if (propertiesFile.canRead()) {
11+
properties.load(new FileInputStream(propertiesFile))
12+
def KEYSTORE_FILE_KEY = "keystore.file"
13+
if (properties.containsKey(KEYSTORE_FILE_KEY)) {
14+
// Override debug keystore if one specified
15+
android.signingConfigs.debug.storeFile = file(properties[KEYSTORE_FILE_KEY])
16+
}
17+
}
18+
819
compileSdkVersion rootProject.ext.compileSdkVersion
920

1021
defaultConfig {
@@ -14,6 +25,12 @@ android {
1425
versionCode rootProject.ext.fullVersionCode
1526
versionName rootProject.ext.versionName
1627

28+
def GOOGLE_CLIENT_SECRET = "google.client.secret"
29+
if (!properties.containsKey(GOOGLE_CLIENT_SECRET)) {
30+
project.logger.log(LogLevel.ERROR, String.format("Can't find property: \"%s\" in the local.properties file", GOOGLE_CLIENT_SECRET))
31+
}
32+
buildConfigField("String", "GOOGLE_CLIENT_SECRET", properties[GOOGLE_CLIENT_SECRET])
33+
1734
resValue "string", "app_name", APP_NAME
1835
resValue "string", "app_title", APP_TITLE
1936

@@ -28,14 +45,6 @@ android {
2845
}
2946
}
3047

31-
Properties properties = new Properties()
32-
def propertiesFile = file('../local.properties')
33-
if (propertiesFile.canRead()) {
34-
properties.load(new FileInputStream(propertiesFile))
35-
if (properties != null && properties.containsKey('keystore.file')) {
36-
android.signingConfigs.debug.storeFile = file(properties['keystore.file'])
37-
}
38-
}
3948
project.logger.lifecycle('android.signingConfigs.debug.storeFile: ' + android.signingConfigs.debug.storeFile)
4049

4150
buildTypes {
@@ -75,9 +84,9 @@ dependencies {
7584

7685
implementation "com.github.HITGIF:TextFieldBoxes:1.4.5"
7786

78-
implementation "com.google.android.gms:play-services-auth:18.0.0"
87+
implementation "com.google.android.gms:play-services-auth:18.1.0"
7988

80-
implementation "com.google.android.material:material:1.1.0"
89+
implementation "com.google.android.material:material:1.2.1"
8190

8291
implementation platform("com.google.firebase:firebase-bom:$firebaseBomVersion")
8392
implementation "com.google.firebase:firebase-analytics"
@@ -92,6 +101,8 @@ dependencies {
92101
implementation "io.reactivex.rxjava2:rxjava:2.2.19"
93102
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
94103

104+
implementation "net.openid:appauth:0.7.1"
105+
95106
testImplementation "junit:junit:$junitVersion"
96107
androidTestImplementation "androidx.test.ext:junit:$androidxTestJunitVersion"
97108
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxTestEspressoVersion"

app/src/main/AndroidManifest.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
34
package="com.anotherdev.sample.firebase.auth">
45

56
<application
@@ -28,6 +29,19 @@
2829

2930
<activity android:name="com.anotherdev.sample.firebase.auth.MainActivity" />
3031

32+
<activity
33+
android:name="net.openid.appauth.RedirectUriReceiverActivity"
34+
tools:node="replace">
35+
<intent-filter>
36+
<action android:name="android.intent.action.VIEW" />
37+
<category android:name="android.intent.category.DEFAULT" />
38+
<category android:name="android.intent.category.BROWSABLE" />
39+
<data android:scheme="@string/auth_google_scheme"
40+
android:host="@string/auth_google_host"
41+
android:path="@string/auth_google_path" />
42+
</intent-filter>
43+
</activity>
44+
3145
</application>
3246

3347
</manifest>

app/src/main/java/com/anotherdev/sample/firebase/auth/LoginActivity.java

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.content.Intent;
44
import android.content.pm.ApplicationInfo;
5+
import android.net.Uri;
56
import android.os.Bundle;
67
import android.util.Log;
78
import android.view.Menu;
@@ -37,15 +38,26 @@
3738
import com.facebook.login.widget.LoginButton;
3839
import com.github.florent37.inlineactivityresult.rx.RxInlineActivityResult;
3940
import com.google.android.gms.auth.api.signin.GoogleSignIn;
41+
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
4042
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
4143
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
44+
import com.google.android.gms.common.ConnectionResult;
45+
import com.google.android.gms.common.GoogleApiAvailability;
4246
import com.google.firebase.FirebaseApp;
4347
import com.yarolegovich.lovelydialog.LovelyTextInputDialog;
4448

49+
import net.openid.appauth.AuthorizationRequest;
50+
import net.openid.appauth.AuthorizationResponse;
51+
import net.openid.appauth.AuthorizationService;
52+
import net.openid.appauth.AuthorizationServiceConfiguration;
53+
import net.openid.appauth.ClientSecretBasic;
54+
import net.openid.appauth.ResponseTypeValues;
55+
4556
import butterknife.BindView;
4657
import hu.akarnokd.rxjava3.bridge.RxJavaBridge;
4758
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
4859
import io.reactivex.rxjava3.core.Completable;
60+
import io.reactivex.rxjava3.core.Observable;
4961
import io.reactivex.rxjava3.core.Single;
5062
import io.reactivex.rxjava3.functions.Consumer;
5163
import io.reactivex.rxjava3.internal.functions.Functions;
@@ -66,6 +78,7 @@ public class LoginActivity extends BaseActivity {
6678

6779
private final CallbackManager facebookCallbackManager = CallbackManager.Factory.create();
6880
private GoogleSignInClient googleSignInClient;
81+
private AuthorizationService appAuthService;
6982

7083
private FirebaseAuth firebaseAuth;
7184

@@ -75,6 +88,13 @@ protected int getActivityLayoutRes() {
7588
return R.layout.activity_login;
7689
}
7790

91+
private AuthorizationService getAppAuthService() {
92+
if (appAuthService == null) {
93+
appAuthService = new AuthorizationService(this);
94+
}
95+
return appAuthService;
96+
}
97+
7898
@Override
7999
protected void onCreate(@Nullable Bundle savedInstanceState) {
80100
super.onCreate(savedInstanceState);
@@ -353,6 +373,52 @@ public void onSuccess(LoginResult loginResult) {
353373
});
354374
}
355375

376+
private Observable<String> getGoogleIdTokenBySdk() {
377+
return new RxInlineActivityResult(this)
378+
.request(googleSignInClient.getSignInIntent())
379+
.map(result -> GoogleSignIn.getSignedInAccountFromIntent(result.getData()).getResult())
380+
.map(GoogleSignInAccount::getIdToken)
381+
.as(RxJavaBridge.toV3Observable());
382+
}
383+
384+
private Observable<String> getGoogleIdTokenByChromeCustomTab() {
385+
AuthorizationServiceConfiguration asc = new AuthorizationServiceConfiguration(
386+
Uri.parse("https://accounts.google.com/o/oauth2/v2/auth"),
387+
Uri.parse("https://www.googleapis.com/oauth2/v4/token")
388+
);
389+
390+
String clientId = getString(R.string.default_web_client_id);
391+
Uri redirectUri = new Uri.Builder()
392+
.scheme(getString(R.string.auth_google_scheme))
393+
.authority(getString(R.string.auth_google_host))
394+
.path(getString(R.string.auth_google_path))
395+
.build();
396+
AuthorizationRequest.Builder builder = new AuthorizationRequest.Builder(asc, clientId, ResponseTypeValues.CODE, redirectUri)
397+
.setScopes("profile email")
398+
.setPrompt(AuthorizationRequest.Prompt.LOGIN);
399+
400+
AuthorizationService service = getAppAuthService();
401+
return new RxInlineActivityResult(this)
402+
.request(service.getAuthorizationRequestIntent(builder.build()))
403+
.flatMap(result -> {
404+
Intent data = result.getData();
405+
Throwable cause = result.getCause();
406+
return data != null ? io.reactivex.Observable.just(data) : io.reactivex.Observable.error(cause != null ? cause : new UnknownError());
407+
})
408+
.map(AuthorizationResponse::fromIntent)
409+
.flatMap(authResponse -> io.reactivex.Observable.<String>create(emitter -> service.performTokenRequest(
410+
authResponse.createTokenExchangeRequest(),
411+
new ClientSecretBasic(BuildConfig.GOOGLE_CLIENT_SECRET),
412+
(tokenResponse, e) -> {
413+
if (tokenResponse != null) {
414+
emitter.onNext(tokenResponse.idToken);
415+
} else {
416+
emitter.onError(e);
417+
}
418+
})))
419+
.as(RxJavaBridge.toV3Observable());
420+
}
421+
356422
private void setupSignInWithGoogleButton(FirebaseAuth firebaseAuth) {
357423
setupButton(firebaseAuth,
358424
signInWithGoogleButton,
@@ -362,24 +428,22 @@ private void setupSignInWithGoogleButton(FirebaseAuth firebaseAuth) {
362428
onDestroy.add(unlinkProvider(user, signInWithGoogleButton, Provider.GOOGLE, R.string.google)
363429
.subscribe(() -> {}, RxUtil.ON_ERROR_LOG_V3));
364430
} else {
365-
onDestroy.add(RxJavaBridge
366-
.toV3Disposable(new RxInlineActivityResult(this)
367-
.request(googleSignInClient.getSignInIntent())
368-
.map(result -> {
369-
Intent data = result.getData();
370-
return GoogleSignIn.getSignedInAccountFromIntent(data)
371-
.getResult();
372-
})
373-
.flatMapSingle(account -> {
374-
String token = account.getIdToken();
375-
IdpAuthCredential credential = GoogleAuthProvider.getCredential(token);
376-
return RxJavaBridge.toV2Single(firebaseAuth.signInWithCredential(credential));
377-
})
378-
.doOnError(e -> {
379-
dialog(e);
380-
googleSignInClient.signOut();
381-
})
382-
.subscribe(io.reactivex.internal.functions.Functions.emptyConsumer(), RxUtil.ON_ERROR_LOG_V2)));
431+
final boolean hasGms = ConnectionResult.SUCCESS == GoogleApiAvailability.getInstance()
432+
.isGooglePlayServicesAvailable(this);
433+
Observable<String> getGoogleIdToken = hasGms
434+
? getGoogleIdTokenBySdk()
435+
: getGoogleIdTokenByChromeCustomTab();
436+
//noinspection ResultOfMethodCallIgnored
437+
getGoogleIdToken.doOnSubscribe(onDestroy::add)
438+
.flatMapSingle(token -> {
439+
IdpAuthCredential credential = GoogleAuthProvider.getCredential(token);
440+
return firebaseAuth.signInWithCredential(credential);
441+
})
442+
.doOnError(e -> {
443+
dialog(e);
444+
googleSignInClient.signOut();
445+
})
446+
.subscribe(Functions.emptyConsumer(), RxUtil.ON_ERROR_LOG_V3);
383447
}
384448
},
385449
auth -> {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<resources>
3+
4+
<string name="auth_google_scheme">https</string>
5+
<string name="auth_google_host">idp.anotherdev.com</string>
6+
<string name="auth_google_path">"/auth/handler/huawei-dtse"</string>
7+
8+
</resources>

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ buildscript {
88

99
}
1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:4.0.1'
11+
classpath 'com.android.tools.build:gradle:4.0.2'
1212

1313
// NOTE: Do not place your application dependencies here; they belong
1414
// in the individual module build.gradle files
1515

16-
classpath 'com.google.gms:google-services:4.3.3'
16+
classpath 'com.google.gms:google-services:4.3.4'
1717
}
1818
}
1919

buildsystem/dependencies.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ext {
2525
targetCompatibility = JavaVersion.VERSION_1_8
2626

2727
// Libraries
28-
androidxAppCompatVersion = '1.1.0'
28+
androidxAppCompatVersion = '1.2.0'
2929
androidxCoreKtxVersion = '1.3.1'
3030
androidxLifecycleVersion = '2.2.0'
3131
firebaseBomVersion = '25.6.0'
@@ -38,6 +38,6 @@ ext {
3838
timberVersion = '4.7.1'
3939

4040
junitVersion = '4.13'
41-
androidxTestJunitVersion = '1.1.1'
42-
androidxTestEspressoVersion = '3.2.0'
41+
androidxTestJunitVersion = '1.1.2'
42+
androidxTestEspressoVersion = '3.3.0'
4343
}

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip

0 commit comments

Comments
 (0)