diff --git a/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/auth/SocialAuthRequestFactory.java b/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/auth/SocialAuthRequestFactory.java index e8b69f8c5..38e4639c2 100644 --- a/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/auth/SocialAuthRequestFactory.java +++ b/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/auth/SocialAuthRequestFactory.java @@ -5,6 +5,7 @@ import cn.daxpay.open.platform.capability.social.justauth.request.DouyinRequest; import cn.daxpay.open.platform.capability.social.justauth.request.FeishuRequest; import cn.daxpay.open.platform.capability.social.justauth.request.GithubRequest; import cn.daxpay.open.platform.capability.social.justauth.request.GiteeRequest; +import cn.daxpay.open.platform.capability.social.justauth.request.GoogleRequest; import cn.daxpay.open.platform.capability.social.justauth.request.QqRequest; import cn.daxpay.open.platform.capability.social.justauth.request.SocialAuthRequest; import cn.daxpay.open.platform.capability.social.justauth.request.WeComRequest; @@ -27,6 +28,7 @@ public class SocialAuthRequestFactory { return switch (source) { case GITHUB -> new GithubRequest(config); case GITEE -> new GiteeRequest(config); + case GOOGLE -> new GoogleRequest(config); case QQ -> new QqRequest(config); case WECHAT_MP -> new WechatMpRequest(config); case WE_COM -> new WeComRequest(config); diff --git a/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/SocialSourceEnum.java b/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/SocialSourceEnum.java index 762a9d9cc..4bbf3b37c 100644 --- a/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/SocialSourceEnum.java +++ b/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/SocialSourceEnum.java @@ -80,6 +80,14 @@ public enum SocialSourceEnum implements I18nSupport { "https://gitee.com/api/v5/user" ), + /// Google + GOOGLE( + "google", + "https://accounts.google.com/o/oauth2/v2/auth", + "https://oauth2.googleapis.com/token", + "https://openidconnect.googleapis.com/v1/userinfo" + ), + ; /// 平台编码(与 AuthLoginTypeCode 对应, 作为配置和绑定的唯一标识) diff --git a/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/request/GoogleRequest.java b/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/request/GoogleRequest.java new file mode 100644 index 000000000..265123a10 --- /dev/null +++ b/daxpay-platform/daxpay-platform-capability/capability-social/src/main/java/cn/daxpay/open/platform/capability/social/justauth/request/GoogleRequest.java @@ -0,0 +1,75 @@ +package cn.daxpay.open.platform.capability.social.justauth.request; + +import cn.daxpay.open.platform.capability.social.justauth.SocialAuthConfig; +import cn.daxpay.open.platform.capability.social.justauth.SocialSourceEnum; +import cn.daxpay.open.platform.capability.social.justauth.exception.SocialException; +import cn.daxpay.open.platform.capability.social.justauth.model.AuthCallback; +import cn.daxpay.open.platform.capability.social.justauth.model.AuthToken; +import cn.daxpay.open.platform.capability.social.justauth.model.AuthUser; +import cn.daxpay.open.platform.capability.social.justauth.util.SocialUrlBuilder; +import cn.hutool.json.JSONObject; + +/// # Google 授权登录 +/// +/// [Google OAuth2.0 / OpenID Connect](https://developers.google.com/identity/openid-connect/openid-connect) +/// authorize 必须显式携带 scope(openid email profile), 否则无法获取用户信息; +/// token 响应为 JSON, 用户信息接口需通过 Authorization: Bearer 头携带令牌, +/// 用户唯一标识为 sub 字段. +/// +public class GoogleRequest extends AbstractSocialAuthRequest { + + public GoogleRequest(SocialAuthConfig config) { + super(config, SocialSourceEnum.GOOGLE); + } + + /// Google 授权地址必须显式声明 scope(openid email profile) + /// 默认通用 authorize 方法不带 scope, 故在此重写 + @Override + public String authorize(String state) { + return SocialUrlBuilder.ofBaseUrl(this.getSource().authorize()) + .queryParam("response_type", "code") + .queryParam("client_id", this.getConfig().getClientId()) + .queryParam("redirect_uri", this.buildRedirectUri()) + .queryParam("state", state) + .queryParam("scope", "openid email profile") + .build(); + } + + /// Google 的 token 响应为 JSON 格式 + @Override + public AuthToken getAccessToken(AuthCallback callback) { + String response = this.doPost(this.accessTokenUrl(callback.getCode())); + JSONObject object = this.parseObj(response); + if (object.containsKey("error")) { + throw new SocialException(object.getStr("error_description")); + } + return new AuthToken() + .setAccessToken(object.getStr("access_token")) + .setRefreshToken(object.getStr("refresh_token")) + .setScope(object.getStr("scope")) + .setTokenType(object.getStr("token_type")) + .setExpireIn(object.getInt("expires_in", 0)); + } + + /// Google 用户信息需通过 Authorization: Bearer 头携带令牌 + /// 唯一标识为 sub, 昵称取 name, 头像取 picture, 邮箱取 email + @Override + public AuthUser getUserInfo(AuthToken token) { + String response = this.doGet( + this.getSource().userInfo(), + this.headers("Authorization", "Bearer " + token.getAccessToken()) + ); + JSONObject object = this.parseObj(response); + if (object.containsKey("error")) { + throw new SocialException(object.getStr("error_description")); + } + return new AuthUser() + .setUuid(object.getStr("sub")) + .setUsername(object.getStr("email")) + .setNickname(object.getStr("name")) + .setAvatar(object.getStr("picture")) + .setEmail(object.getStr("email")) + .setSource(this.getSourceName()) + .setToken(token); + } +} diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/social_source.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/social_source.json index b8d0a08d6..774dc98a5 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/social_source.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/en-US/enum/social_source.json @@ -4,6 +4,7 @@ "qq": "QQ", "github": "GitHub", "gitee": "Gitee", + "google": "Google", "feishu": "Feishu", "dingTalk": "DingTalk", "douyin": "Douyin" diff --git a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/social_source.json b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/social_source.json index 821a405cd..3ca6b8fec 100644 --- a/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/social_source.json +++ b/daxpay-platform/daxpay-platform-common/common-i18n/src/main/resources/i18n/zh-CN/enum/social_source.json @@ -4,6 +4,7 @@ "qq": "QQ", "github": "GitHub", "gitee": "Gitee", + "google": "Google", "feishu": "飞书", "dingTalk": "钉钉", "douyin": "抖音"