将google登录拿回来
This commit is contained in:
parent
ea145e977c
commit
515d794f78
@ -88,7 +88,49 @@
|
||||
android:path="/relay_cb" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name="net.openid.appauth.RedirectUriReceiverActivity"
|
||||
tools:node="replace">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="com.googleusercontent.apps.53206975661-ih3r0ubph3rqejdq97b029difbrk2bqj" />
|
||||
<data android:scheme="com.googleusercontent.apps.53206975661-asnf3qe4bg29p8h981pgf099osvrjbme" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="http" />
|
||||
<data android:host="oauth-svr.cebggame.com"/>
|
||||
<data android:pathPrefix="/google"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="oauth-svr.cebggame.com"/>
|
||||
<data android:pathPrefix="/google"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".oauth.OAuthLoginCbActivity"
|
||||
tools:node="replace"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="cfoauthcb" android:path="/login_result" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!--
|
||||
This activity declaration is merged with the version from the library manifest.
|
||||
|
@ -118,7 +118,7 @@ dependencies {
|
||||
implementation "androidx.appcompat:appcompat:1.0.2"
|
||||
implementation "androidx.biometric:biometric:1.1.0"
|
||||
|
||||
implementation 'com.google.android.gms:play-services-auth:20.3.0'
|
||||
implementation 'com.google.android.gms:play-services-auth:21.2.0'
|
||||
|
||||
// implementation 'com.xm.permissions:XmPermissions:1.0.1'
|
||||
implementation 'pub.devrel:easypermissions:3.0.0'
|
||||
@ -127,7 +127,7 @@ dependencies {
|
||||
implementation "com.squareup.okio:okio:2.10.0"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'com.bytedance.ies.ugc.aweme:opensdk-oversea-external:0.2.1.0'
|
||||
implementation 'com.google.android.play:core:1.10.0' //PAD资源分发
|
||||
implementation 'com.google.android.play:core:1.10.3' //PAD资源分发
|
||||
implementation 'com.facebook.android:facebook-core:latest.release'
|
||||
implementation 'com.facebook.android:facebook-login:latest.release'
|
||||
implementation 'com.facebook.android:facebook-share:latest.release'
|
||||
|
@ -7,25 +7,53 @@ import android.view.Window;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.cege.games.release.oauth.AppAuthSvr;
|
||||
import com.cege.games.release.oauth.OAuthUtil;
|
||||
import com.cege.games.release.ui.UIManager;
|
||||
import com.facebook.appevents.AppEventsLogger;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.android.gms.common.Scopes;
|
||||
import com.google.android.gms.common.api.ApiException;
|
||||
import com.google.android.gms.common.api.Scope;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.analytics.FirebaseAnalytics;
|
||||
import com.jc.jcfw.JcSDK;
|
||||
import com.jc.jcfw.google.PayClient;
|
||||
import com.jc.jcfw.util.JsonUtils;
|
||||
import com.unity3d.player.UnityPlayerActivity;
|
||||
|
||||
import net.openid.appauth.AuthState;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
||||
public class MainActivity extends UnityPlayerActivity {
|
||||
private static final String TAG = MainActivity.class.getSimpleName();
|
||||
|
||||
public static MainActivity app;
|
||||
// AppAuth
|
||||
private static final int RC_AUTH = 0X04;
|
||||
// google sign
|
||||
private static final int RC_SIGN_IN = 0X05;
|
||||
|
||||
private String mFunID;
|
||||
|
||||
private FirebaseAnalytics mFirebaseAnalytics;
|
||||
private AppEventsLogger fbLogger;
|
||||
private OAuthUtil mOAuthUtil;
|
||||
|
||||
// AppAuth
|
||||
private AppAuthSvr mAppAuthSvr;
|
||||
private ExecutorService mExecutor;
|
||||
private GoogleSignInClient mGoogleSignInClient;
|
||||
|
||||
public boolean isGooglePlayServicesAvailable() {
|
||||
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS;
|
||||
@ -40,6 +68,10 @@ public class MainActivity extends UnityPlayerActivity {
|
||||
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
|
||||
|
||||
app = this;
|
||||
// begin of google oauth sign
|
||||
mAppAuthSvr = new AppAuthSvr(this);
|
||||
mExecutor = Executors.newSingleThreadExecutor();
|
||||
mAppAuthSvr.init(mExecutor);
|
||||
|
||||
PayClient payClient = PayClient.getInstance();
|
||||
payClient.init(this);
|
||||
@ -56,6 +88,23 @@ public class MainActivity extends UnityPlayerActivity {
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
UIManager.getSingleton().onActivityResult(this, requestCode, resultCode, data);
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
switch (requestCode) {
|
||||
case RC_AUTH:
|
||||
mAppAuthSvr.parseLoginResult(data);
|
||||
break;
|
||||
case RC_SIGN_IN:
|
||||
handleSignInResult(GoogleSignIn.getSignedInAccountFromIntent(data));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (requestCode == RC_SIGN_IN) {
|
||||
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
|
||||
handleSignInResult(task);
|
||||
}
|
||||
mFunID = "";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -86,4 +135,84 @@ public class MainActivity extends UnityPlayerActivity {
|
||||
}
|
||||
}
|
||||
|
||||
// begin google sign in
|
||||
private GoogleSignInClient initGsiClient() {
|
||||
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
||||
.requestScopes(new Scope(Scopes.EMAIL))
|
||||
.requestIdToken(getString(R.string.default_web_client_id1))
|
||||
.build();
|
||||
return GoogleSignIn.getClient(this, gso);
|
||||
}
|
||||
|
||||
public void signWithGoogle(String funId) {
|
||||
this.mFunID = funId;
|
||||
if (isGooglePlayServicesAvailable()) {
|
||||
if (mGoogleSignInClient == null) {
|
||||
mGoogleSignInClient = initGsiClient();
|
||||
}
|
||||
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
|
||||
if (account != null) {
|
||||
Log.w(TAG, "already login: " + account.getIdToken());
|
||||
mGoogleSignInClient.silentSignIn()
|
||||
.addOnCompleteListener(this, this::handleSignInResult);
|
||||
} else {
|
||||
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
|
||||
startActivityForResult(signInIntent, RC_SIGN_IN);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "no gms, use app auth");
|
||||
AuthState state = mAppAuthSvr.getCurrentState();
|
||||
if (state.isAuthorized()) {
|
||||
if (state.getNeedsTokenRefresh()) {
|
||||
Log.w(TAG, "need refresh accessToken");
|
||||
mAppAuthSvr.refreshToken(funId, null);
|
||||
} else {
|
||||
Log.w(TAG, "already login, accessToken not expired, id token:: " + state.getIdToken());
|
||||
JcSDK.nativeCb(this.mFunID, null, state.getIdToken());
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "not login");
|
||||
mExecutor.submit(() -> mAppAuthSvr.doAuth(funId, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void signOutGoogle(String funId) {
|
||||
if (isGooglePlayServicesAvailable()) {
|
||||
if (mGoogleSignInClient != null) {
|
||||
mGoogleSignInClient.signOut()
|
||||
.addOnCompleteListener(this, task -> {
|
||||
// ...
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
|
||||
try {
|
||||
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
|
||||
Log.w(TAG, "gso signIn success: " + account.getIdToken());
|
||||
JcSDK.nativeCb(this.mFunID, null, account.getIdToken());
|
||||
// Signed in successfully, show authenticated UI.
|
||||
} catch (ApiException e) {
|
||||
// The ApiException status code indicates the detailed failure reason.
|
||||
// Please refer to the GoogleSignInStatusCodes class reference for more
|
||||
// information.
|
||||
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
|
||||
JcSDK.nativeCb(this.mFunID, "signInResult:failed code=" + e.getStatusCode(), null);
|
||||
}
|
||||
}
|
||||
|
||||
// general oauth login
|
||||
public void oauthLogin(String funId, String jsonData) {
|
||||
if (this.mOAuthUtil == null) {
|
||||
this.mOAuthUtil = new OAuthUtil(this);
|
||||
}
|
||||
try {
|
||||
this.mOAuthUtil.startLogin(funId, jsonData);
|
||||
} catch (JSONException e) {
|
||||
JcSDK.nativeCb(funId, e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
394
app/src/com/cege/games/release/oauth/AppAuthSvr.java
Normal file
394
app/src/com/cege/games/release/oauth/AppAuthSvr.java
Normal file
@ -0,0 +1,394 @@
|
||||
package com.cege.games.release.oauth;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
|
||||
import com.jc.jcfw.JcSDK;
|
||||
import com.jc.jcfw.appauth.AuthStateManager;
|
||||
import com.jc.jcfw.appauth.JConfiguration;
|
||||
import com.jc.jcfw.util.ThreadUtils;
|
||||
|
||||
import net.openid.appauth.AppAuthConfiguration;
|
||||
import net.openid.appauth.AuthState;
|
||||
import net.openid.appauth.AuthorizationException;
|
||||
import net.openid.appauth.AuthorizationRequest;
|
||||
import net.openid.appauth.AuthorizationResponse;
|
||||
import net.openid.appauth.AuthorizationService;
|
||||
import net.openid.appauth.AuthorizationServiceConfiguration;
|
||||
import net.openid.appauth.ClientAuthentication;
|
||||
import net.openid.appauth.ClientSecretBasic;
|
||||
import net.openid.appauth.RegistrationRequest;
|
||||
import net.openid.appauth.RegistrationResponse;
|
||||
import net.openid.appauth.ResponseTypeValues;
|
||||
import net.openid.appauth.TokenRequest;
|
||||
import net.openid.appauth.TokenResponse;
|
||||
import net.openid.appauth.browser.AnyBrowserMatcher;
|
||||
import net.openid.appauth.browser.BrowserMatcher;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AppAuthSvr {
|
||||
private final String TAG = getClass().getSimpleName();
|
||||
private final Activity activity;
|
||||
private AuthorizationService mAuthService;
|
||||
private AuthStateManager mAuthStateManager;
|
||||
private JConfiguration mConfiguration;
|
||||
private ExecutorService mExecutor;
|
||||
private final AtomicReference<String> mClientId = new AtomicReference<>();
|
||||
private final AtomicReference<AuthorizationRequest> mAuthRequest = new AtomicReference<>();
|
||||
private final AtomicReference<CustomTabsIntent> mAuthIntent = new AtomicReference<>();
|
||||
private CountDownLatch mAuthIntentLatch = new CountDownLatch(1);
|
||||
|
||||
private String mFunID;
|
||||
|
||||
private static final int RC_AUTH = 0X04;
|
||||
|
||||
private Consumer<String> loginCbAction = null;
|
||||
|
||||
@NonNull
|
||||
private final BrowserMatcher mBrowserMatcher = AnyBrowserMatcher.INSTANCE;
|
||||
|
||||
public AppAuthSvr(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public void init(ExecutorService executorService) {
|
||||
mExecutor = executorService;
|
||||
mAuthStateManager = AuthStateManager.getInstance(activity);
|
||||
mConfiguration = JConfiguration.getInstance(activity);
|
||||
mExecutor.submit(this::initializeAppAuth);
|
||||
}
|
||||
|
||||
public void setFunID(String funID) {
|
||||
this.mFunID = funID;
|
||||
}
|
||||
|
||||
public void setLoginCbAction(Consumer<String> func) {
|
||||
this.loginCbAction = func;
|
||||
}
|
||||
|
||||
public AuthState getCurrentState() {
|
||||
return mAuthStateManager.getCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the authorization request, using the browser selected in the
|
||||
* spinner,
|
||||
* and a user-provided `login_hint` if available.
|
||||
*/
|
||||
@WorkerThread
|
||||
public void doAuth(String funID, Consumer<String> func) {
|
||||
this.mFunID = funID;
|
||||
this.loginCbAction = func;
|
||||
try {
|
||||
mAuthIntentLatch.await();
|
||||
} catch (InterruptedException ex) {
|
||||
Log.w(TAG, "Interrupted while waiting for auth intent");
|
||||
}
|
||||
|
||||
Intent intent = mAuthService.getAuthorizationRequestIntent(
|
||||
mAuthRequest.get(),
|
||||
mAuthIntent.get());
|
||||
activity.startActivityForResult(intent, RC_AUTH);
|
||||
}
|
||||
|
||||
public void parseLoginResult(@NonNull Intent data) {
|
||||
AuthorizationResponse response = AuthorizationResponse.fromIntent(data);
|
||||
AuthorizationException ex = AuthorizationException.fromIntent(data);
|
||||
if (response != null || ex != null) {
|
||||
mAuthStateManager.updateAfterAuthorization(response, ex);
|
||||
}
|
||||
if (response != null && response.authorizationCode != null) {
|
||||
// authorization code exchange is required
|
||||
mAuthStateManager.updateAfterAuthorization(response, ex);
|
||||
exchangeAuthorizationCode(response);
|
||||
} else if (ex != null) {
|
||||
Log.i(TAG, "Authorization flow failed: " + ex.getMessage());
|
||||
errorCB("Authorization flow failed: " + ex.getMessage());
|
||||
} else {
|
||||
Log.i(TAG, "No authorization state retained - reauthorization required");
|
||||
errorCB("No authorization state retained - reauthorization required");
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshToken(String funID, Consumer<String> func) {
|
||||
this.mFunID = funID;
|
||||
this.loginCbAction = func;
|
||||
AuthState state = getCurrentState();
|
||||
performTokenRequest(state.createTokenRefreshRequest(), this::handleCodeExchangeResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the authorization service configuration if necessary, either from
|
||||
* the local
|
||||
* static values or by retrieving an OpenID discovery document.
|
||||
*/
|
||||
@WorkerThread
|
||||
private void initializeAppAuth() {
|
||||
Log.i(TAG, "Initializing AppAuth");
|
||||
recreateAuthorizationService();
|
||||
|
||||
if (mAuthStateManager.getCurrent().getAuthorizationServiceConfiguration() != null) {
|
||||
// configuration is already created, skip to client initialization
|
||||
Log.i(TAG, "auth config already established");
|
||||
initializeClient();
|
||||
return;
|
||||
}
|
||||
|
||||
// if we are not using discovery, build the authorization service configuration
|
||||
// directly
|
||||
// from the static configuration values.
|
||||
if (mConfiguration.getDiscoveryUri() == null) {
|
||||
Log.i(TAG, "Creating auth config from res/raw/auth_config.json");
|
||||
AuthorizationServiceConfiguration config = new AuthorizationServiceConfiguration(
|
||||
mConfiguration.getAuthEndpointUri(),
|
||||
mConfiguration.getTokenEndpointUri(),
|
||||
mConfiguration.getRegistrationEndpointUri(),
|
||||
mConfiguration.getEndSessionEndpoint());
|
||||
|
||||
mAuthStateManager.replace(new AuthState(config));
|
||||
initializeClient();
|
||||
return;
|
||||
}
|
||||
|
||||
// WrongThread inference is incorrect for lambdas
|
||||
// noinspection WrongThread
|
||||
Log.i(TAG, "Retrieving OpenID discovery doc");
|
||||
AuthorizationServiceConfiguration.fetchFromUrl(
|
||||
mConfiguration.getDiscoveryUri(),
|
||||
this::handleConfigurationRetrievalResult,
|
||||
mConfiguration.getConnectionBuilder());
|
||||
}
|
||||
|
||||
@MainThread
|
||||
private void handleConfigurationRetrievalResult(
|
||||
AuthorizationServiceConfiguration config,
|
||||
AuthorizationException ex) {
|
||||
if (config == null) {
|
||||
Log.i(TAG, "Failed to retrieve discovery document", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "Discovery document retrieved");
|
||||
mAuthStateManager.replace(new AuthState(config));
|
||||
mExecutor.submit(this::initializeClient);
|
||||
}
|
||||
|
||||
private void recreateAuthorizationService() {
|
||||
if (mAuthService != null) {
|
||||
Log.i(TAG, "Discarding existing AuthService instance");
|
||||
mAuthService.dispose();
|
||||
}
|
||||
mAuthService = createAuthorizationService();
|
||||
mAuthRequest.set(null);
|
||||
mAuthIntent.set(null);
|
||||
}
|
||||
|
||||
private AuthorizationService createAuthorizationService() {
|
||||
Log.i(TAG, "Creating authorization service");
|
||||
AppAuthConfiguration.Builder builder = new AppAuthConfiguration.Builder();
|
||||
builder.setBrowserMatcher(mBrowserMatcher);
|
||||
builder.setConnectionBuilder(mConfiguration.getConnectionBuilder());
|
||||
|
||||
return new AuthorizationService(activity, builder.build());
|
||||
}
|
||||
|
||||
private void createAuthRequest(@Nullable String loginHint) {
|
||||
Log.i(TAG, "Creating auth request for login hint: " + loginHint);
|
||||
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
|
||||
mAuthStateManager.getCurrent().getAuthorizationServiceConfiguration(),
|
||||
mClientId.get(),
|
||||
ResponseTypeValues.CODE,
|
||||
mConfiguration.getRedirectUri())
|
||||
// apple need `form_post` when authorization_scope has `name email `
|
||||
// .setResponseMode("form_post")
|
||||
// .setResponseType("code id_token")
|
||||
.setScope(mConfiguration.getScope());
|
||||
if (!TextUtils.isEmpty(loginHint)) {
|
||||
authRequestBuilder.setLoginHint(loginHint);
|
||||
}
|
||||
mAuthRequest.set(authRequestBuilder.build());
|
||||
}
|
||||
|
||||
private void warmUpBrowser() {
|
||||
mAuthIntentLatch = new CountDownLatch(1);
|
||||
mExecutor.execute(() -> {
|
||||
Log.i(TAG, "Warming up browser instance for auth request");
|
||||
Uri uri = mAuthRequest.get().toUri();
|
||||
Log.d(TAG, "URI: " + uri);
|
||||
CustomTabsIntent.Builder intentBuilder = mAuthService.createCustomTabsIntentBuilder(uri);
|
||||
mAuthIntent.set(intentBuilder.build());
|
||||
mAuthIntentLatch.countDown();
|
||||
});
|
||||
}
|
||||
|
||||
@MainThread
|
||||
private void initializeAuthRequest() {
|
||||
createAuthRequest("");
|
||||
warmUpBrowser();
|
||||
displayAuthOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a dynamic registration request if a client ID is not provided by
|
||||
* the static
|
||||
* configuration.
|
||||
*/
|
||||
@WorkerThread
|
||||
private void initializeClient() {
|
||||
if (mConfiguration.getClientId() != null) {
|
||||
Log.i(TAG, "Using static client ID: " + mConfiguration.getClientId());
|
||||
// use a statically configured client ID
|
||||
mClientId.set(mConfiguration.getClientId());
|
||||
ThreadUtils.runInMain(this::initializeAuthRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RegistrationResponse lastResponse = mAuthStateManager.getCurrent().getLastRegistrationResponse();
|
||||
if (lastResponse != null) {
|
||||
Log.i(TAG, "Using dynamic client ID: " + lastResponse.clientId);
|
||||
// already dynamically registered a client ID
|
||||
mClientId.set(lastResponse.clientId);
|
||||
ThreadUtils.runInMain(this::initializeAuthRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
// WrongThread inference is incorrect for lambdas
|
||||
// noinspection WrongThread
|
||||
Log.i(TAG, "Dynamically registering client");
|
||||
|
||||
RegistrationRequest registrationRequest = new RegistrationRequest.Builder(
|
||||
mAuthStateManager.getCurrent().getAuthorizationServiceConfiguration(),
|
||||
Collections.singletonList(mConfiguration.getRedirectUri()))
|
||||
.setTokenEndpointAuthenticationMethod(ClientSecretBasic.NAME)
|
||||
.build();
|
||||
|
||||
mAuthService.performRegistrationRequest(
|
||||
registrationRequest,
|
||||
this::handleRegistrationResponse);
|
||||
}
|
||||
|
||||
private void handleRegistrationResponse(
|
||||
RegistrationResponse response,
|
||||
AuthorizationException ex) {
|
||||
mAuthStateManager.updateAfterRegistration(response, ex);
|
||||
if (response == null) {
|
||||
Log.i(TAG, "Failed to dynamically register client", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "Dynamically registered client: " + response.clientId);
|
||||
mClientId.set(response.clientId);
|
||||
initializeAuthRequest();
|
||||
}
|
||||
|
||||
private void displayAuthOptions() {
|
||||
AuthState state = mAuthStateManager.getCurrent();
|
||||
AuthorizationServiceConfiguration config = state.getAuthorizationServiceConfiguration();
|
||||
|
||||
String authEndpointStr;
|
||||
if (config.discoveryDoc != null) {
|
||||
authEndpointStr = "Discovered auth endpoint: \n";
|
||||
} else {
|
||||
authEndpointStr = "Static auth endpoint: \n";
|
||||
}
|
||||
authEndpointStr += config.authorizationEndpoint;
|
||||
Log.i(TAG, authEndpointStr);
|
||||
|
||||
String clientIdStr;
|
||||
if (state.getLastRegistrationResponse() != null) {
|
||||
clientIdStr = "Dynamic client ID: \n";
|
||||
} else {
|
||||
clientIdStr = "Static client ID: \n";
|
||||
}
|
||||
clientIdStr += mClientId;
|
||||
Log.i(TAG, clientIdStr);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
private void exchangeAuthorizationCode(AuthorizationResponse authorizationResponse) {
|
||||
Log.d(TAG, "Exchanging authorization code");
|
||||
performTokenRequest(
|
||||
authorizationResponse.createTokenExchangeRequest(),
|
||||
this::handleCodeExchangeResponse);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
private void performTokenRequest(
|
||||
TokenRequest request,
|
||||
AuthorizationService.TokenResponseCallback callback) {
|
||||
ClientAuthentication clientAuthentication;
|
||||
try {
|
||||
clientAuthentication = mAuthStateManager.getCurrent().getClientAuthentication();
|
||||
} catch (ClientAuthentication.UnsupportedAuthenticationMethod ex) {
|
||||
Log.d(TAG, "Token request cannot be made, client authentication for the token "
|
||||
+ "endpoint could not be constructed (%s)", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
mAuthService.performTokenRequest(
|
||||
request,
|
||||
clientAuthentication,
|
||||
callback);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void handleCodeExchangeResponse(
|
||||
@Nullable TokenResponse tokenResponse,
|
||||
@Nullable AuthorizationException authException) {
|
||||
mAuthStateManager.updateAfterTokenResponse(tokenResponse, authException);
|
||||
if (!mAuthStateManager.getCurrent().isAuthorized()) {
|
||||
final String message = "Authorization Code exchange failed: "
|
||||
+ ((authException != null) ? authException.error : "");
|
||||
Log.d(TAG, message);
|
||||
errorCB(message);
|
||||
} else {
|
||||
checkAuthStateAndCB();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAuthStateAndCB() {
|
||||
AuthState state = mAuthStateManager.getCurrent();
|
||||
Log.d(TAG, "login success, auth state: " + state.isAuthorized());
|
||||
Log.d(TAG, "id token : " + state.getIdToken());
|
||||
Log.d(TAG, "access token: " + state.getAccessToken());
|
||||
Log.d(TAG, "refresh token: " + state.getRefreshToken());
|
||||
mAuthStateManager.replace(state);
|
||||
if (loginCbAction != null) {
|
||||
mExecutor.submit(() -> {
|
||||
loginCbAction.accept("success");
|
||||
clearParams();
|
||||
});
|
||||
} else {
|
||||
successCB(state.getIdToken());
|
||||
}
|
||||
}
|
||||
private void clearParams() {
|
||||
this.mFunID = null;
|
||||
this.loginCbAction = null;
|
||||
}
|
||||
public void errorCB(String msg) {
|
||||
JcSDK.nativeCb(mFunID, msg, null);
|
||||
clearParams();
|
||||
}
|
||||
|
||||
public void successCB(String dataStr) {
|
||||
JcSDK.nativeCb(mFunID, null, dataStr);
|
||||
clearParams();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
package com.cege.games.release.oauth;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.cege.games.release.MainActivity;
|
||||
import com.jc.jcfw.JcSDK;
|
||||
|
||||
public class OAuthLoginCbActivity extends Activity {
|
||||
private static final String TAG = OAuthLoginCbActivity.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.d(TAG, "receive oauth login callback");
|
||||
Intent intent = getIntent();
|
||||
|
||||
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||
Uri uri = intent.getData();
|
||||
String error = uri.getQueryParameter("error");
|
||||
String state = uri.getQueryParameter("state");
|
||||
if (null != error && !error.isEmpty()) {
|
||||
JcSDK.nativeCb(state, error, null);
|
||||
} else {
|
||||
String token = uri.getQueryParameter("token");
|
||||
// if token is null, get token and state from uri fragment
|
||||
if (null == token || "undefined".equals(token) || token.isEmpty()){
|
||||
String fragment = uri.getFragment();
|
||||
String[] vals = fragment.split("&");
|
||||
for (String val : vals) {
|
||||
if (val.startsWith("token=")) {
|
||||
token = val.substring(6);
|
||||
} else if (val.startsWith("id_token=")) {
|
||||
token = val.substring(9);
|
||||
} else if (val.startsWith("state=")) {
|
||||
state = val.substring(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
JcSDK.nativeCb(state, null, token);
|
||||
}
|
||||
Intent intentMain = new Intent(this, MainActivity.class);
|
||||
startActivity(intentMain);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
61
app/src/com/cege/games/release/oauth/OAuthUtil.java
Normal file
61
app/src/com/cege/games/release/oauth/OAuthUtil.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.cege.games.release.oauth;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
|
||||
import net.openid.appauth.AuthorizationRequest;
|
||||
import net.openid.appauth.AuthorizationService;
|
||||
import net.openid.appauth.AuthorizationServiceConfiguration;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class OAuthUtil {
|
||||
private final Activity mActivity;
|
||||
|
||||
public OAuthUtil(Activity activity) {
|
||||
this.mActivity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param funId
|
||||
* @param jsonData: {
|
||||
* "endpoint": "",
|
||||
* "client_id": "",
|
||||
* "redirect_uri": "",
|
||||
* "response_type": "code",
|
||||
* "response_mode": "form_post", nullable
|
||||
* "scopes": "",
|
||||
* }
|
||||
* @throws JSONException
|
||||
*/
|
||||
public void startLogin(String funId, String jsonData) throws JSONException {
|
||||
JSONObject data = new JSONObject(jsonData);
|
||||
AuthorizationServiceConfiguration config = new AuthorizationServiceConfiguration(
|
||||
Uri.parse(data.getString("endpoint")),
|
||||
Uri.parse("")
|
||||
);
|
||||
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
|
||||
config,
|
||||
data.getString("client_id"),
|
||||
data.getString("response_type"),
|
||||
Uri.parse(data.getString("redirect_uri"))
|
||||
);
|
||||
String[] scopes = data.getString("scopes").split(" +");
|
||||
if (data.has("response_mode")) {
|
||||
authRequestBuilder.setResponseMode(data.getString("response_mode"));
|
||||
}
|
||||
AuthorizationRequest authRequest = authRequestBuilder
|
||||
.setScopes(scopes)
|
||||
.setCodeVerifier(null, null, null)
|
||||
.setState(funId)
|
||||
.setNonce(funId)
|
||||
.build();
|
||||
AuthorizationService service = new AuthorizationService(this.mActivity);
|
||||
Intent authIntent = service.getAuthorizationRequestIntent(authRequest);
|
||||
this.mActivity.startActivity(authIntent);
|
||||
}
|
||||
}
|
@ -119,10 +119,19 @@ public class JcSDK {
|
||||
payClient.queryPurchase(funid);
|
||||
}
|
||||
|
||||
public static void onProxyCB(String funId, String data) {
|
||||
EventBus.getDefault().post(new ProxyCBEvent(funId, data));
|
||||
public static void signWithOAuth(String funid, String jsonData) {
|
||||
MainActivity.app.oauthLogin(funid, jsonData);
|
||||
}
|
||||
|
||||
public static void signWithGoogle(String funid) {
|
||||
MainActivity.app.signWithGoogle(funid);
|
||||
}
|
||||
|
||||
public static void signOutGoogle(String funid) {
|
||||
MainActivity.app.signOutGoogle(funid);
|
||||
}
|
||||
|
||||
|
||||
public static void nativeCb(String funId, String error, String dataStr) {
|
||||
toUnity(funId, error, dataStr);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user