From 061a66d7d90b0d2c796d9e8350a440fc5f698283 Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Thu, 28 Jul 2022 17:23:20 +0800 Subject: [PATCH 01/64] fix web pkce flow --- guard/src/main/java/cn/authing/guard/WebAuthView.java | 8 +++++--- .../java/cn/authing/guard/network/OIDCClient.java | 11 +++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/guard/src/main/java/cn/authing/guard/WebAuthView.java b/guard/src/main/java/cn/authing/guard/WebAuthView.java index 925f5c4d..19165487 100644 --- a/guard/src/main/java/cn/authing/guard/WebAuthView.java +++ b/guard/src/main/java/cn/authing/guard/WebAuthView.java @@ -39,6 +39,7 @@ public interface WebViewListener { private WebViewListener listener; private boolean loadingEventFired; private WebAuthViewCallback callback; + private OIDCClient oidcClient; public interface WebAuthViewCallback { void call(UserInfo userInfo); @@ -83,7 +84,7 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request try { String authCode = Util.getAuthCode(url); if (authCode != null) { - new OIDCClient(authRequest).authByCode(authCode, (code, message, userInfo) -> fireCallback(code, message, userInfo)); + oidcClient.authByCode(authCode, (code, message, userInfo) -> fireCallback(code, message, userInfo)); } else { ALog.e(TAG, url); fireCallback(500, "login failed", null); @@ -136,7 +137,7 @@ private void handleAuthCode(String url) { try { String authCode = Util.getAuthCode(url); if (authCode != null) { - new OIDCClient(authRequest).authByCode(authCode, (code, message, userInfo) -> fireCallback(code, message, userInfo)); + oidcClient.authByCode(authCode, (code, message, userInfo) -> fireCallback(code, message, userInfo)); } else { ALog.e(TAG, url); fireCallback(500, "login failed", null); @@ -178,13 +179,14 @@ public void onPageFinished(WebView view, String url) { } }); + oidcClient = new OIDCClient(authRequest); Authing.getPublicConfig(config -> { if (getContext() instanceof AuthActivity) { AuthActivity activity = (AuthActivity) getContext(); AuthFlow flow = (AuthFlow) activity.getIntent().getSerializableExtra(AuthActivity.AUTH_FLOW); authRequest.setScope(flow.getScope()); } - post(()-> new OIDCClient(authRequest).buildAuthorizeUrl((ok, data) -> loadUrl(data))); + post(()-> oidcClient.buildAuthorizeUrl((ok, data) -> loadUrl(data))); }); } diff --git a/guard/src/main/java/cn/authing/guard/network/OIDCClient.java b/guard/src/main/java/cn/authing/guard/network/OIDCClient.java index f4489896..916e43cc 100644 --- a/guard/src/main/java/cn/authing/guard/network/OIDCClient.java +++ b/guard/src/main/java/cn/authing/guard/network/OIDCClient.java @@ -4,7 +4,6 @@ import org.json.JSONException; import org.json.JSONObject; -import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Objects; @@ -132,8 +131,8 @@ public void authByCode(String code, @NotNull AuthCallback callback) { .add("code", code) .add("scope", authRequest.getScope()) .add("prompt", "consent") - .add(secret == null ? "code_verifier=" : "client_secret", secret == null ? authRequest.getCodeVerifier() : secret) - .add("redirect_uri", URLEncoder.encode(authRequest.getRedirectURL(), "utf-8")) + .add(secret == null ? "code_verifier" : "client_secret", secret == null ? authRequest.getCodeVerifier() : secret) + .add("redirect_uri", authRequest.getRedirectURL()) .build(); Guardian.authRequest(url, "post", formBody, (data)-> { ALog.d(TAG, "authByCode cost:" + (System.currentTimeMillis() - now) + "ms"); @@ -168,8 +167,8 @@ public void authByToken(UserInfo userInfo, String token, @NotNull AuthCallback { ALog.d(TAG, "authByToken cost:" + (System.currentTimeMillis() - now) + "ms"); @@ -247,7 +246,7 @@ public void getNewAccessTokenByRefreshToken(String refreshToken, @NotNull AuthCa .add("client_id",Authing.getAppId()) .add("grant_type", "refresh_token") .add("refresh_token", refreshToken) - .add(secret == null ? "code_verifier=" : "client_secret", secret == null ? authRequest.getCodeVerifier() : secret) + .add(secret == null ? "code_verifier" : "client_secret", secret == null ? authRequest.getCodeVerifier() : secret) .build(); Guardian.authRequest(url, "post", formBody, (data)-> { if (data.getCode() == 200) { From f47955f372a7bf681374dfca76257a6f010b547a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=9F=E5=AE=B6=E6=83=A0?= Date: Tue, 2 Aug 2022 14:17:34 +0800 Subject: [PATCH 02/64] update LICENSE and README --- LICENSE | 4 ++-- README.md | 44 +++++++++++++++++++++++++++++++------------- README.zh-CN.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 README.zh-CN.md diff --git a/LICENSE b/LICENSE index 4d52d78c..b2923fd4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 lancemao +Copyright (c) 2019-present Authing Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 2709f00c..551a16d3 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,47 @@ # Guard Android -
-
-
-
- - - - +
+
-
-[中文文档请移步至这里查看](https://docs.authing.cn/v2/android/) + +License -[Click me for English documentation](https://docs.authing.cn/v2/en/reference/sdk-for-android/) +**English** | [简体中文](./README.zh-CN.md) -
+## Introduction + +You can quickly build user login authentication capabilities using the Authing Guard SDK. + +## Sample + +drawing + +## Documentation + +- [Click me for English documentation](https://docs.authing.cn/v2/en/reference/sdk-for-android/) + +## Authing Console Configuration + +In the Authing Console's self-built application, modify your application settings: + +- **Authorization Configuration**: `authorization_code`、 `implicit`、 `password`、`refresh_token`、`authing_token` +- **Authorization Configuration**: `Return Type` select `code` + +## Contribution -## Contribute - Fork it - Create your feature branch (git checkout -b my-new-feature) - Commit your changes (git commit -am 'Add some feature') - Push to the branch (git push origin my-new-feature) - Create new Pull Request +## License + +[MIT](https://opensource.org/licenses/MIT) + +Copyright (c) 2019-present, Authing + ## Get help Contact our senior Android developer via Wechat: diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 00000000..a7ac2f5e --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,48 @@ +# Guard Android + +
+ +
+ +License + +**简体中文** | [English](./README.md) + +## 简介 + +你可以使用 Authing Guard SDK 快速构建用户登录认证能力。 + +## 示例 + +drawing + +## 参考文档 + +- [中文文档请移步至这里查看](https://docs.authing.cn/v2/android/) + +## Authing 控制台配置 + +在控制台的创建自建应用时,请选择客户端应用,其它配置注意: + +- **授权配置**:`授权模式` 选中 `authorization_code`、 `implicit`、 `password`、`refresh_token`、`authing_token` +- **授权配置**:`返回类型` 选中 `code` + +## 开源共建 + +- Fork 此仓库 +- 创建自己的 git 分支 (git checkout -b my-new-feature) +- 提交你的修改 (git commit -am 'Add some feature') +- 将修改内容推送到远程分支 (git push -u origin my-new-feature) +- 创建一个 Pull Request + +## License + +[MIT](https://opensource.org/licenses/MIT) + +Copyright (c) 2019-present, Authing + +## 获取帮助 + +通过微信联系我们的高级Android开发者: + + From e8078d9ca3222355db5d292008fe719a8766975f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=9F=E5=AE=B6=E6=83=A0?= Date: Tue, 2 Aug 2022 14:25:46 +0800 Subject: [PATCH 03/64] update README sample image --- README.md | 2 +- README.zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 551a16d3..7a6cb29c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ You can quickly build user login authentication capabilities using the Authing G ## Sample -drawing +drawing ## Documentation diff --git a/README.zh-CN.md b/README.zh-CN.md index a7ac2f5e..c10e2258 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -14,7 +14,7 @@ ## 示例 -drawing +drawing ## 参考文档 From be4287f597c21fc1920af142131ea55f23ddc588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=9F=E5=AE=B6=E6=83=A0?= Date: Tue, 2 Aug 2022 17:32:47 +0800 Subject: [PATCH 04/64] update README badge --- README.md | 8 +++++--- README.zh-CN.md | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7a6cb29c..73fb27d1 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,10 @@
- -License +
+ + License +
**English** | [简体中文](./README.zh-CN.md) @@ -15,7 +17,7 @@ You can quickly build user login authentication capabilities using the Authing G ## Sample -drawing +drawing ## Documentation diff --git a/README.zh-CN.md b/README.zh-CN.md index c10e2258..ac0541f7 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -3,8 +3,11 @@
- -License + +
+ + License +
**简体中文** | [English](./README.md) @@ -14,7 +17,7 @@ ## 示例 -drawing +drawing ## 参考文档 From 1d27dd02374e74c2fa2b8d5098685a0cfd4ed9e2 Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Wed, 3 Aug 2022 13:50:39 +0800 Subject: [PATCH 05/64] support enterprise wechat agent mode --- .../cn/authing/guard/network/AuthClient.java | 21 ++++++++++++++ .../cn/authing/guard/network/OIDCClient.java | 4 +++ .../guard/social/SocialLoginButton.java | 12 ++++++-- .../guard/social/SocialLoginListView.java | 27 +++++++---------- .../java/cn/authing/guard/social/WeCom.java | 29 +++++++++++++++---- .../guard/social/WeComLoginButton.java | 2 +- .../java/cn/authing/guard/util/Const.java | 1 + 7 files changed, 69 insertions(+), 27 deletions(-) diff --git a/guard/src/main/java/cn/authing/guard/network/AuthClient.java b/guard/src/main/java/cn/authing/guard/network/AuthClient.java index 12394816..4a800909 100644 --- a/guard/src/main/java/cn/authing/guard/network/AuthClient.java +++ b/guard/src/main/java/cn/authing/guard/network/AuthClient.java @@ -363,6 +363,27 @@ public static void loginByWecom(AuthRequest authData, String authCode, @NotNull }); } + public static void loginByWecomAgency(String authCode, @NotNull AuthCallback callback) { + loginByWecomAgency(null, authCode, callback); + } + + public static void loginByWecomAgency(AuthRequest authData, String authCode, @NotNull AuthCallback callback) { + Authing.getPublicConfig(config -> { + try { + JSONObject body = new JSONObject(); + body.put("connId", config.getSocialConnectionId(Const.EC_TYPE_WECHAT_COM_AGENCY)); + body.put("code", authCode); + String endpoint = "/api/v2/ecConn/wechat-work-agency/authByCode"; + Guardian.post(endpoint, body, (data)-> { + startOidcInteraction(authData, data, callback); + }); + } catch (Exception e) { + e.printStackTrace(); + callback.call(500, "Exception", null); + } + }); + } + public static void loginByAlipay(String authCode, @NotNull AuthCallback callback) { loginByAlipay(null, authCode, callback); } diff --git a/guard/src/main/java/cn/authing/guard/network/OIDCClient.java b/guard/src/main/java/cn/authing/guard/network/OIDCClient.java index 916e43cc..55b5fe3d 100644 --- a/guard/src/main/java/cn/authing/guard/network/OIDCClient.java +++ b/guard/src/main/java/cn/authing/guard/network/OIDCClient.java @@ -111,6 +111,10 @@ public void loginByWecom(String authCode, @NotNull AuthCallback callba AuthClient.loginByWecom(authRequest, authCode, callback); } + public void loginByWecomAgency(String authCode, @NotNull AuthCallback callback) { + AuthClient.loginByWecomAgency(authRequest, authCode, callback); + } + public void loginByAlipay(String authCode, @NotNull AuthCallback callback) { AuthClient.loginByAlipay(authRequest, authCode, callback); } diff --git a/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java b/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java index e64557d5..d0065e7c 100644 --- a/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java +++ b/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java @@ -23,6 +23,7 @@ public abstract class SocialLoginButton extends androidx.appcompat.widget.AppCom protected SocialAuthenticator authenticator; protected AuthCallback callback; protected AnimatedVectorDrawable backgroundDrawable; + protected String type; public SocialLoginButton(Context context) { this(context, null); @@ -62,7 +63,7 @@ public SocialLoginButton(Context context, AttributeSet attrs) { public SocialLoginButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - authenticator = createAuthenticator(); + if (attrs == null || attrs.getAttributeValue(NS_ANDROID, "background") == null) { setBackgroundResource(R.drawable.ic_authing_circle); } @@ -73,9 +74,10 @@ public SocialLoginButton(Context context, AttributeSet attrs, int defStyleAttr) } setBackground(backgroundDrawable); backgroundDrawable.start(); - if (authenticator != null) { - authenticator.login(context, this::loginDone); + if (authenticator == null){ + authenticator = createAuthenticator(); } + authenticator.login(context, this::loginDone); })); } @@ -91,4 +93,8 @@ private boolean requiresAgreement() { public void setOnLoginListener(AuthCallback callback) { this.callback = callback; } + + public void setType(String type) { + this.type = type; + } } diff --git a/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java b/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java index d21823df..e951b712 100644 --- a/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java +++ b/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java @@ -56,17 +56,7 @@ public SocialLoginListView(Context context, AttributeSet attrs, int defStyleAttr List socialConfigs = config.getSocialConfigs(); for (int i = 0, n = socialConfigs.size();i < n;++i) { SocialConfig sc = socialConfigs.get(i); - String type = sc.getType(); - if ("wechat:mobile".equals(type)) { - sb.append("wechat"); - } else if ("alipay".equals(type)) { - sb.append("alipay"); - } else if (Const.EC_TYPE_WECHAT_COM.equals(type)) { - sb.append("wecom"); - } else if (Const.EC_TYPE_LARK_INTERNAL.equals(type) - || Const.EC_TYPE_LARK_PUBLIC.equals(type)) { - sb.append("lark"); - } + sb.append(sc.getType()); if (i < n - 1) { sb.append("|"); } @@ -82,20 +72,23 @@ private void setup(Context context, String s) { removeAllViews(); String[] sources = s.split("\\|"); for (String source : sources) { - String src = source.trim(); + String type = source.trim(); SocialLoginButton button = null; - switch (src) { - case "wechat": + switch (type) { + case Const.EC_TYPE_WECHAT: button = new WechatLoginButton(context); break; - case "alipay": + case Const.EC_TYPE_ALIPAY: button = new AlipayLoginButton(context); break; - case "wecom": + case Const.EC_TYPE_WECHAT_COM: + case Const.EC_TYPE_WECHAT_COM_AGENCY: button = new WeComLoginButton(context); + button.setType(type); break; - case "lark": + case Const.EC_TYPE_LARK_INTERNAL: + case Const.EC_TYPE_LARK_PUBLIC: button = new LarkLoginButton(context); break; } diff --git a/guard/src/main/java/cn/authing/guard/social/WeCom.java b/guard/src/main/java/cn/authing/guard/social/WeCom.java index 5ea1f04b..a2e05f7d 100644 --- a/guard/src/main/java/cn/authing/guard/social/WeCom.java +++ b/guard/src/main/java/cn/authing/guard/social/WeCom.java @@ -21,22 +21,31 @@ public class WeCom extends SocialAuthenticator { private static final String TAG = "WeCom"; + private final String type; public static String schema; public static String agentId; public static String corpId; + public WeCom() { + type = Const.EC_TYPE_WECHAT_COM; + } + + public WeCom(String type) { + this.type = type; + } + @Override public void login(Context context, @NotNull AuthCallback callback) { Authing.getPublicConfig(config -> { IWWAPI iwwapi = WWAPIFactory.createWWAPI(context); - String sch = (schema != null ) ? schema : config.getSocialSchema(Const.EC_TYPE_WECHAT_COM);; + String sch = (schema != null ) ? schema : config.getSocialSchema(type); iwwapi.registerApp(sch); final WWAuthMessage.Req req = new WWAuthMessage.Req(); req.sch = sch; - req.agentId = (agentId != null ) ? agentId : config.getSocialAgentId(Const.EC_TYPE_WECHAT_COM); - req.appId = (corpId != null ) ? corpId : config.getSocialAppId(Const.EC_TYPE_WECHAT_COM); - req.state = Const.EC_TYPE_WECHAT_COM; + req.agentId = (agentId != null ) ? agentId : config.getSocialAgentId(type); + req.appId = (corpId != null ) ? corpId : config.getSocialAppId(type); + req.state = type; iwwapi.sendMessage(req, resp -> { if (resp instanceof WWAuthMessage.Resp) { WWAuthMessage.Resp rsp = (WWAuthMessage.Resp) resp; @@ -59,12 +68,20 @@ public void login(Context context, @NotNull AuthCallback callback) { @Override protected void standardLogin(String authCode, @NonNull AuthCallback callback) { - AuthClient.loginByWecom(authCode, callback); + if (Const.EC_TYPE_WECHAT_COM.equals(type)) { + AuthClient.loginByWecom(authCode, callback); + } else if (Const.EC_TYPE_WECHAT_COM_AGENCY.equals(type)) { + AuthClient.loginByWecomAgency(authCode, callback); + } } @Override protected void oidcLogin(String authCode, @NonNull AuthCallback callback) { - new OIDCClient().loginByWecom(authCode, callback); + if (Const.EC_TYPE_WECHAT_COM.equals(type)) { + new OIDCClient().loginByWecom(authCode, callback); + } else if (Const.EC_TYPE_WECHAT_COM_AGENCY.equals(type)) { + new OIDCClient().loginByWecomAgency(authCode, callback); + } } private void fireCallback(AuthCallback callback, UserInfo info) { diff --git a/guard/src/main/java/cn/authing/guard/social/WeComLoginButton.java b/guard/src/main/java/cn/authing/guard/social/WeComLoginButton.java index 9c2b1d6d..3978f3b5 100644 --- a/guard/src/main/java/cn/authing/guard/social/WeComLoginButton.java +++ b/guard/src/main/java/cn/authing/guard/social/WeComLoginButton.java @@ -17,7 +17,7 @@ public WeComLoginButton(@NonNull Context context) { @Override protected SocialAuthenticator createAuthenticator() { - return new WeCom(); + return new WeCom(type); } public WeComLoginButton(@NonNull Context context, @Nullable AttributeSet attrs) { diff --git a/guard/src/main/java/cn/authing/guard/util/Const.java b/guard/src/main/java/cn/authing/guard/util/Const.java index 9e5338fd..8626ff55 100644 --- a/guard/src/main/java/cn/authing/guard/util/Const.java +++ b/guard/src/main/java/cn/authing/guard/util/Const.java @@ -21,6 +21,7 @@ public class Const { public static final String EC_TYPE_WECHAT = "wechat:mobile"; public static final String EC_TYPE_WECHAT_COM = "wechatwork:mobile"; + public static final String EC_TYPE_WECHAT_COM_AGENCY = "wechatwork:agency:mobile"; public static final String EC_TYPE_ALIPAY = "alipay"; public static final String EC_TYPE_LARK_INTERNAL = "lark-internal"; public static final String EC_TYPE_LARK_PUBLIC = "lark-public"; From feda07f96c2f0e97305295a4f13e1354d651249c Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Thu, 4 Aug 2022 14:20:17 +0800 Subject: [PATCH 06/64] add verifying accounts and passwords api --- .../cn/authing/guard/network/AuthClient.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/guard/src/main/java/cn/authing/guard/network/AuthClient.java b/guard/src/main/java/cn/authing/guard/network/AuthClient.java index 4a800909..90291fee 100644 --- a/guard/src/main/java/cn/authing/guard/network/AuthClient.java +++ b/guard/src/main/java/cn/authing/guard/network/AuthClient.java @@ -11,6 +11,7 @@ import org.json.JSONObject; import java.io.InputStream; +import java.net.URLEncoder; import java.util.Iterator; import java.util.List; @@ -953,6 +954,18 @@ public static void loginByScannedTicket(String ticket, @NotNull AuthCallback callback) { + try { + String endpoint = "/api/v2/qrcode/cancel"; + JSONObject body = new JSONObject(); + body.put("random", ticket); + Guardian.post(endpoint, body, (data)-> callback.call(data.getCode(), data.getMessage(), data.getData())); + } catch (Exception e) { + e.printStackTrace(); + callback.call(500, "Exception", null); + } + } + public static void createUserInfoFromResponse(Response data, @NotNull AuthCallback callback) { createUserInfoFromResponse(new UserInfo(), data, callback); } @@ -991,6 +1004,27 @@ public static void createUserInfoFromResponse(UserInfo userInfo, Response data, } } + public static void checkPassword(String password, @NotNull AuthCallback callback) { + try { + String encryptPassword = URLEncoder.encode(Util.encryptPassword(password), "UTF-8"); + String endpoint = "/api/v2/users/password/check?password=" + encryptPassword; + Guardian.get(endpoint, (data)-> callback.call(data.getCode(), data.getMessage(), data.getData())); + } catch (Exception e) { + e.printStackTrace(); + callback.call(500, "Exception", null); + } + } + + public static void checkAccount(String paramsName, String paramsValue, @NotNull AuthCallback callback) { + try { + String endpoint = "/api/v2/users/is-user-exists?" + paramsName +"=" + paramsValue; + Guardian.get(endpoint, (data)-> callback.call(data.getCode(), data.getMessage(), data.getData())); + } catch (Exception e) { + e.printStackTrace(); + callback.call(500, "Exception", null); + } + } + private static void startOidcInteraction(AuthRequest authData, Response data, @NotNull AuthCallback callback){ if (authData == null) { createUserInfoFromResponse(data, callback); From d8a379ccaad2f2e779cef853e4d4a5b107875cad Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Fri, 5 Aug 2022 14:06:21 +0800 Subject: [PATCH 07/64] update version 1.3.8 --- app/build.gradle | 2 +- guard/gradle.properties | 2 +- guard/src/main/java/cn/authing/guard/util/Const.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1a68b2ae..7c281dc9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { minSdk 24 targetSdk 31 versionCode 1 - versionName "1.3.7" + versionName "1.3.8" archivesBaseName = "GuardDemo-$versionName" } diff --git a/guard/gradle.properties b/guard/gradle.properties index 55f6cea1..46a8e403 100644 --- a/guard/gradle.properties +++ b/guard/gradle.properties @@ -1,6 +1,6 @@ GROUP=cn.authing POM_ARTIFACT_ID=guard -VERSION_NAME=1.3.7 +VERSION_NAME=1.3.8 POM_NAME=guard POM_PACKAGING=aar diff --git a/guard/src/main/java/cn/authing/guard/util/Const.java b/guard/src/main/java/cn/authing/guard/util/Const.java index 8626ff55..e3023f94 100644 --- a/guard/src/main/java/cn/authing/guard/util/Const.java +++ b/guard/src/main/java/cn/authing/guard/util/Const.java @@ -5,7 +5,7 @@ public class Const { public final static String NS_ANDROID = "http://schemas.android.com/apk/res/android"; - public static final String SDK_VERSION = "1.3.7"; + public static final String SDK_VERSION = "1.3.8"; public final static int EC_MFA_REQUIRED = 1636; public final static int EC_FIRST_TIME_LOGIN = 1639; From 13d555a12d3110aac9a67b97a557cac30a78b404 Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Wed, 10 Aug 2022 14:29:03 +0800 Subject: [PATCH 08/64] support i18n of extended fields --- .../complete/UserInfoCompleteContainer.java | 38 ++++++- .../java/cn/authing/guard/data/Config.java | 13 +++ .../main/java/cn/authing/guard/util/Util.java | 12 +++ guard/src/main/res/values-zh-rTW/strings.xml | 100 +++++++++--------- guard/src/main/res/values/strings.xml | 30 +++--- 5 files changed, 127 insertions(+), 66 deletions(-) diff --git a/guard/src/main/java/cn/authing/guard/complete/UserInfoCompleteContainer.java b/guard/src/main/java/cn/authing/guard/complete/UserInfoCompleteContainer.java index 6b29d54f..34b4e8f2 100644 --- a/guard/src/main/java/cn/authing/guard/complete/UserInfoCompleteContainer.java +++ b/guard/src/main/java/cn/authing/guard/complete/UserInfoCompleteContainer.java @@ -9,14 +9,19 @@ import androidx.annotation.Nullable; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.ArrayList; import java.util.List; +import cn.authing.guard.Authing; import cn.authing.guard.MandatoryField; import cn.authing.guard.activity.AuthActivity; import cn.authing.guard.analyze.Analyzer; import cn.authing.guard.data.ExtendedField; import cn.authing.guard.flow.AuthFlow; +import cn.authing.guard.util.Util; public class UserInfoCompleteContainer extends LinearLayout { public UserInfoCompleteContainer(Context context) { @@ -89,11 +94,42 @@ private View inflateItem(int layoutId, ExtendedField field) { if (!field.isRequired()) { label.setAsteriskPosition(0); } - label.setMandatoryText(field.getLabel()); + setLabelName(label, field); } return view; } + private void setLabelName(MandatoryField label, ExtendedField field){ + label.setMandatoryText(field.getLabel()); + String name = field.getName(); + if (Util.isNull(name)){ + return; + } + + String language = Util.getAppLanguage(); + Authing.getPublicConfig(config -> { + JSONObject extendedFieldsI18n = config.getExtendedFieldsI18n(); + if (extendedFieldsI18n == null){ + return; + } + if (extendedFieldsI18n.has(name)){ + try { + JSONObject nameObj = extendedFieldsI18n.getJSONObject(name); + if (nameObj.has(language)){ + JSONObject languageObj = nameObj.getJSONObject(language); + boolean enabled = languageObj.getBoolean("enabled"); + if (enabled){ + label.setMandatoryText(languageObj.getString("value")); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + }); + + } + public List getValues() { List fields = new ArrayList<>(); for (int i = 0;i < getChildCount();++i) { diff --git a/guard/src/main/java/cn/authing/guard/data/Config.java b/guard/src/main/java/cn/authing/guard/data/Config.java index 6dca9220..d4660481 100644 --- a/guard/src/main/java/cn/authing/guard/data/Config.java +++ b/guard/src/main/java/cn/authing/guard/data/Config.java @@ -34,6 +34,7 @@ public interface ConfigCallback { private int passwordStrength; private List completeFieldsPlace; private List extendedFields; + private JSONObject extendedFieldsI18n; private List redirectUris = new ArrayList<>(); private boolean internationalSmsEnable; private String userAgent; @@ -108,6 +109,10 @@ public static Config parse(JSONObject data) throws JSONException { config.setExtendedFields(toExtendedFields(data.getJSONArray("extendsFields"))); } + if (data.has("extendsFieldsI18n")) { + config.setExtendedFieldsI18n(data.getJSONObject("extendsFieldsI18n")); + } + if (data.has("redirectUris")) { config.setRedirectUris(toStringList(data.getJSONArray("redirectUris"))); } @@ -249,6 +254,14 @@ public void setExtendedFields(List extendedFields) { this.extendedFields = extendedFields; } + public JSONObject getExtendedFieldsI18n() { + return extendedFieldsI18n; + } + + public void setExtendedFieldsI18n(JSONObject extendedFieldsI18n) { + this.extendedFieldsI18n = extendedFieldsI18n; + } + public List getRedirectUris() { return redirectUris; } diff --git a/guard/src/main/java/cn/authing/guard/util/Util.java b/guard/src/main/java/cn/authing/guard/util/Util.java index e7165671..41754a6c 100644 --- a/guard/src/main/java/cn/authing/guard/util/Util.java +++ b/guard/src/main/java/cn/authing/guard/util/Util.java @@ -348,6 +348,18 @@ public static boolean isCn(){ return !Util.isNull(lang) && lang.contains("zh"); } + public static String getAppLanguage() { + String country = Locale.getDefault().getCountry(); + if ("TW".equals(country)) { + return "zh-TW"; + } else if("US".equals(country)) { + return "en-US"; + } else if("JP".equals(country)) { + return "JP"; + } + return "zh-CN"; + } + public static String getLangHeader() { String lang = Locale.getDefault().getLanguage(); return (!Util.isNull(lang) && lang.contains("zh")) ? "zh-CN" : "en-US"; diff --git a/guard/src/main/res/values-zh-rTW/strings.xml b/guard/src/main/res/values-zh-rTW/strings.xml index a5b722ec..88b23745 100644 --- a/guard/src/main/res/values-zh-rTW/strings.xml +++ b/guard/src/main/res/values-zh-rTW/strings.xml @@ -1,56 +1,56 @@ 請輸入 - 用戶名 - 郵箱 - 手機號 + 帳號 + 電子郵件 + 手機號碼 請輸入密碼 請再次輸入密碼 - 登錄 + 登入 請輸入驗證碼 請輸入圖形驗證碼 發送驗證碼 - 帳號密碼登錄 - 用短信驗證碼登錄 - %1$d 秒後獲取 + 帳號密碼登入 + 用短信驗證碼登入 + %1$d 秒後獲得 註冊 歡迎加入 短信驗證碼 - 郵箱驗證碼 - 密碼登錄 - 手機號註冊 - 郵箱註冊 - 郵箱驗證碼註冊 - 立即登錄 + 電子郵件驗證碼 + 帳號 + 手機號碼註冊 + 電子郵件註冊 + 電子郵件驗證碼註冊 + 立即登入 沒有帳號? 立即註冊 - 第三方帳號登錄 + 第三方帳號登入 忘記密碼? 找回密碼 - 重置密碼 - 請輸入手機號或郵箱 - 其他帳號登錄 - 密碼重置郵件已發送至 %1$s, 有效期為 5 分鐘 - 重新發送密碼重置郵件 + 重設密碼 + 請輸入手機號碼或電子郵件 + 其他帳號登入 + 密碼重設郵件已發送至 %1$s, 有效期為 5 分鐘 + 重新發送密碼重設郵件 綁定 解綁 - 綁定電子郵箱 - 驗證碼將發送至填入郵箱 - 請輸入郵箱驗證碼 - 綁定手機號 - 您未綁定手機號,請輸入手機號綁定 + 綁定電子電子郵件 + 驗證碼將發送至填入電子郵件 + 請輸入電子郵件驗證碼 + 綁定手機號碼 + 您未綁定手機號碼,請輸入手機號碼綁定 驗證碼已發送至 請輸入短信驗證碼 - 帳號登錄驗證 - 請輸入獲取的 6 位數字安全碼 + 帳號登入驗證 + 請輸入獲得的 6 位數字安全碼 安全碼丟失? 恢復代碼 使用恢復代碼 - 登錄成功後,我們將生成一個新的恢復代碼 + 登入成功後,我們將生成一個新的恢復代碼 已安全地記錄了這段密鑰 已復制 其他驗證方式 手機驗證 - 郵箱驗證 + 電子郵件驗證 安全碼驗證 完善帳號信息 為了更好的使用體驗,請先完善您的資料信息 @@ -59,13 +59,13 @@ 為了保障帳號安全,請設置初始密碼 此頁面的有效期為 10 分鐘 - 手機號一鍵登錄 - 本機號碼一鍵登錄 - 其他方式登錄 - 退出登錄 + 手機號碼一鍵登入 + 本機號碼一鍵登入 + 其他方式登入 + 退出登入 註銷帳號 生物認證 - 用生物信息登錄 + 用生物信息登入 選擇國家或地區代碼 搜索 取消 @@ -75,7 +75,7 @@ 未定義 請輸入舊密碼 頭像 - 呢稱 + 暱稱 姓名 修改密碼 更新資料 @@ -90,19 +90,19 @@ 開發者 - 問題反饋 - 聯繫方式 + 幫助中心 + 聯絡方式 相關問題 問題描述 - 問題截圖 + 截圖 上傳圖片 - 聯繫方式為必填項 + 聯絡方式為必填項 無法收到驗證碼 - 無法登錄 + 無法登入 無法註冊 - 帳號丟失 - 無法重置密碼 - 帳號鎖定 + 帳號遺失 + 無法重設密碼 + 帳號鎖住 其他 提交成功 @@ -121,17 +121,17 @@ 兩次輸入的密碼必須一致 發送短信失敗:無效手機號碼 未選擇國家碼 - 手機號填寫錯誤 + 手機號碼填寫錯誤 驗證碼不正確 - 用戶名或密碼錯誤 - 郵箱格式不正確 + 帳號或密碼錯誤 + 電子郵件格式不正確 電話號碼格式不正確 輸入格式不正確 - 請輸入正確的手機號碼或郵箱 - 郵箱驗證碼獲取失敗 + 請輸入正確的手機號碼或電子郵件 + 電子郵件驗證碼獲得失敗 手機號碼已經被綁定 - 郵箱已經被綁定 + 電子郵件已經被綁定 在 60 秒內已發送短信驗證碼 - %1$s不能為空 - 帳號密碼不能為空 + 請填入%1$s + 請填入帳號密碼 \ No newline at end of file diff --git a/guard/src/main/res/values/strings.xml b/guard/src/main/res/values/strings.xml index 8c187345..03fc7319 100644 --- a/guard/src/main/res/values/strings.xml +++ b/guard/src/main/res/values/strings.xml @@ -3,12 +3,12 @@ User Name Email Phone - Please input password + Enter password Confirm password Login - Please input verify code - Please input captcha code - Get Verify Code + Enter verify code + Enter captcha code + Send Code Login by account and password Login by SMS code Re-send after %1$d seconds @@ -23,7 +23,7 @@ Sign In Instead No account? Sign up Now - Continue with + COr sign in with Forgot password? Reset password @string/authing_find_password_back @@ -35,7 +35,7 @@ Unbind Bind email Verify code will be sent to the email below - Please input email code + Enter email code Bind mobile phone number You have not bound your phone number, please enter your phone number to bind Code was sent to @@ -90,18 +90,18 @@ Developer - Feedback - Contact information - Related issue - Description + Need help? + Contact + Problem + Problem description Screen shot Add Contact information cannot be empty - Cannot get verify code - Cannot login - Cannot register - Lost my account - Cannot reset password + Unable to receive the verification code + Unable to log in + Unable to register + Lost Account + Unable to reset password Account is locked Other Submit successfully From c73375f0d16e0e996608abc1ca2229cc8c3082bd Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Wed, 10 Aug 2022 14:31:19 +0800 Subject: [PATCH 09/64] MFA process added information completion --- .../cn/authing/guard/mfa/MFABaseButton.java | 67 +++++++++++++++++++ .../cn/authing/guard/mfa/MFAEmailButton.java | 13 +--- .../cn/authing/guard/mfa/MFAOTPButton.java | 16 +---- .../cn/authing/guard/mfa/MFAPhoneButton.java | 13 +--- .../authing/guard/mfa/MFARecoveryButton.java | 10 ++- 5 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 guard/src/main/java/cn/authing/guard/mfa/MFABaseButton.java diff --git a/guard/src/main/java/cn/authing/guard/mfa/MFABaseButton.java b/guard/src/main/java/cn/authing/guard/mfa/MFABaseButton.java new file mode 100644 index 00000000..5923c804 --- /dev/null +++ b/guard/src/main/java/cn/authing/guard/mfa/MFABaseButton.java @@ -0,0 +1,67 @@ +package cn.authing.guard.mfa; + +import android.content.Context; +import android.content.Intent; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; + +import cn.authing.guard.Authing; +import cn.authing.guard.activity.AuthActivity; +import cn.authing.guard.data.Config; +import cn.authing.guard.data.ExtendedField; +import cn.authing.guard.data.UserInfo; +import cn.authing.guard.flow.AuthFlow; +import cn.authing.guard.flow.FlowHelper; +import cn.authing.guard.internal.LoadingButton; +import cn.authing.guard.util.Util; + +public class MFABaseButton extends LoadingButton { + + + public MFABaseButton(@NonNull Context context) { + super(context); + } + + public MFABaseButton(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public MFABaseButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + + protected void mfaOk(int code, String message, UserInfo userInfo) { + Authing.getPublicConfig((config)->{ + if (getContext() instanceof AuthActivity) { + AuthActivity activity = (AuthActivity) getContext(); + AuthFlow flow = (AuthFlow) activity.getIntent().getSerializableExtra(AuthActivity.AUTH_FLOW); + List missingFields = FlowHelper.missingFields(config, userInfo); + if (shouldCompleteAfterLogin(config) && missingFields.size() > 0) { + flow.getData().put(AuthFlow.KEY_USER_INFO, userInfo); + FlowHelper.handleUserInfoComplete(this, missingFields); + } else { + AuthFlow.Callback cb = flow.getAuthCallback(); + if (cb != null) { + cb.call(getContext(), code, message, userInfo); + } + + Intent intent = new Intent(); + intent.putExtra("user", userInfo); + activity.setResult(AuthActivity.OK, intent); + activity.finish(); + } + } + }); + } + + + private boolean shouldCompleteAfterLogin(Config config) { + List complete = config.getCompleteFieldsPlace(); + return complete != null && complete.contains("login"); + } +} diff --git a/guard/src/main/java/cn/authing/guard/mfa/MFAEmailButton.java b/guard/src/main/java/cn/authing/guard/mfa/MFAEmailButton.java index 1355c378..7507befc 100644 --- a/guard/src/main/java/cn/authing/guard/mfa/MFAEmailButton.java +++ b/guard/src/main/java/cn/authing/guard/mfa/MFAEmailButton.java @@ -21,11 +21,10 @@ import cn.authing.guard.analyze.Analyzer; import cn.authing.guard.data.UserInfo; import cn.authing.guard.flow.AuthFlow; -import cn.authing.guard.internal.LoadingButton; import cn.authing.guard.network.AuthClient; import cn.authing.guard.util.Util; -public class MFAEmailButton extends LoadingButton implements AuthActivity.EventListener { +public class MFAEmailButton extends MFABaseButton implements AuthActivity.EventListener { public MFAEmailButton(@NonNull Context context) { this(context, null); @@ -166,15 +165,7 @@ private void doMFA(View v) { private void mfaDone(int code, String message, UserInfo userInfo) { stopLoadingVisualEffect(); if (code == 200) { - try { - AuthActivity activity = (AuthActivity) getContext(); - Intent intent = new Intent(); - intent.putExtra("user", userInfo); - activity.setResult(AuthActivity.OK, intent); - activity.finish(); - } catch (Exception e) { - e.printStackTrace(); - } + mfaOk(code, message, userInfo); } else { Util.setErrorText(this, message); } diff --git a/guard/src/main/java/cn/authing/guard/mfa/MFAOTPButton.java b/guard/src/main/java/cn/authing/guard/mfa/MFAOTPButton.java index ffbca5ec..0d30675d 100644 --- a/guard/src/main/java/cn/authing/guard/mfa/MFAOTPButton.java +++ b/guard/src/main/java/cn/authing/guard/mfa/MFAOTPButton.java @@ -3,7 +3,6 @@ import static cn.authing.guard.util.Const.NS_ANDROID; import android.content.Context; -import android.content.Intent; import android.graphics.Color; import android.util.AttributeSet; import android.view.View; @@ -11,18 +10,15 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.json.JSONException; - import cn.authing.guard.R; import cn.authing.guard.VerifyCodeEditText; import cn.authing.guard.activity.AuthActivity; import cn.authing.guard.analyze.Analyzer; import cn.authing.guard.data.UserInfo; -import cn.authing.guard.internal.LoadingButton; import cn.authing.guard.network.AuthClient; import cn.authing.guard.util.Util; -public class MFAOTPButton extends LoadingButton implements AuthActivity.EventListener { +public class MFAOTPButton extends MFABaseButton implements AuthActivity.EventListener { public MFAOTPButton(@NonNull Context context) { this(context, null); @@ -71,15 +67,7 @@ private void doMFA() { private void mfaDone(int code, String message, UserInfo userInfo) { stopLoadingVisualEffect(); if (code == 200) { - try { - AuthActivity activity = (AuthActivity) getContext(); - Intent intent = new Intent(); - intent.putExtra("user", userInfo); - activity.setResult(AuthActivity.OK, intent); - activity.finish(); - } catch (Exception e) { - e.printStackTrace(); - } + mfaOk(code, message, userInfo); } else { Util.setErrorText(this, message); } diff --git a/guard/src/main/java/cn/authing/guard/mfa/MFAPhoneButton.java b/guard/src/main/java/cn/authing/guard/mfa/MFAPhoneButton.java index fe109bf1..89b26176 100644 --- a/guard/src/main/java/cn/authing/guard/mfa/MFAPhoneButton.java +++ b/guard/src/main/java/cn/authing/guard/mfa/MFAPhoneButton.java @@ -21,11 +21,10 @@ import cn.authing.guard.analyze.Analyzer; import cn.authing.guard.data.UserInfo; import cn.authing.guard.flow.AuthFlow; -import cn.authing.guard.internal.LoadingButton; import cn.authing.guard.network.AuthClient; import cn.authing.guard.util.Util; -public class MFAPhoneButton extends LoadingButton { +public class MFAPhoneButton extends MFABaseButton { public MFAPhoneButton(@NonNull Context context) { this(context, null); @@ -165,15 +164,7 @@ private void next(AuthFlow flow) { private void mfaDone(int code, String message, UserInfo userInfo) { stopLoadingVisualEffect(); if (code == 200) { - try { - AuthActivity activity = (AuthActivity) getContext(); - Intent intent = new Intent(); - intent.putExtra("user", userInfo); - activity.setResult(AuthActivity.OK, intent); - activity.finish(); - } catch (Exception e) { - e.printStackTrace(); - } + mfaOk(code, message, userInfo); } else if (code == 500 && message.startsWith("duplicate key value violates unique constraint")) { Util.setErrorText(this, "Phone number already bound by another user"); } else { diff --git a/guard/src/main/java/cn/authing/guard/mfa/MFARecoveryButton.java b/guard/src/main/java/cn/authing/guard/mfa/MFARecoveryButton.java index 25314aa7..962df7f1 100644 --- a/guard/src/main/java/cn/authing/guard/mfa/MFARecoveryButton.java +++ b/guard/src/main/java/cn/authing/guard/mfa/MFARecoveryButton.java @@ -19,11 +19,10 @@ import cn.authing.guard.analyze.Analyzer; import cn.authing.guard.data.UserInfo; import cn.authing.guard.flow.AuthFlow; -import cn.authing.guard.internal.LoadingButton; import cn.authing.guard.network.AuthClient; import cn.authing.guard.util.Util; -public class MFARecoveryButton extends LoadingButton { +public class MFARecoveryButton extends MFABaseButton { private String recoveryCode; @@ -126,9 +125,8 @@ private void mfaDone(int code, String message, UserInfo userInfo) { private void done() { AuthActivity activity = (AuthActivity) getContext(); AuthFlow flow = activity.getFlow(); - Intent intent = new Intent(); - intent.putExtra("user", (UserInfo) flow.getData().get(KEY_USER_INFO)); - activity.setResult(AuthActivity.OK, intent); - activity.finish(); + UserInfo userInfo = (UserInfo) flow.getData().get(KEY_USER_INFO); + + mfaOk(200, "", userInfo); } } From 980ac590df64efcb82ae083762aaa70d65396af3 Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Wed, 10 Aug 2022 16:09:41 +0800 Subject: [PATCH 10/64] update version 1.3.9 --- app/build.gradle | 2 +- guard/gradle.properties | 2 +- guard/src/main/java/cn/authing/guard/util/Const.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7c281dc9..855c8aaa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { minSdk 24 targetSdk 31 versionCode 1 - versionName "1.3.8" + versionName "1.3.9" archivesBaseName = "GuardDemo-$versionName" } diff --git a/guard/gradle.properties b/guard/gradle.properties index 46a8e403..930d3896 100644 --- a/guard/gradle.properties +++ b/guard/gradle.properties @@ -1,6 +1,6 @@ GROUP=cn.authing POM_ARTIFACT_ID=guard -VERSION_NAME=1.3.8 +VERSION_NAME=1.3.9 POM_NAME=guard POM_PACKAGING=aar diff --git a/guard/src/main/java/cn/authing/guard/util/Const.java b/guard/src/main/java/cn/authing/guard/util/Const.java index e3023f94..7cfb3af9 100644 --- a/guard/src/main/java/cn/authing/guard/util/Const.java +++ b/guard/src/main/java/cn/authing/guard/util/Const.java @@ -5,7 +5,7 @@ public class Const { public final static String NS_ANDROID = "http://schemas.android.com/apk/res/android"; - public static final String SDK_VERSION = "1.3.8"; + public static final String SDK_VERSION = "1.3.9"; public final static int EC_MFA_REQUIRED = 1636; public final static int EC_FIRST_TIME_LOGIN = 1639; From a770242eb192ad22457449e27e95ee3ec28f31fe Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Fri, 19 Aug 2022 20:41:38 +0800 Subject: [PATCH 11/64] support google login --- guard/build.gradle | 2 + .../java/cn/authing/guard/MandatoryField.java | 2 +- .../authing/guard/activity/AuthActivity.java | 6 + .../java/cn/authing/guard/data/Config.java | 68 ++++++----- .../cn/authing/guard/data/SocialConfig.java | 9 ++ .../cn/authing/guard/network/AuthClient.java | 22 ++++ .../cn/authing/guard/network/OIDCClient.java | 4 + .../java/cn/authing/guard/social/Google.java | 111 ++++++++++++++++++ .../guard/social/GoogleLoginButton.java | 28 +++++ .../guard/social/SocialAuthenticator.java | 4 + .../guard/social/SocialLoginButton.java | 8 ++ .../guard/social/SocialLoginListView.java | 3 + .../java/cn/authing/guard/util/Const.java | 1 + .../main/res/drawable/ic_authing_google.xml | 8 ++ 14 files changed, 246 insertions(+), 30 deletions(-) create mode 100644 guard/src/main/java/cn/authing/guard/social/Google.java create mode 100644 guard/src/main/java/cn/authing/guard/social/GoogleLoginButton.java create mode 100644 guard/src/main/res/drawable/ic_authing_google.xml diff --git a/guard/build.gradle b/guard/build.gradle index 8ec60baa..be82b9bb 100644 --- a/guard/build.gradle +++ b/guard/build.gradle @@ -37,4 +37,6 @@ dependencies { compileOnly files('libs/lib_wwapi-2.0.12.11.aar') compileOnly files('libs/alipaysdk.aar') compileOnly files ('libs/larksso-3.0.8.aar') + compileOnly 'com.google.android.gms:play-services-auth:20.2.0' + } diff --git a/guard/src/main/java/cn/authing/guard/MandatoryField.java b/guard/src/main/java/cn/authing/guard/MandatoryField.java index 2654a4a7..641b98e9 100644 --- a/guard/src/main/java/cn/authing/guard/MandatoryField.java +++ b/guard/src/main/java/cn/authing/guard/MandatoryField.java @@ -54,7 +54,7 @@ public void setMandatoryText(CharSequence text) { int length = span.length(); span.setSpan(new ForegroundColorSpan(Color.parseColor("#ff831827")), length - 1, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE); } else { - span = new SpannableString(text); + span = new SpannableString(text != null ? text : ""); } setText(span); } diff --git a/guard/src/main/java/cn/authing/guard/activity/AuthActivity.java b/guard/src/main/java/cn/authing/guard/activity/AuthActivity.java index 7b907e9c..a30b7c62 100644 --- a/guard/src/main/java/cn/authing/guard/activity/AuthActivity.java +++ b/guard/src/main/java/cn/authing/guard/activity/AuthActivity.java @@ -27,6 +27,7 @@ import cn.authing.guard.data.UserInfo; import cn.authing.guard.flow.AuthFlow; import cn.authing.guard.internal.CircularAnimatedView; +import cn.authing.guard.social.Google; import cn.authing.guard.util.Util; public class AuthActivity extends AppCompatActivity { @@ -126,8 +127,13 @@ protected void onActivityResult(int requestCode, int resultCode, @Nullable Inten setResult(OK, intent); finish(); } + if (requestCode == Google.RC_SIGN_IN && data != null) { + data.setAction("cn.authing.guard.broadcast.GOOGLE_LOGIN"); + sendBroadcast(data); + } } + private void showLoading() { if (!Authing.isGettingConfig()) { loadingContainer.setVisibility(View.GONE); diff --git a/guard/src/main/java/cn/authing/guard/data/Config.java b/guard/src/main/java/cn/authing/guard/data/Config.java index d4660481..0ba3cc9e 100644 --- a/guard/src/main/java/cn/authing/guard/data/Config.java +++ b/guard/src/main/java/cn/authing/guard/data/Config.java @@ -306,35 +306,6 @@ public String getSocialBusinessId(String type) { return getSocialValue(type, "businessId"); } - public String getSocialValue(String type, String fieldName) { - String value = ""; - List configs = getSocialConfigs(); - for (SocialConfig c : configs) { - String provider = c.getType(); - if (type.equalsIgnoreCase(provider)) { - switch (fieldName){ - case "connectionId": - value = c.getId(); - break; - case "appId": - value = c.getAppId(); - break; - case "agentId": - value = c.getAgentId(); - break; - case "schema": - value = c.getSchema(); - break; - case "businessId": - value = c.getBusinessId(); - break; - } - break; - } - } - return value; - } - private static List toSocialList(JSONArray array) throws JSONException { List list = new ArrayList<>(); int size = array.length(); @@ -370,12 +341,51 @@ private static List toSocialList(JSONArray array) throws JSONExcep if (fields.has("businessId")) { config.setBusinessId(fields.getString("businessId")); } + if (fields.has("clientID")) { + config.setClientId(fields.getString("clientID")); + } } list.add(config); } return list; } + public String getSocialClientId(String type) { + return getSocialValue(type, "clientId"); + } + + public String getSocialValue(String type, String fieldName) { + String value = ""; + List configs = getSocialConfigs(); + for (SocialConfig c : configs) { + String provider = c.getType(); + if (type.equalsIgnoreCase(provider)) { + switch (fieldName){ + case "connectionId": + value = c.getId(); + break; + case "appId": + value = c.getAppId(); + break; + case "agentId": + value = c.getAgentId(); + break; + case "schema": + value = c.getSchema(); + break; + case "businessId": + value = c.getBusinessId(); + break; + case "clientId": + value = c.getClientId(); + break; + } + break; + } + } + return value; + } + private static List toAgreementList(JSONArray array) throws JSONException { List list = new ArrayList<>(); int size = array.length(); diff --git a/guard/src/main/java/cn/authing/guard/data/SocialConfig.java b/guard/src/main/java/cn/authing/guard/data/SocialConfig.java index 378d29f4..c433db85 100644 --- a/guard/src/main/java/cn/authing/guard/data/SocialConfig.java +++ b/guard/src/main/java/cn/authing/guard/data/SocialConfig.java @@ -7,6 +7,7 @@ public class SocialConfig { private String agentId; private String schema; private String businessId; + private String clientId; public String getId() { return id; @@ -55,4 +56,12 @@ public String getBusinessId() { public void setBusinessId(String businessId) { this.businessId = businessId; } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } } diff --git a/guard/src/main/java/cn/authing/guard/network/AuthClient.java b/guard/src/main/java/cn/authing/guard/network/AuthClient.java index 90291fee..0da3153b 100644 --- a/guard/src/main/java/cn/authing/guard/network/AuthClient.java +++ b/guard/src/main/java/cn/authing/guard/network/AuthClient.java @@ -429,6 +429,28 @@ public static void loginByLark(AuthRequest authData, String authCode, @NotNull A }); } + public static void loginByGoogle(String authCode, @NotNull AuthCallback callback) { + loginByGoogle(null, authCode, callback); + } + + public static void loginByGoogle(AuthRequest authData, String authCode, @NotNull AuthCallback callback) { + Authing.getPublicConfig(config -> { + try { + JSONObject body = new JSONObject(); + String connId = config.getSocialConnectionId(Const.EC_TYPE_GOOGLE); + body.put("connId", connId); + body.put("code", authCode); + String endpoint = "/api/v2/ecConn/google/authByCode"; + Guardian.post(endpoint, body, (data)-> { + startOidcInteraction(authData, data, callback); + }); + } catch (Exception e) { + e.printStackTrace(); + callback.call(500, "Exception", null); + } + }); + } + public static void loginByOneAuth(String token, String accessToken, @NotNull AuthCallback callback) { loginByOneAuth(null, token, accessToken, callback); } diff --git a/guard/src/main/java/cn/authing/guard/network/OIDCClient.java b/guard/src/main/java/cn/authing/guard/network/OIDCClient.java index 55b5fe3d..4346ad11 100644 --- a/guard/src/main/java/cn/authing/guard/network/OIDCClient.java +++ b/guard/src/main/java/cn/authing/guard/network/OIDCClient.java @@ -123,6 +123,10 @@ public void loginByLark(String authCode, @NotNull AuthCallback callbac AuthClient.loginByLark(authRequest, authCode, callback); } + public void loginByGoogle(String authCode, @NotNull AuthCallback callback) { + AuthClient.loginByGoogle(authRequest, authCode, callback); + } + public void authByCode(String code, @NotNull AuthCallback callback) { long now = System.currentTimeMillis(); Authing.getPublicConfig(config -> { diff --git a/guard/src/main/java/cn/authing/guard/social/Google.java b/guard/src/main/java/cn/authing/guard/social/Google.java new file mode 100644 index 00000000..2ee59f78 --- /dev/null +++ b/guard/src/main/java/cn/authing/guard/social/Google.java @@ -0,0 +1,111 @@ +package cn.authing.guard.social; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +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.api.ApiException; +import com.google.android.gms.tasks.Task; + +import cn.authing.guard.AuthCallback; +import cn.authing.guard.Authing; +import cn.authing.guard.data.UserInfo; +import cn.authing.guard.network.AuthClient; +import cn.authing.guard.network.OIDCClient; +import cn.authing.guard.util.ALog; +import cn.authing.guard.util.Const; + +public class Google extends SocialAuthenticator{ + + public static final int RC_SIGN_IN = 1000; + private Context context; + private AuthCallback callback; + private GoogleLoginReceiver googleLoginReceiver; + + @Override + public void login(Context context, @NonNull AuthCallback callback) { + this.context = context; + this.callback = callback; + Authing.getPublicConfig(config -> { + if (config == null) { + return; + } + + registerReceiver(); + + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestServerAuthCode(config.getSocialClientId(Const.EC_TYPE_GOOGLE)) + .requestEmail() + .requestId() + .requestProfile() + .build(); + GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(context, gso); + + Intent intent = googleSignInClient.getSignInIntent(); + ((Activity)context).startActivityForResult(intent, RC_SIGN_IN); + }); + + } + + private void registerReceiver(){ + if (context == null){ + return; + } + IntentFilter intentFilter =new IntentFilter(); + intentFilter.addAction("cn.authing.guard.broadcast.GOOGLE_LOGIN"); + googleLoginReceiver =new GoogleLoginReceiver(); + context.registerReceiver(googleLoginReceiver, intentFilter); + } + + public void unregisterReceiver(){ + if (context == null || googleLoginReceiver == null){ + return; + } + context.unregisterReceiver(googleLoginReceiver); + } + + private void handleSignInResult(Context context, @Nullable Intent data) { + Task task = GoogleSignIn.getSignedInAccountFromIntent(data); + + try { + GoogleSignInAccount account = task.getResult(ApiException.class); + login(context, account.getServerAuthCode(), callback); + } catch (ApiException e) { + ALog.e("Google", e.toString()); + callback.call(500, "Login by google failed", null); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + unregisterReceiver(); + } + + @Override + protected void standardLogin(String authCode, @NonNull AuthCallback callback) { + AuthClient.loginByGoogle(authCode, callback); + } + + @Override + protected void oidcLogin(String authCode, @NonNull AuthCallback callback) { + new OIDCClient().loginByGoogle(authCode, callback); + } + + private class GoogleLoginReceiver extends BroadcastReceiver{ + + @Override + public void onReceive(Context context, Intent intent) { + handleSignInResult(context, intent); + } + } +} diff --git a/guard/src/main/java/cn/authing/guard/social/GoogleLoginButton.java b/guard/src/main/java/cn/authing/guard/social/GoogleLoginButton.java new file mode 100644 index 00000000..fa30d853 --- /dev/null +++ b/guard/src/main/java/cn/authing/guard/social/GoogleLoginButton.java @@ -0,0 +1,28 @@ +package cn.authing.guard.social; + +import android.content.Context; +import android.util.AttributeSet; + +import cn.authing.guard.R; + +public class GoogleLoginButton extends SocialLoginButton { + + public GoogleLoginButton(Context context) { + this(context, null); + } + + public GoogleLoginButton(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.buttonStyle); + } + + public GoogleLoginButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + setImageResource(R.drawable.ic_authing_google); + } + + @Override + protected SocialAuthenticator createAuthenticator() { + return new Google(); + } +} diff --git a/guard/src/main/java/cn/authing/guard/social/SocialAuthenticator.java b/guard/src/main/java/cn/authing/guard/social/SocialAuthenticator.java index e7e6709f..12abaad9 100644 --- a/guard/src/main/java/cn/authing/guard/social/SocialAuthenticator.java +++ b/guard/src/main/java/cn/authing/guard/social/SocialAuthenticator.java @@ -46,4 +46,8 @@ protected AuthContainer.AuthProtocol getAuthProtocol(Context context) { AuthFlow flow = (AuthFlow) activity.getIntent().getSerializableExtra(AuthActivity.AUTH_FLOW); return flow.getAuthProtocol(); } + + protected void onDetachedFromWindow() { + + } } diff --git a/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java b/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java index d0065e7c..e08e0f38 100644 --- a/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java +++ b/guard/src/main/java/cn/authing/guard/social/SocialLoginButton.java @@ -97,4 +97,12 @@ public void setOnLoginListener(AuthCallback callback) { public void setType(String type) { this.type = type; } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (authenticator != null){ + authenticator.onDetachedFromWindow(); + } + } } diff --git a/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java b/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java index e951b712..03a471fe 100644 --- a/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java +++ b/guard/src/main/java/cn/authing/guard/social/SocialLoginListView.java @@ -91,6 +91,9 @@ private void setup(Context context, String s) { case Const.EC_TYPE_LARK_PUBLIC: button = new LarkLoginButton(context); break; + case Const.EC_TYPE_GOOGLE: + button = new GoogleLoginButton(context); + break; } if (button == null) { diff --git a/guard/src/main/java/cn/authing/guard/util/Const.java b/guard/src/main/java/cn/authing/guard/util/Const.java index 7cfb3af9..0aca031c 100644 --- a/guard/src/main/java/cn/authing/guard/util/Const.java +++ b/guard/src/main/java/cn/authing/guard/util/Const.java @@ -26,6 +26,7 @@ public class Const { public static final String EC_TYPE_LARK_INTERNAL = "lark-internal"; public static final String EC_TYPE_LARK_PUBLIC = "lark-public"; public static final String EC_TYPE_YI_DUN = "yidun"; + public static final String EC_TYPE_GOOGLE = "google:mobile"; public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static final MediaType FORM = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"); diff --git a/guard/src/main/res/drawable/ic_authing_google.xml b/guard/src/main/res/drawable/ic_authing_google.xml new file mode 100644 index 00000000..ff25f715 --- /dev/null +++ b/guard/src/main/res/drawable/ic_authing_google.xml @@ -0,0 +1,8 @@ + + + + + + From d093b5648f63387f3fcd2ee8fa263e19380dd3c1 Mon Sep 17 00:00:00 2001 From: zhongjiahui Date: Sun, 21 Aug 2022 21:02:00 +0800 Subject: [PATCH 12/64] add google login sample --- app/build.gradle | 4 + app/src/main/AndroidManifest.xml | 1 + .../java/cn/authing/SampleListActivity.java | 51 +++--- .../main/java/cn/authing/SignInActivity.java | 152 ++++++++++++++++++ app/src/main/res/layout/activity_signin.xml | 111 +++++++++++++ app/src/main/res/layout/theragun_login.xml | 3 +- 6 files changed, 297 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/cn/authing/SignInActivity.java create mode 100644 app/src/main/res/layout/activity_signin.xml diff --git a/app/build.gradle b/app/build.gradle index 855c8aaa..f7ee3cf6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -74,4 +74,8 @@ dependencies { // AppAuth implementation 'net.openid:appauth:0.10.0' + + // google + implementation 'com.google.android.gms:play-services-auth:20.2.0' + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d43d00ec..aa0925d4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -141,6 +141,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/cn/authing/SampleListActivity.java b/app/src/main/java/cn/authing/SampleListActivity.java index 9859af22..23f7cc63 100644 --- a/app/src/main/java/cn/authing/SampleListActivity.java +++ b/app/src/main/java/cn/authing/SampleListActivity.java @@ -3,13 +3,6 @@ import static cn.authing.guard.activity.AuthActivity.OK; import static cn.authing.guard.activity.AuthActivity.RC_LOGIN; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.biometric.BiometricManager; -import androidx.biometric.BiometricPrompt; -import androidx.core.content.ContextCompat; - import android.content.Intent; import android.os.Bundle; import android.view.Menu; @@ -18,6 +11,13 @@ import android.widget.ListView; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.biometric.BiometricManager; +import androidx.biometric.BiometricPrompt; +import androidx.core.content.ContextCompat; + import java.util.concurrent.Executor; import cn.authing.abao.AbaoActivity; @@ -59,6 +59,7 @@ public class SampleListActivity extends AppCompatActivity { "生物二次验证", "Authenticator", "Login by push notification", + "谷歌登录" }; @Override @@ -70,27 +71,31 @@ protected void onCreate(Bundle savedInstanceState) { ArrayAdapter adapter = new ArrayAdapter<>(this, R.layout.sample_list_item, from); listView.setAdapter(adapter); listView.setOnItemClickListener((arg0, arg1, arg2, pos) -> { - if (pos == 7) { + if (pos == 7) {//AppAuth startActivity(AppAuthActivity.class); return; - } else if (pos == 12) { + } else if (pos == 12) {//扫码登录 startActivity(ScanAuthActivity.class); return; - } else if (pos == 14) { + } else if (pos == 14) {//Authenticator startActivity(AuthenticatorActivity.class); return; + } else if (pos == 16) {//google登录 + Intent intent = new Intent(SampleListActivity.this, SignInActivity.class); + startActivity(intent); + return; } if (null != Authing.getCurrentUser()){ gotoMain(); return; } - if (pos == AUTHING_LOGIN) { + if (pos == AUTHING_LOGIN) {//Authing 标准登录 AuthFlow.start(this); - } else if (pos == 1) { + } else if (pos == 1) {//手机号一键登录(Authing UI) Intent intent = new Intent(SampleListActivity.this, OneClickActivity.class); startActivityForResult(intent, RC_LOGIN); - } else if (pos == 2) { + } else if (pos == 2) {//手机号一键登录(纯逻辑) OneClick oneClick = new OneClick(SampleListActivity.this); // if you want to return refreshToken、idToken、refreshToken oneClick.setAuthProtocol(AuthContainer.AuthProtocol.EOIDC); @@ -101,33 +106,33 @@ protected void onCreate(Bundle savedInstanceState) { gotoMain(userInfo); } })); - } else if (pos == 3) { + } else if (pos == 3) {//微信 startActivity(WechatAuthActivity.class); - } else if (pos == 4) { + } else if (pos == 4) {//Theragun startActivity(TheragunAuthActivity.class); - } else if (pos == 5) { + } else if (pos == 5) {//阿宝说 startActivity(AbaoActivity.class); - } else if (pos == 6) { + } else if (pos == 6) {//Auth Container AuthFlow flow = AuthFlow.start(this); flow.setAuthProtocol(AuthContainer.AuthProtocol.EOIDC); // Intent intent = new Intent(SampleListActivity.this, NissanVirtualKeyAuthActivity.class); // startActivity(intent); - } else if (pos == 8) { + } else if (pos == 8) {//Authing WebView 登录 AuthFlow flow = AuthFlow.startWeb(this); // flow.setScope("openid"); flow.setSkipConsent(true); - } else if (pos == 9) { + } else if (pos == 9) {//Authing 自定义 WebView 登录 startActivity(AuthingWebViewActivity.class); - } else if (pos == 10) { + } else if (pos == 10) {//MFA Authing.init(SampleListActivity.this, "61c173ada0e3aec651b1a1d1"); AuthFlow.start(this); - } else if (pos == 11) { + } else if (pos == 11) {//登录/注册后用户信息完善 Authing.init(SampleListActivity.this, "61ae0c9807451d6f30226bd4"); AuthFlow.start(this); - } else if (pos == 13) { + } else if (pos == 13) {//生物二次验证 biometric = true; AuthFlow.start(this); - } else if (pos == 15) { + } else if (pos == 15) {//Login by push notification Intent intent = new Intent(SampleListActivity.this, LoginByPushNotificationActivity.class); startActivityForResult(intent, RC_LOGIN); } diff --git a/app/src/main/java/cn/authing/SignInActivity.java b/app/src/main/java/cn/authing/SignInActivity.java new file mode 100644 index 00000000..0cdfe0cd --- /dev/null +++ b/app/src/main/java/cn/authing/SignInActivity.java @@ -0,0 +1,152 @@ +package cn.authing; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +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.SignInButton; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; + +public class SignInActivity extends AppCompatActivity implements + View.OnClickListener { + + private static final String TAG = "SignInActivity"; + private static final int RC_SIGN_IN = 9001; + + private GoogleSignInClient mGoogleSignInClient; + private TextView mStatusTextView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_signin); + + mStatusTextView = findViewById(R.id.status); + findViewById(R.id.sign_in_button).setOnClickListener(this); + findViewById(R.id.sign_out_button).setOnClickListener(this); + findViewById(R.id.disconnect_button).setOnClickListener(this); + + // Configure sign-in to request the user's ID, email address, and basic + // profile. ID and basic profile are included in DEFAULT_SIGN_IN. + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + //.requestIdToken("416092875790-22eprs8p2i31aqkiu7i1i0duauskcurk.apps.googleusercontent.com") + .requestIdToken("416092875790-usvrkoj06srkmalel5ld6selsk2rq35r.apps.googleusercontent.com") + //.requestServerAuthCode("416092875790-usvrkoj06srkmalel5ld6selsk2rq35r.apps.googleusercontent.com") + .requestEmail() + .build(); + + // Build a GoogleSignInClient with the options specified by gso. + mGoogleSignInClient = GoogleSignIn.getClient(this, gso); + + // Set the dimensions of the sign-in button. + SignInButton signInButton = findViewById(R.id.sign_in_button); + signInButton.setSize(SignInButton.SIZE_STANDARD); + signInButton.setColorScheme(SignInButton.COLOR_LIGHT); + } + + @Override + public void onStart() { + super.onStart(); + + // Check for existing Google Sign In account, if the user is already signed in + // the GoogleSignInAccount will be non-null. + GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); + updateUI(account); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + // Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...); + if (requestCode == RC_SIGN_IN) { + // The Task returned from this call is always completed, no need to attach + // a listener. + Task task = GoogleSignIn.getSignedInAccountFromIntent(data); + handleSignInResult(task); + } + } + + private void handleSignInResult(Task completedTask) { + try { + GoogleSignInAccount account = completedTask.getResult(ApiException.class); + // Signed in successfully, show authenticated UI. + updateUI(account); + } catch (ApiException e) { + // The ApiException status code indicates the detailed failure reason. + // Please refer to the GoogleSignInStatusCodes class reference for more information. + Log.e(TAG, "signInResult:failed code =" + e.getStatusCode()); + Log.e(TAG, "signInResult:failed e =" + e); + updateUI(null); + } + } + + private void signIn() { + Intent signInIntent = mGoogleSignInClient.getSignInIntent(); + startActivityForResult(signInIntent, RC_SIGN_IN); + } + + private void signOut() { + mGoogleSignInClient.signOut() + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + // [START_EXCLUDE] + updateUI(null); + // [END_EXCLUDE] + } + }); + } + + private void revokeAccess() { + mGoogleSignInClient.revokeAccess() + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + // [START_EXCLUDE] + updateUI(null); + // [END_EXCLUDE] + } + }); + } + + private void updateUI(@Nullable GoogleSignInAccount account) { + if (account != null) { + mStatusTextView.setText("Signed in as: " + account.getDisplayName()); + + findViewById(R.id.sign_in_button).setVisibility(View.GONE); + findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE); + } else { + mStatusTextView.setText("Signed out"); + + findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE); + findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.sign_in_button: + signIn(); + break; + case R.id.sign_out_button: + signOut(); + break; + case R.id.disconnect_button: + revokeAccess(); + break; + } + } +} diff --git a/app/src/main/res/layout/activity_signin.xml b/app/src/main/res/layout/activity_signin.xml new file mode 100644 index 00000000..be63ca26 --- /dev/null +++ b/app/src/main/res/layout/activity_signin.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + +