Keycloak自定义实现第三方登录

第三方Oauth登录

  • 由于对接的第三方IDP不一定都是标准的openid connect实现,所以都需要根据第三方的Oauth文档进行定制;
    Keycloak对于新增Social IDP的实现,都是标准,以及灵活的;
    我们完全可以参照 Keycloak 本身已实现的Github LinkedIn等,快速实现我们的需求;

我们这里以酷家乐的Oauth2 接口进行说明

酷家乐 Oauth2接口分析

  • 请求code的参数及返回都是标准的,这里无需进行修改
  • 换取token接口,由于返回参数进行data的wrap,以及字段名为驼峰的,所以需要对这部分进行修改定制

  • 获取用户信息

由于获取用户信息,还需要额外请求用户的OpenId,所以需要对该部分进行修改

定制Provider

提供工程类: KujialeIdentityProviderFactory

工厂类完全可以从GitHubIdentityProviderFactory 拷贝过来,修改成自己 PROVIDER_ID, NAME 以及create自己的Provider

public class GitHubIdentityProviderFactory extends AbstractIdentityProviderFactory<GitHubIdentityProvider> implements SocialIdentityProviderFactory<GitHubIdentityProvider> {public static final String PROVIDER_ID = "github";@Overridepublic String getName() {return "GitHub";}@Overridepublic GitHubIdentityProvider create(KeycloakSession session, IdentityProviderModel model) {return new GitHubIdentityProvider(session, new OAuth2IdentityProviderConfig(model));}@Overridepublic OAuth2IdentityProviderConfig createConfig() {return new OAuth2IdentityProviderConfig();}@Overridepublic String getId() {return PROVIDER_ID;}
}

解析accessToken 以及获取用户信息

解析用户信息

KujialeIdentityProvider 完整代码

public class KujialeIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {public static final String AUTH_URL = "https://oauth.kujiale.com/oauth2/show";public static final String TOKEN_URL = "https://oauth.kujiale.com/oauth2/auth/token";public static final String OPENID_URL = "https://oauth.kujiale.com/oauth2/auth/user";public static final String PROFILE_URL = "https://oauth.kujiale.com/oauth2/openapi/user";public static final String DEFAULT_SCOPE = "get_user_info";public static final String OAUTH2_PARAMETER_ACCESS_TOKEN = "accessToken";public KujialeIdentityProvider(KeycloakSession session, OAuth2IdentityProviderConfig config) {super(session, config);config.setAuthorizationUrl(AUTH_URL);config.setTokenUrl(TOKEN_URL);config.setUserInfoUrl(PROFILE_URL);}@Overrideprotected boolean supportsExternalExchange() {return true;}@Overrideprotected String getProfileEndpointForValidation(EventBuilder event) {return PROFILE_URL;}@Overrideprotected String getDefaultScopes() {return DEFAULT_SCOPE;}/*** 提取酷家乐用户信息,转换为keycloak用户实体** @param event* @param profile* @return*/@Overrideprotected BrokeredIdentityContext extractIdentityFromProfile(EventBuilder event, JsonNode profile) {if (!profile.has("d") || profile.get("d").isEmpty()) {throw new NullPointerException("kujiale idp user info response is null " + profile.toString());}JsonNode userNode = profile.get("d");String openId = getJsonProperty(userNode, "openId");if (openId == null || openId.isEmpty()) {throw new NullPointerException("kujiale idp user info is null " + userNode.asText());}BrokeredIdentityContext user = new BrokeredIdentityContext(openId);String userName = userNode.get("userName").asText();user.setUsername(userName);user.setFirstName(userName);user.setIdpConfig(getConfig());user.setIdp(this);AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, userNode, getConfig().getAlias());return user;}/*** 构建获取酷家乐用户信息的请求 暂不支持** @param subjectToken* @param userInfoUrl* @return*/@Overrideprotected SimpleHttp buildUserInfoRequest(String subjectToken, String userInfoUrl) {return SimpleHttp.doGet(userInfoUrl, session).header("Authorization", "Bearer " + subjectToken);}/*** 获取酷家乐用户信息** @param response* @return*/@Overridepublic BrokeredIdentityContext getFederatedIdentity(String response) {String accessToken;try {JsonNode resNode = asJsonNode(response);accessToken = extractTokenFromResponse(resNode.get("d").toString(), OAUTH2_PARAMETER_ACCESS_TOKEN);} catch (Exception ex) {throw new IdentityBrokerException("No access token available in OAuth server response: " + response);}if (accessToken == null) {throw new IdentityBrokerException("No access token available in OAuth server response: " + response);}BrokeredIdentityContext context = doGetFederatedIdentity(accessToken);context.getContextData().put(FEDERATED_ACCESS_TOKEN, accessToken);return context;}protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {BrokeredIdentityContext context = null;try {JsonNode openidResponse = generateOpenIdRequest(accessToken).asJson();String openId = openidResponse.get("d").asText();if (openId == null) {throw new Exception("Can not get openId from kujiale IDP");}JsonNode profile = generateUserInfoRequest(accessToken, openId).asJson();context = extractIdentityFromProfile(null, profile);} catch (Exception ex) {logger.warn("Cannot GetFederatedIdentity from kujiale IDP, error " + ex.getMessage());}return context;}public SimpleHttp generateOpenIdRequest(String accessToken) {SimpleHttp openIdRequest = SimpleHttp.doGet(OPENID_URL, session).param("access_token", accessToken);return openIdRequest;}public SimpleHttp generateUserInfoRequest(String accessToken, String openId) {SimpleHttp openIdRequest = SimpleHttp.doGet(PROFILE_URL, session).param("open_id", openId).param("access_token", accessToken);return openIdRequest;}}

