# oauth2-auth-server-oidc **Repository Path**: XcyzzZ/oauth2-auth-server-oidc ## Basic Information - **Project Name**: oauth2-auth-server-oidc - **Description**: SpringBoot生态的OAuth2 Authorization Server的增强实现 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 38 - **Created**: 2024-03-11 - **Last Updated**: 2024-03-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring Authorization Server - OIDC扩展 模块说明: | 模块 | 说明 | |:-----|:------| | [oauth2-auth-server-oidc-base](oauth2-auth-server-oidc-base) | OIDC AuthServer核心功能Base模块,其他示例模块均依赖此模块 | | [samples/oauth2-auth-server-oidc-minimal](samples/oauth2-auth-server-oidc-minimal) | OIDC AuthServer最小集成示例 | | [samples/oauth2-auth-server-oidc-token-ext](samples/oauth2-auth-server-oidc-token-ext) | OIDC AuthServer扩展token示例 | | [samples/oauth2-auth-server-oidc-resource](samples/oauth2-auth-server-oidc-resource) | OIDC AuthServer同时作为Resource Server示例 | | [samples/oauth2-auth-server-oidc-login-captcha](samples/oauth2-auth-server-oidc-login-captcha) | OIDC AuthServer自定义登录图片验证码集成示例 | | [samples/oauth2-auth-server-oidc-login-third](samples/oauth2-auth-server-oidc-login-third) | OIDC AuthServer集成第三方OAuth2(GitHub)登录示例 | | [samples/oauth2-auth-server-oidc-session](samples/oauth2-auth-server-oidc-session) | OIDC AuthServer共享session集成示例(支持AuthServer分布式部署) | | [samples/oauth2-auth-server-oidc-combo](samples/oauth2-auth-server-oidc-combo) | OIDC AuthServer综合集成示例(自定义登录页、手机验证码登录、token扩展、第三方登录、同时作为资源服务器) | | [samples/oauth2-client1](samples/oauth2-client1) | Spring Security OAuth2 Client示例1(使用Authorization Code + PKCE) | | [samples/oauth2-client2](samples/oauth2-client2) | Spring Security OAuth2 Client示例2(使用Authorization Code) | | [samples/oauth2-resource-server-jwt](samples/oauth2-resource-server-jwt) | Spring Security OAuth2 Resource Server示例1(使用Jwt验证) | | [samples/oauth2-resource-server-jwt](samples/oauth2-resource-server-opaque) | Spring Security OAuth2 Resource Server示例2(使用OpaqueToken验证,即使用introspection_endpoint) | | [samples/sample-common](samples/oauth2-common) | samples通用基础模块(仅提取示例中的通用部分,无实际作用) | ## oauth2-auth-server-oidc-base扩展点 - 自定义登录页面 - 自定义登录认证逻辑:[UniLoginUserDetailsService](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/handler/login/UniLoginUserDetailsService.java) - 默认实现支持: - [UniLoginUserDetailsPasswordMatcherService - 账号密码登录](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/handler/login/UniLoginUserDetailsPasswordMatcherService.java) - [UniLoginUserDetailsKaptchaMatcherService - 账号密码+图片验证码登录](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/handler/kaptcha/UniLoginUserDetailsKaptchaMatcherService.java) - 支持登录表单Ajax提交 - 扩展token:[DefaultOidcTokenCustomer.AbstractOidcTokenCustomerExtend](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/handler/oidc/DefaultOidcTokenCustomer.java) - 扩展UserInfo:[DefaultOidcUserInfoMapper.OidcUserInfoMapperExtend](oauth2-auth-server-oidc-base/src/main/java/com/luo/demo/security/authserver/handler/oidc/DefaultOidcUserInfoMapper.java) - 注册第三方用户信息:[DefaultOidcTokenCustomer.AbstractOidcTokenCustomerExtend](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/handler/oidc/DefaultOidcTokenCustomer.java) - 自定义Token端点响应信息:[OAuth2TokenEndpointAuthenticationResponseHandler](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/handler/token/OAuth2TokenEndpointAuthenticationResponseHandler.java) - 默认实现:[DefaultOAuth2TokenEndpointAuthenticationResponseHandlerImpl](oauth2-auth-server-oidc-base/src/main/java/org.springframework/security/oauth2/server/authorization/web/DefaultOAuth2TokenEndpointAuthenticationResponseHandlerImpl.java) - 自定义OIDC认证信息管理服务:[OidcAuthorizationService extends OAuth2AuthorizationService](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/service/JdbcOidcAuthorizationService.java) - 默认实现:[JdbcOidcAuthorizationService](oauth2-auth-server-oidc-base/src/main/java/com/luo/sc/oidc/authserver/service/OidcAuthorizationService.java) - 自定义Client注册信息仓库:[RegisteredClientRepository(Spring Authorization Server接口)]() - 默认实现:[JdbcRegisteredClientRepository]() - 自定义授权确认信息管理服务:[OAuth2AuthorizationConsentService(Spring Authorization Server接口)]() - 默认实现:[JdbcOAuth2AuthorizationConsentService]() 默认账号密码:root/123456 ## RP注册信息配置 ```java @Resource private JdbcRegisteredClientRepository registeredClientRepository; @Test void regOidcClient() { RegisteredClient registeredClient_client1 = RegisteredClient.withId(UUID.randomUUID().toString()) //客户端名称 .clientName("luo-oauth2-client1 - 客户端") //客户端ID和Secret(需在Client端进行配置),且Secret需使用对应的PasswordEncoder进行编码 .clientId("luo-oauth2-client1") .clientSecret("{bcrypt}$2a$10$LgGXHSU2Fh/dCLIwrOetiOnCK3Zypeo588EpAOQeJAnT0kdiia6em") //客户端认证方法 .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) //客户端认证方none - 若开启PKCE认证,则需添加none认证方法,否则 .clientAuthenticationMethod(ClientAuthenticationMethod.NONE) //支持的OAuth2授权模式(authorization_code和refresh_token) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) //在OP端认证成功后的回调(重定向回RP端)URI .redirectUri("http://oauth2-client1:8081/login/oauth2/code/luo-oauth2-client1") //添加Client端对应的权限scope .scope(OidcScopes.OPENID) .scope(OidcScopes.PHONE) .scope(OidcScopes.EMAIL) .scope(OidcScopes.PROFILE) //支持PKCE模式下(无client_secret)获取refresh_token .scope(OIDCScopeValue.OFFLINE_ACCESS.getValue()) .scope("articles.read") .scope("roles") //Client相关设置 .clientSettings(ClientSettings.builder() //是否需要展示权限确认页面 .requireAuthorizationConsent(true) //是否需要开启PKCE模式(SPA建议开启) .requireProofKey(true) //如下两项jwtSetUrl、tokenEndpointAuthenticationSigningAlgorithm适用于认证方法private_key_jwt和client_secret_jwt, //以上使用的client_secret_post和client_secret_basic可不用配置 //覆盖Client端的jwksSetUrl //.jwkSetUrl(null) //设置client认证(private_key_jwt和client_secret_jwt)JWT签名算法 //.tokenEndpointAuthenticationSigningAlgorithm(SignatureAlgorithm.RS256) //注:idToken、accessToke均使用RS256签名算法,目前不可配置,参见:JwtUtils.headers方法 //自定义配置(如自定义OIDC协议中RP的前端、后端登出URI) .setting(CLIENT_SETTINGS.FRONTCHANNEL_LOGOUT_URI, "http://oauth2-client1:8081/front_logout") .setting(CLIENT_SETTINGS.BACKCHANNEL_LOGOUT_URI, "http://oauth2-client1:8081/back_logout") .build()) //Token相关设置 .tokenSettings(TokenSettings.builder() //accessToken生存时长(即超过多久失效,默认5分钟) .accessTokenTimeToLive(Duration.ofMinutes(5)) //refreshToken生存时长(即超过多久失效,默认60分钟) .refreshTokenTimeToLive(Duration.ofMinutes(60)) //执行刷新token流程时,是否返回新的refreshToken(默认true即重用refreshToken), //true则重用之前的refreshToken,false则生成新的refreshToken及生存时长 .reuseRefreshTokens(false) //设置idToken签名算法 TODO 参见 OidcClientRegistrationEndpointFilter 逻辑 .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256) //支持PKCE模式下(无client_secret)执行refresh_token流程 .setting(TOKEN_SETTINGS.ALLOW_PUBLIC_CLIENT_REFRESH_TOKEN, true) //注:idToken默认生存时长30分钟,目前不可配置,参见:JwtUtils.idTokenClaims方法 //注:code有效时长5分钟,目前不可配置,参见:OAuth2AuthorizationCodeRequestAuthenticationProvider.generateAuthorizationCode //注:session时长 > refreshToken刷新时长 //TODO 注:session时长 remember-me时长 .build()) registeredClientRepository.save(registeredClient_client1); } ``` ## 示例工程说明 本地运行示例模块Host配置: >127.0.0.1 oauth2-server > >127.0.0.1 oauth2-client1 > >127.0.0.1 oauth2-client2 > >127.0.0.1 oauth2-resource1 > >127.0.0.1 oauth2-resource2 示例oauth2-client1和oauth2-client2的客户端注册信息如下: ```sql INSERT INTO oauth2_registered_client ( id, client_id, client_id_issued_at, client_secret, client_secret_expires_at, client_name, client_authentication_methods, authorization_grant_types, redirect_uris, scopes, client_settings, token_settings ) VALUES ( 'b8756f02-af55-4b39-a173-22bbfda82d9f', 'luo-oauth2-client1', '2022-03-07 09:10:03', '{bcrypt}$2a$10$LgGXHSU2Fh/dCLIwrOetiOnCK3Zypeo588EpAOQeJAnT0kdiia6em', NULL, 'luo-oauth2-client1 - 客户端', 'client_secret_post,client_secret_basic,none', 'refresh_token,authorization_code,password', 'http://oauth2-client1:8081/login/oauth2/code/luo-oauth2-client1', 'articles.read,phone,openid,profile,roles,email,offline_access', '{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.client.require-authorization-consent\":true,\"settings.client.require-proof-key\":true,\"frontchannel_logout_uri\":\"http://oauth2-client1:8081/front_logout\"}', '{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.token.reuse-refresh-tokens\":false,\"settings.token.allow-public-client-refresh-token\":true,\"settings.token.id-token-signature-algorithm\":[\"org.springframework.security.oauth2.jose.jws.SignatureAlgorithm\",\"RS256\"],\"settings.token.access-token-time-to-live\":[\"java.time.Duration\",300.000000000],\"settings.token.refresh-token-time-to-live\":[\"java.time.Duration\",3600.000000000]}' ), ( '8b767dc8-de43-4705-8b10-72ef642cfbbc', 'luo-oauth2-client2', '2022-03-07 09:10:04', '{bcrypt}$2a$10$xw.pBLQitbNdAAyBhuBAo.IIP8dbDHcXF5c1YNIDqhhcC18cmNGo2', NULL, 'luo-oauth2-client2 - 客户端', 'client_secret_post,client_secret_basic,none', 'refresh_token,authorization_code', 'http://oauth2-client2:8082/login/oauth2/code/luo-oauth2-client2', 'articles.read,phone,openid,profile,roles,email', '{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.client.require-authorization-consent\":true,\"settings.client.require-proof-key\":false,\"frontchannel_logout_uri\":\"http://oauth2-client2:8082/front_logout\"}', '{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.token.reuse-refresh-tokens\":true,\"settings.token.id-token-signature-algorithm\":[\"org.springframework.security.oauth2.jose.jws.SignatureAlgorithm\",\"RS256\"],\"settings.token.access-token-time-to-live\":[\"java.time.Duration\",300.000000000],\"settings.token.refresh-token-time-to-live\":[\"java.time.Duration\",3600.000000000]}' ); ``` ### OIDC AuthServer最小接入 - 用户名、密码登录(默认root/123456) 参见示例:[oauth2-auth-server-oidc-minimal](samples/oauth2-auth-server-oidc-minimal) 1. 新建对应Mysql库oauth2-server(名称可适当调整)并导入[oauth2-auth-server-oidc-base/src/main/resources/sql/oidc-authorization-server.sql](oauth2-auth-server-oidc-base/src/main/resources/sql/oidc-authorization-server.sql) 2. 根据需要配置具体client注册信息(可参见测试用例) 3. 可通过`自定义UserDetailsService实现`来根据用户名检索用户及密码信息 4. 配置OIDC Authorization相关属性(需生成RSA对称密钥对) ### OIDC AuthServer同时作为Resource Server 参见示例:[oauth2-auth-server-oidc-resource](samples/oauth2-auth-server-oidc-resource) ### OIDC AuthServer扩展token > 扩展token需实现:DefaultOidcTokenCustomer.AbstractOidcTokenCustomerExtend > > 扩展userinfo需实现:DefaultOidcUserInfoMapper.OidcUserInfoMapperExtend - accessToken - refreshToken - idToken - userInfo 参见示例:[oauth2-auth-server-oidc-token-ext](samples/oauth2-auth-server-oidc-token-ext) ### OIDC AuthServer自定义登录 - 图片验证码 参见示例:[oauth2-auth-server-oidc-login-captcha](samples/oauth2-auth-server-oidc-login-captcha) ### OIDC AuthServer自定义登录 - 集成第三方登录(GitHub) 参见示例:[oauth2-auth-server-oidc-login-third](samples/oauth2-auth-server-oidc-login-third) ### OIDC AuthServer自定义登录 - 组合集成 - 自定义登录页 - 手机验证码登录 - token扩展 - 第三方登录 - 同时作为资源服务器 参见示例:[oauth2-auth-server-oidc-login-third](samples/oauth2-auth-server-oidc-login-third) ### OIDC AuthServer集成共享Session 参见示例:[oauth2-auth-server-oidc-login-session](oauth2-auth-server-oidc-login-session)