定制属性映射: IdentityProviderMapper

其实属性映射,本质上只是新增个说明,我们的Provider支持 Import Attribute,
所以代码都是模板代码

public class KujialeUserAttributeMapper extends AbstractJsonUserAttributeMapper {private static final String[] cp = new String[]{KujialeIdentityProviderFactory.PROVIDER_ID};@Overridepublic String[] getCompatibleProviders() {return cp;}@Overridepublic String getId() {return "kujiale-user-attribute-mapper";}}

添加META-INF

添加
org.keycloak.broker.social.SocialIdentityProviderFactory

内容为:自己的ProviderFactory全类名

添加
org.keycloak.broker.provider.IdentityProviderMapper

内容为 自己Mapper的全类名

NoClassDefFoundError报错

相关问题链接
https://stackoverflow.com/questions/57778240/noclassdeffounderror-in-a-provider-jar-when-using-a-class-from-org-keycloak-auth

解决方法

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifestEntries><Dependencies>org.keycloak.keycloak-services</Dependencies></manifestEntries></archive></configuration>
</plugin>

部署Provider及配置使用

部署

拷贝到 /standalone/deployments中,重启服务

重启服务后,到 Admin ==> server info 确认新增的Provider生效



配置

新增IDP

设置属性mapper

可以设置默认使用的IDP

第一次登录,会自动创建用户已经,导入对应的属性信息

属性:

关联的IDP信息

Keycloak自定义实现第三方登录相关推荐

  1. Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)并与UsernamePassword登录关联解决方案

    前文:Spring Security OAuth2--自定义OAuth2第三方登录(Gitee) Maven 主要 <!--Spring Security--><dependency ...

  2. Spring Security OAuth2——自定义OAuth2第三方登录(Gitee)

    官方文档 https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-custom-pr ...

  3. keycloak 自定义登录页面

    keycloak 自定义登录页面详细步骤如下: 因为keycloak是jboss开发的,使用FTL后缀开发前端文件,可能根据以下方式实现 keycloak将前端页面分为四类:按类设置主题. •Acco ...

  4. 这个第三方登录开源工具,支持市面上几乎所有主流平台!好用!

    随着微信.支付宝等航母级应用在众人身边的普及,越来越多的应用.网站在登陆的时候除了提供注册用户外,还直接提供第三方登录的方式,也就是直接关联微信.支付宝这类应用,用已有的账号和密码来快速完成当前应用或 ...

  5. 第三方登录(QQ登录)开发流程详解

    一.准备工作 接入QQ登录前,网站需首先进行申请,获得对应的appid与appkey,以保证后续流程中可正确对网站与用户进行验证与授权. 申请appid和appkey的用途 appid :应用的唯一标 ...

  6. android 第三方登录界面,Android App集成第三方登录与换肤指南

    Android App集成第三方登录与换肤指南 文档编辑 概述 本文主要是介绍了如何通过开源框架快速支持QQ和微信登录,并介绍了如何实现app快速换肤 QQ登录接入 APP要支持QQ登录,需要先到腾讯 ...

  7. 第三方登录如何给前台返回token_如何设计优雅的第三方账号登录?

    # 前言 在互联网应用中,我们构建一个网站或APP,如果没有用户,那就没有价值.所以,如何吸引用户注册和登录,是一个重要问题,而这就涉及到账号体系了. 在应用构建初期,用户量较少,那么自建系统的账号体 ...

  8. .netcore 极速接入第三方登录

    新年新气象,趁着新年的喜庆,肝了十来天,终于发了第一版,希望大家喜欢. 如果有不喜欢看文字的童鞋,可以直接看下面的地址体验一下: Github: https://github.com/mrhuo/Mr ...

  9. Spring Boot 快速集成第三方登录功能

    Spring Boot 快速集成第三方登录功能 前言 此 demo 主要演示 Spring Boot 项目如何使用 史上最全的第三方登录工具 - JustAuth 实现第三方登录,包括 QQ 登录.G ...

最新文章

  1. Hash函数的安全性
  2. 「小程序JAVA实战」小程序视频上传方法的抽象复用(57)
  3. 沾包 nagle算法等
  4. tinyMce在线编辑器内JavaScript实现按Ctrl+S无刷新保存
  5. 需求工程-软件需求模式读书笔记3
  6. Django层级模型定义及序列化嵌套的方法
  7. 【Java调试】通过SqlSessionFactory类对象获取mapper文件内的动态SQL在执行时的完整SQL及参数(2种使用方法+测试Demo及结果)
  8. 二叉树的基本操作及哈夫曼编码/译码系统的实现
  9. 不装oracle进行远程连接解决办法 .
  10. 【theano-windows】学习笔记十八——混合蒙特卡洛采样
  11. 学习《Building Applications with FME Objects》 之四 从数据集读取要素
  12. Java Thread 总结
  13. 127.0.0.1和0.0.0.0和本机IP的区别
  14. DFN-LOW算法---割点、桥、强连通分量
  15. zabbix中文乱码的三种解决办法
  16. 【JAVA】doc,excel,等转pdf,swf
  17. 高淇java_关于高淇JAVA中SORM总结学习笔记详细个人解释
  18. php errorcode,errorCode.php
  19. word实现奇数页页眉用本章标题,偶数页用论文标题
  20. 关于“2021中国隧道与地下空间大会暨中国(城市)地下空间学会(筹)成立大会”的通知

热门文章

  1. kali下Eternalblue攻击win7
  2. shopify js使用liquid配置数据方法
  3. win7变成xp风格了怎么改回_【让win7变成xp】win7变成xp风格_win7界面变成xp
  4. 征途手游2新开区服务器维护多久,征途永恒开服表
  5. 统考英语和计算机可以插u盘吗,统考大学英语B考试技巧 精品
  6. 惠普p1106打印机安装步骤_【记录】win10中安装惠普HP LaserJet Professional P1106打印机驱动...
  7. 【STM32】LED初始化基础以及基本使用方法(CT117E电路)
  8. C++ 动态创建二维数组int** B = new int* [n];
  9. 漫画本地化母语翻译、审校、嵌字排版 安睿杰翻译
  10. 电商api—拼多多搜索