├── .gitignore ├── LICENSE ├── README.md ├── myoidc-client ├── pom.xml └── src │ ├── main │ ├── java │ │ └── myoidc │ │ │ └── client │ │ │ ├── MyOIDCClientApplication.java │ │ │ ├── config │ │ │ ├── MVCConfiguration.java │ │ │ └── MyOIDCConfiguration.java │ │ │ ├── domain │ │ │ ├── DiscoveryEndpointInfo.java │ │ │ ├── RPHolder.java │ │ │ ├── RPHolderRepository.java │ │ │ └── shared │ │ │ │ ├── Application.java │ │ │ │ └── BeanProvider.java │ │ │ ├── infrastructure │ │ │ └── RPHolderRepositoryDefault.java │ │ │ ├── service │ │ │ ├── MyOIDCClientService.java │ │ │ ├── business │ │ │ │ ├── OIDCTokenVerifier.java │ │ │ │ ├── PasswordOAuth2Handler.java │ │ │ │ └── PasswordParams.java │ │ │ ├── dto │ │ │ │ ├── AbstractOauthDto.java │ │ │ │ ├── AccessTokenDto.java │ │ │ │ ├── AuthAccessTokenDto.java │ │ │ │ ├── AuthCallbackDto.java │ │ │ │ ├── AuthorizationCodeDto.java │ │ │ │ ├── RefreshAccessTokenDto.java │ │ │ │ └── UserInfoDto.java │ │ │ └── impl │ │ │ │ └── MyOIDCClientServiceImpl.java │ │ │ └── web │ │ │ ├── WebUtils.java │ │ │ ├── context │ │ │ ├── OIDCApplicationContextAware.java │ │ │ └── OIDCServletContextAware.java │ │ │ └── controller │ │ │ ├── AuthorizationCodeController.java │ │ │ ├── ClientCredentialsController.java │ │ │ ├── ImplicitController.java │ │ │ ├── PasswordController.java │ │ │ ├── RefreshTokenController.java │ │ │ ├── StartupController.java │ │ │ └── UserInfoController.java │ └── resources │ │ ├── application.properties │ │ ├── static │ │ ├── angular.min.js │ │ ├── bootstrap │ │ │ ├── css │ │ │ │ ├── bootstrap-theme.css │ │ │ │ ├── bootstrap-theme.min.css │ │ │ │ ├── bootstrap.css │ │ │ │ └── bootstrap.min.css │ │ │ ├── fonts │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ └── js │ │ │ │ ├── bootstrap.js │ │ │ │ └── bootstrap.min.js │ │ └── favicon.ico │ │ └── templates │ │ ├── access_token_result.html │ │ ├── authorization_code.html │ │ ├── client_credentials.html │ │ ├── code_access_token.html │ │ ├── error │ │ └── 405.html │ │ ├── fragment │ │ ├── footer.html │ │ └── header.html │ │ ├── implicit.html │ │ ├── index.html │ │ ├── oauth_error.html │ │ ├── password.html │ │ ├── refresh_token.html │ │ └── user_info.html │ └── test │ ├── java │ └── myoidc │ │ └── client │ │ ├── MyOIDCClientApplicationTest.java │ │ ├── domain │ │ └── DiscoveryEndpointInfoTest.java │ │ ├── infrastructure │ │ └── RPHolderRepositoryDefaultTest.java │ │ └── service │ │ └── business │ │ └── PasswordOAuth2HandlerTest.java │ └── resources │ └── application-test.properties ├── myoidc-server ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── myoidc │ │ │ └── server │ │ │ ├── Constants.java │ │ │ ├── MyOIDCServerApplication.java │ │ │ ├── config │ │ │ ├── MVCConfiguration.java │ │ │ ├── MyOIDCConfiguration.java │ │ │ ├── OAuth2MethodSecurityConfiguration.java │ │ │ ├── OAuth2ServerConfiguration.java │ │ │ └── SecurityConfiguration.java │ │ │ ├── domain │ │ │ ├── AbstractDomain.java │ │ │ ├── README.txt │ │ │ ├── oauth │ │ │ │ ├── OauthClientDetails.java │ │ │ │ └── OauthRepository.java │ │ │ ├── security │ │ │ │ ├── OIDCUserDetails.java │ │ │ │ ├── SecurityHolder.java │ │ │ │ └── SecurityUtils.java │ │ │ ├── shared │ │ │ │ ├── Application.java │ │ │ │ ├── BeanProvider.java │ │ │ │ ├── Repository.java │ │ │ │ └── UUIDGenerator.java │ │ │ └── user │ │ │ │ ├── Privilege.java │ │ │ │ ├── User.java │ │ │ │ ├── UserPrivilege.java │ │ │ │ └── UserRepository.java │ │ │ ├── infrastructure │ │ │ ├── PasswordHandler.java │ │ │ ├── README.txt │ │ │ ├── RandomUtils.java │ │ │ ├── jdbc │ │ │ │ ├── OauthClientDetailsRowMapper.java │ │ │ │ └── OauthRepositoryJdbc.java │ │ │ ├── jpa │ │ │ │ ├── AbstractRepositoryHibernate.java │ │ │ │ └── UserRepositoryHibernate.java │ │ │ └── oidc │ │ │ │ ├── MyOIDCAccessTokenConverter.java │ │ │ │ ├── MyOIDCJwtAccessTokenConverter.java │ │ │ │ ├── MyOIDCTokenStore.java │ │ │ │ ├── MyOIDCUserAuthenticationConverter.java │ │ │ │ ├── OIDCUseScene.java │ │ │ │ └── OIDCUtils.java │ │ │ ├── service │ │ │ ├── OauthService.java │ │ │ ├── README.txt │ │ │ ├── SecurityService.java │ │ │ ├── UserService.java │ │ │ ├── business │ │ │ │ ├── ClientRegistrationFormSaver.java │ │ │ │ ├── OAuthClientDetailsSaver.java │ │ │ │ └── UserFormSaver.java │ │ │ ├── dto │ │ │ │ ├── ClientRegistrationFormDto.java │ │ │ │ ├── OAuthResourceDto.java │ │ │ │ ├── OauthClientDetailsDto.java │ │ │ │ ├── UserDto.java │ │ │ │ ├── UserFormDto.java │ │ │ │ ├── UserJsonDto.java │ │ │ │ └── UserListDto.java │ │ │ ├── impl │ │ │ │ ├── OauthServiceImpl.java │ │ │ │ ├── SecurityServiceImpl.java │ │ │ │ └── UserServiceImpl.java │ │ │ ├── oauth │ │ │ │ ├── CurrentUserJsonDtoLoader.java │ │ │ │ ├── CustomJdbcClientDetailsService.java │ │ │ │ ├── CustomJdbcTokenStore.java │ │ │ │ ├── OauthUserApprovalHandler.java │ │ │ │ └── SOSAuthorizationCodeServices.java │ │ │ └── validation │ │ │ │ ├── ClientIdValidation.java │ │ │ │ ├── ClientIdValidator.java │ │ │ │ ├── UsernameValidation.java │ │ │ │ └── UsernameValidator.java │ │ │ └── web │ │ │ ├── README.txt │ │ │ ├── WebUtils.java │ │ │ ├── context │ │ │ ├── OIDCApplicationContextAware.java │ │ │ ├── OIDCServletContextAware.java │ │ │ └── SpringSecurityHolder.java │ │ │ ├── controller │ │ │ ├── MyOIDCController.java │ │ │ ├── OAuth2RestController.java │ │ │ ├── admin │ │ │ │ ├── AdminRPController.java │ │ │ │ └── AdminUserController.java │ │ │ ├── endpoint │ │ │ │ ├── DiscoveryEndpoint.java │ │ │ │ ├── JWKSEndpoint.java │ │ │ │ ├── RegistrationEndpoint.java │ │ │ │ └── UserInfoEndpoint.java │ │ │ └── resource │ │ │ │ ├── MobileController.java │ │ │ │ └── UnityController.java │ │ │ └── filter │ │ │ └── ExtCharacterEncodingFilter.java │ └── resources │ │ ├── application.properties │ │ ├── jwks.json │ │ ├── public │ │ ├── MyOIDC_API-1.1.0.html │ │ ├── angular.min.js │ │ ├── bootstrap │ │ │ ├── css │ │ │ │ ├── bootstrap-theme.css │ │ │ │ ├── bootstrap-theme.min.css │ │ │ │ ├── bootstrap.css │ │ │ │ └── bootstrap.min.css │ │ │ ├── fonts │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ └── js │ │ │ │ ├── bootstrap.js │ │ │ │ └── bootstrap.min.js │ │ ├── db_table_description.html │ │ ├── favicon.ico │ │ └── images │ │ │ ├── oidc-sm.png │ │ │ └── openid.png │ │ └── templates │ │ ├── admin │ │ ├── rp_client_test.html │ │ ├── rp_form.html │ │ ├── rp_list.html │ │ ├── user_form.html │ │ └── user_list.html │ │ ├── fragment │ │ ├── footer.html │ │ └── header.html │ │ ├── index.html │ │ ├── login.html │ │ ├── registration_form.html │ │ ├── registration_pre.html │ │ └── registration_success.html │ └── test │ ├── java │ └── myoidc │ │ └── server │ │ ├── ContextTest.java │ │ ├── JwkTokenStoreTest.java │ │ ├── MyOIDCServerApplicationTests.java │ │ ├── configuration │ │ └── SecurityConfigurationTest.java │ │ ├── domain │ │ └── shared │ │ │ └── UUIDGeneratorTest.java │ │ ├── infrastructure │ │ ├── AbstractRepositoryTest.java │ │ ├── Auth0JwtTest.java │ │ ├── JJwtTest.java │ │ ├── JWKSTest.java │ │ ├── Jose4JTest.java │ │ ├── JsonWebKeySetTest.java │ │ ├── NimbusJoseJwtTest.java │ │ ├── PasswordHandlerTest.java │ │ ├── PrimeJwtTest.java │ │ ├── RandomUtilsTest.java │ │ ├── VertxAuthJwtTest.java │ │ ├── jdbc │ │ │ └── OauthRepositoryJdbcTest.java │ │ ├── jpa │ │ │ └── UserRepositoryHibernateTest.java │ │ └── oidc │ │ │ └── OIDCUtilsTest.java │ │ └── service │ │ └── business │ │ └── ClientRegistrationFormSaverTest.java │ └── resources │ ├── application-test.properties │ ├── jwks_ec.json │ ├── jwks_oct.json │ ├── jwks_rsa.json │ └── keystore.jwks ├── others ├── Final_OpenID-Connect-Core-1.0-incorporating-errata-set-1.html ├── How-To-Use.txt ├── OpenID Connect Standard for Federation.pdf ├── database │ ├── initial-db.ddl │ └── myoidc-server.ddl ├── development-log.txt ├── images │ ├── Security-Token-Service.png │ ├── favicon.ico │ └── openid.png ├── key │ ├── private_key.json │ └── public_key.json ├── oidc_test.txt └── springboot │ ├── myoidc.zip │ └── spring-boot-reference(2.0.0).pdf └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/MyOIDCClientApplication.java: -------------------------------------------------------------------------------- 1 | package myoidc.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Spring Boot bootstrap 8 | */ 9 | @SpringBootApplication 10 | public class MyOIDCClientApplication { 11 | 12 | 13 | /** 14 | * Run it directly 15 | * 16 | * @param args args 17 | */ 18 | public static void main(String[] args) { 19 | SpringApplication.run(MyOIDCClientApplication.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/config/MVCConfiguration.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.config; 2 | 3 | 4 | 5 | import myoidc.client.domain.shared.Application; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.http.converter.HttpMessageConverter; 8 | import org.springframework.http.converter.StringHttpMessageConverter; 9 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 11 | 12 | import java.nio.charset.Charset; 13 | import java.util.List; 14 | 15 | /** 16 | * 2018/1/30 17 | *

18 | * Spring MVC 扩展配置 19 | *

20 | * 21 | * @author Shengzhao Li 22 | */ 23 | @Configuration 24 | public class MVCConfiguration implements WebMvcConfigurer { 25 | 26 | 27 | /** 28 | * 扩展拦截器 29 | */ 30 | @Override 31 | public void addInterceptors(InterceptorRegistry registry) { 32 | 33 | WebMvcConfigurer.super.addInterceptors(registry); 34 | } 35 | 36 | 37 | // /** 38 | // * 字符编码配置 UTF-8 39 | // */ 40 | // @Bean 41 | // public FilterRegistrationBean encodingFilter() { 42 | // FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); 43 | // registrationBean.setFilter(new ExtCharacterEncodingFilter()); 44 | // registrationBean.addUrlPatterns("/*"); 45 | // return registrationBean; 46 | // } 47 | 48 | 49 | /** 50 | * 解决乱码问题 51 | * For UTF-8 52 | */ 53 | @Override 54 | public void configureMessageConverters(List> converters) { 55 | WebMvcConfigurer.super.configureMessageConverters(converters); 56 | converters.add(new StringHttpMessageConverter(Charset.forName(Application.ENCODING))); 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/config/MyOIDCConfiguration.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.config; 2 | 3 | 4 | import myoidc.client.domain.shared.Application; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | 11 | /** 12 | * 2018/1/30 13 | *

14 | * 15 | * @author Shengzhao Li 16 | */ 17 | @Configuration 18 | public class MyOIDCConfiguration { 19 | 20 | 21 | @Value("${application.host}") 22 | private String host; 23 | 24 | 25 | // Application 26 | @Bean 27 | public Application application() { 28 | Application application = new Application(); 29 | application.setHost(host); 30 | return application; 31 | } 32 | 33 | 34 | @Bean 35 | public RestTemplate restTemplate() { 36 | return new RestTemplate(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/domain/RPHolderRepository.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.domain; 2 | 3 | /** 4 | * 2020/4/7 5 | * 6 | * @author Shengzhao Li 7 | * @since 1.1.0 8 | */ 9 | public interface RPHolderRepository { 10 | 11 | RPHolder findRPHolder(); 12 | 13 | boolean saveRPHolder(RPHolder rpHolder); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/domain/shared/Application.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.domain.shared; 2 | 3 | 4 | import org.springframework.beans.factory.InitializingBean; 5 | import org.springframework.util.Assert; 6 | 7 | /** 8 | * @author Shengzhao Li 9 | */ 10 | public class Application implements InitializingBean { 11 | 12 | //系统字符编码 13 | public static final String ENCODING = "UTF-8"; 14 | 15 | public static final String PROJECT_HOME = "https://github.com/monkeyk/MyOIDC"; 16 | //Current version 17 | public static final String VERSION = "1.1.1"; 18 | 19 | 20 | //application host 21 | private static String host; 22 | 23 | 24 | /* 25 | * default 26 | * */ 27 | public Application() { 28 | } 29 | 30 | 31 | public static String host() { 32 | return host; 33 | } 34 | 35 | public void setHost(String host) { 36 | Application.host = host.endsWith("/") ? host : host + "/"; 37 | } 38 | 39 | 40 | @Override 41 | public void afterPropertiesSet() throws Exception { 42 | Assert.notNull(host, "host is null"); 43 | } 44 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/domain/shared/BeanProvider.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.domain.shared; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | /** 6 | * Get Bean form ApplicationContext 7 | * 8 | * @author Shengzhao Li 9 | * @since 1.1.0 10 | */ 11 | public abstract class BeanProvider { 12 | 13 | protected static ApplicationContext applicationContext; 14 | 15 | protected BeanProvider() { 16 | } 17 | 18 | public static void initialize(ApplicationContext applicationContext) { 19 | BeanProvider.applicationContext = applicationContext; 20 | } 21 | 22 | /** 23 | * Get Bean by clazz. 24 | * 25 | * @param clazz Class 26 | * @param class type 27 | * @return Bean instance 28 | */ 29 | public static T getBean(Class clazz) { 30 | if (applicationContext == null) { 31 | return null; 32 | } 33 | return applicationContext.getBean(clazz); 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | public static T getBean(String beanId) { 38 | if (applicationContext == null) { 39 | return null; 40 | } 41 | return (T) applicationContext.getBean(beanId); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/infrastructure/RPHolderRepositoryDefault.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.infrastructure; 2 | 3 | import myoidc.client.domain.RPHolder; 4 | import myoidc.client.domain.RPHolderRepository; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.jose4j.json.JsonUtil; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.stereotype.Repository; 10 | import org.springframework.util.FileCopyUtils; 11 | 12 | import java.io.File; 13 | import java.io.FileReader; 14 | import java.io.FileWriter; 15 | import java.io.IOException; 16 | import java.util.Map; 17 | 18 | /** 19 | * 2020/4/7 20 | *

21 | * 默认存储 RPHolder 在临时文件中/ 22 | *

23 | * 实际使用时用具体的实现(如存数据库) 24 | * 25 | * @author Shengzhao Li 26 | * @since 1.1.0 27 | */ 28 | @Repository 29 | public class RPHolderRepositoryDefault implements RPHolderRepository { 30 | 31 | private static final Logger LOG = LoggerFactory.getLogger(RPHolderRepositoryDefault.class); 32 | 33 | //文件名 34 | private static final String FILE = "myoidc-client-rpholder.json"; 35 | 36 | 37 | //临时文件对象 38 | private File file; 39 | 40 | @Override 41 | public RPHolder findRPHolder() { 42 | try { 43 | File file = getFile(); 44 | String json = FileCopyUtils.copyToString(new FileReader(file)); 45 | if(StringUtils.isNotBlank(json)){ 46 | Map map = JsonUtil.parseJson(json); 47 | return new RPHolder(map); 48 | } 49 | } catch (Exception e) { 50 | LOG.error("File handle error", e); 51 | } 52 | //返回一空对象 53 | return new RPHolder(); 54 | } 55 | 56 | @Override 57 | public boolean saveRPHolder(RPHolder rpHolder) { 58 | try { 59 | File file = getFile(); 60 | String json = rpHolder.toJSON(); 61 | FileCopyUtils.copy(json, new FileWriter(file)); 62 | return true; 63 | } catch (IOException e) { 64 | LOG.error("File handle error", e); 65 | } 66 | return false; 67 | } 68 | 69 | private File getFile() throws IOException { 70 | if (file != null && file.exists()) { 71 | LOG.debug("Use cached file: {}", file); 72 | return file; 73 | } 74 | file = new File(FILE); 75 | if (!file.exists()) { 76 | boolean ok = file.createNewFile(); 77 | LOG.debug("Create file: {} result: {}", FILE, ok); 78 | } 79 | return file; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/MyOIDCClientService.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service; 2 | 3 | 4 | import myoidc.client.domain.RPHolder; 5 | import myoidc.client.service.dto.*; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * 2020/4/7 11 | * 12 | * @author Shengzhao Li 13 | * @since 1.1.0 14 | */ 15 | public interface MyOIDCClientService { 16 | 17 | RPHolder loadRPHolder(); 18 | 19 | boolean saveRPHolder(RPHolder rpHolder); 20 | 21 | AuthAccessTokenDto createAuthAccessTokenDto(AuthCallbackDto callbackDto); 22 | 23 | AccessTokenDto retrieveAccessTokenDto(AuthAccessTokenDto tokenDto); 24 | 25 | UserInfoDto loadUserInfoDto(String access_token); 26 | 27 | Map verifyToken(String token); 28 | 29 | AccessTokenDto retrieveCredentialsAccessTokenDto(AuthAccessTokenDto tokenDto); 30 | 31 | AccessTokenDto retrievePasswordAccessTokenDto(AuthAccessTokenDto authAccessTokenDto); 32 | 33 | AccessTokenDto refreshAccessTokenDto(RefreshAccessTokenDto refreshAccessTokenDto); 34 | } 35 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/business/OIDCTokenVerifier.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.business; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import myoidc.client.domain.RPHolder; 5 | import org.jose4j.jwk.HttpsJwks; 6 | import org.jose4j.jwt.JwtClaims; 7 | import org.jose4j.jwt.consumer.InvalidJwtException; 8 | import org.jose4j.jwt.consumer.JwtConsumer; 9 | import org.jose4j.jwt.consumer.JwtConsumerBuilder; 10 | import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver; 11 | import org.jose4j.keys.resolvers.VerificationKeyResolver; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import java.util.Map; 16 | 17 | import static myoidc.client.domain.RPHolder.RESOURCE_ID; 18 | 19 | /** 20 | * 2020/4/12 21 | * 22 | * @author Shengzhao Li 23 | * @since 1.1.0 24 | */ 25 | public class OIDCTokenVerifier { 26 | 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(OIDCTokenVerifier.class); 29 | 30 | private final RPHolder rpHolder; 31 | private final String token; 32 | 33 | public OIDCTokenVerifier(RPHolder rpHolder, String token) { 34 | this.rpHolder = rpHolder; 35 | this.token = token; 36 | } 37 | 38 | public Map verify() { 39 | 40 | VerificationKeyResolver verificationKeyResolver = new HttpsJwksVerificationKeyResolver(new HttpsJwks(rpHolder.getDiscoveryEndpointInfo().getJwks_uri())); 41 | JwtConsumer consumer = new JwtConsumerBuilder() 42 | .setVerificationKeyResolver(verificationKeyResolver) 43 | //此处有许可项可配置进行校验,请根据实际需要配置 44 | //更多帮助可访问 https://bitbucket.org/b_c/jose4j/wiki/JWT%20Examples 45 | .setRequireExpirationTime() 46 | .setRequireSubject() 47 | .setRequireIssuedAt() 48 | .setExpectedAudience(RESOURCE_ID) 49 | // .setRequireNotBefore() 50 | // .setRequireJwtId() 51 | .build(); 52 | try { 53 | JwtClaims claims = consumer.processToClaims(token); 54 | return claims.getClaimsMap(); 55 | } catch (InvalidJwtException e) { 56 | LOG.warn("Verify token failed", e); 57 | return ImmutableMap.of("error", "verify_failed", "error_details", e.getErrorDetails()); 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/business/PasswordOAuth2Handler.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.business; 2 | 3 | 4 | import myoidc.client.domain.shared.BeanProvider; 5 | import myoidc.client.service.dto.AccessTokenDto; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.web.client.RestClientException; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | /** 12 | * Handle 'password' type actions 13 | *

14 | * http://localhost:8080/oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=password&scope=read,write&username=mobile&password=mobile 15 | *

16 | * How to use? 17 | * Please see unit-test PasswordOAuth2HandlerTest 18 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 19 | * 20 | * @author Shengzhao Li 21 | * @since 1.1.0 22 | */ 23 | public class PasswordOAuth2Handler { 24 | 25 | private static final Logger LOG = LoggerFactory.getLogger(PasswordOAuth2Handler.class); 26 | 27 | private transient RestTemplate restTemplate = BeanProvider.getBean(RestTemplate.class); 28 | 29 | public PasswordOAuth2Handler() { 30 | } 31 | 32 | /** 33 | * Step 1: 34 | * Get access token from Oauth server 35 | *

36 | * Response Data: 37 | * {"access_token":"9d0a2372-d039-4c1a-b0f9-762be10d531c","token_type":"bearer","refresh_token":"cfe0866d-d712-4ec2-9f23-ddb61443c9db","expires_in":38818,"scope":"read write"} 38 | *

39 | * Error Data: 40 | * 41 | * Bad client credentials 42 | * invalid_client 43 | * 44 | *

45 | * or 46 | * {"error":"invalid_grant","error_description":"Bad credentials"} 47 | * 48 | * @return AccessTokenDto 49 | */ 50 | public AccessTokenDto getAccessToken(PasswordParams params) { 51 | final String fullUri = params.getFullUri(); 52 | LOG.debug("Get 'access_token' uri: {}", fullUri); 53 | 54 | try { 55 | return restTemplate.postForObject(fullUri, null, AccessTokenDto.class); 56 | } catch (RestClientException e) { 57 | LOG.error("Send request to: {} error", fullUri, e); 58 | return new AccessTokenDto("request_error", e.getMessage()); 59 | } 60 | } 61 | 62 | 63 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/business/PasswordParams.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.business; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 'password' params 7 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 8 | * 9 | * @author Shengzhao Li 10 | * @since 1.1.0 11 | */ 12 | public class PasswordParams implements Serializable { 13 | 14 | //Fixed value 15 | public static final String GRANT_TYPE = "password"; 16 | private static final long serialVersionUID = 1671832786634202458L; 17 | 18 | 19 | private String accessTokenUri; 20 | 21 | private String clientId; 22 | private String clientSecret; 23 | 24 | private String username; 25 | private String password; 26 | 27 | 28 | //Scope, default 'openid' 29 | private String scope = "openid"; 30 | 31 | /** 32 | * Construct by ''accessTokenUri 33 | * 34 | * @param accessTokenUri Access Token Uri 35 | */ 36 | public PasswordParams(String accessTokenUri) { 37 | this.accessTokenUri = accessTokenUri; 38 | } 39 | 40 | public String getAccessTokenUri() { 41 | return accessTokenUri; 42 | } 43 | 44 | public PasswordParams setAccessTokenUri(String accessTokenUri) { 45 | this.accessTokenUri = accessTokenUri; 46 | return this; 47 | } 48 | 49 | public String getClientId() { 50 | return clientId; 51 | } 52 | 53 | public PasswordParams setClientId(String clientId) { 54 | this.clientId = clientId; 55 | return this; 56 | } 57 | 58 | public String getClientSecret() { 59 | return clientSecret; 60 | } 61 | 62 | public PasswordParams setClientSecret(String clientSecret) { 63 | this.clientSecret = clientSecret; 64 | return this; 65 | } 66 | 67 | public String getUsername() { 68 | return username; 69 | } 70 | 71 | public PasswordParams setUsername(String username) { 72 | this.username = username; 73 | return this; 74 | } 75 | 76 | public String getPassword() { 77 | return password; 78 | } 79 | 80 | public PasswordParams setPassword(String password) { 81 | this.password = password; 82 | return this; 83 | } 84 | 85 | public String getGrantType() { 86 | return GRANT_TYPE; 87 | } 88 | 89 | 90 | public String getScope() { 91 | return scope; 92 | } 93 | 94 | public PasswordParams setScope(String scope) { 95 | this.scope = scope; 96 | return this; 97 | } 98 | 99 | /* 100 | * http://localhost:8080/oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=password&scope=read,write&username=mobile&password=mobile 101 | * */ 102 | public String getFullUri() { 103 | return String.format("%s?client_id=%s&client_secret=%s&grant_type=%s&scope=%s&username=%s&password=%s", 104 | accessTokenUri, clientId, clientSecret, getGrantType(), scope, username, password); 105 | } 106 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/dto/AbstractOauthDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.dto; 2 | 3 | 4 | 5 | import org.apache.commons.lang3.StringUtils; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author Shengzhao Li 11 | */ 12 | public abstract class AbstractOauthDto implements Serializable { 13 | 14 | 15 | private static final long serialVersionUID = -5902798061281438305L; 16 | //Error if have from oauth server 17 | protected String errorDescription; 18 | protected String error; 19 | 20 | 21 | //original data 22 | protected String originalText; 23 | 24 | 25 | protected AbstractOauthDto() { 26 | } 27 | 28 | 29 | public boolean error() { 30 | return StringUtils.isNotEmpty(error) || StringUtils.isNotEmpty(errorDescription); 31 | } 32 | 33 | public String getOriginalText() { 34 | return originalText; 35 | } 36 | 37 | public void setOriginalText(String originalText) { 38 | this.originalText = originalText; 39 | } 40 | 41 | public String getErrorDescription() { 42 | return errorDescription; 43 | } 44 | 45 | public void setErrorDescription(String errorDescription) { 46 | this.errorDescription = errorDescription; 47 | } 48 | 49 | public String getError() { 50 | return error; 51 | } 52 | 53 | public void setError(String error) { 54 | this.error = error; 55 | } 56 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/dto/AuthCallbackDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.dto; 2 | 3 | 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 10 | * 11 | * @author Shengzhao Li 12 | */ 13 | public class AuthCallbackDto implements Serializable { 14 | 15 | 16 | private static final long serialVersionUID = 4713732199062099307L; 17 | private String code; 18 | private String state; 19 | 20 | /* 21 | * Server response error, 22 | * For example: Click 'Deny' button 23 | * */ 24 | private String error; 25 | private String error_description; 26 | 27 | 28 | public AuthCallbackDto() { 29 | } 30 | 31 | public String getError() { 32 | return error; 33 | } 34 | 35 | public boolean error() { 36 | return StringUtils.isNotEmpty(error) || StringUtils.isNotEmpty(error_description); 37 | } 38 | 39 | public void setError(String error) { 40 | this.error = error; 41 | } 42 | 43 | public String getError_description() { 44 | return error_description; 45 | } 46 | 47 | public void setError_description(String error_description) { 48 | this.error_description = error_description; 49 | } 50 | 51 | public String getCode() { 52 | return code; 53 | } 54 | 55 | public void setCode(String code) { 56 | this.code = code; 57 | } 58 | 59 | public String getState() { 60 | return state; 61 | } 62 | 63 | public void setState(String state) { 64 | this.state = state; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/dto/AuthorizationCodeDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.dto; 2 | 3 | import java.io.Serializable; 4 | import java.io.UnsupportedEncodingException; 5 | import java.net.URLEncoder; 6 | 7 | /** 8 | * *

9 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 10 | * 11 | * @author Shengzhao Li 12 | */ 13 | public class AuthorizationCodeDto implements Serializable { 14 | 15 | 16 | private static final long serialVersionUID = -5293876788733247369L; 17 | private String userAuthorizationUri; 18 | private String responseType; 19 | private String scope; 20 | private String clientId; 21 | private String redirectUri; 22 | private String state; 23 | 24 | 25 | public AuthorizationCodeDto() { 26 | } 27 | 28 | 29 | public String getUserAuthorizationUri() { 30 | return userAuthorizationUri; 31 | } 32 | 33 | public void setUserAuthorizationUri(String userAuthorizationUri) { 34 | this.userAuthorizationUri = userAuthorizationUri; 35 | } 36 | 37 | public String getResponseType() { 38 | return responseType; 39 | } 40 | 41 | public void setResponseType(String responseType) { 42 | this.responseType = responseType; 43 | } 44 | 45 | public String getScope() { 46 | return scope; 47 | } 48 | 49 | public void setScope(String scope) { 50 | this.scope = scope; 51 | } 52 | 53 | public String getClientId() { 54 | return clientId; 55 | } 56 | 57 | public void setClientId(String clientId) { 58 | this.clientId = clientId; 59 | } 60 | 61 | public String getRedirectUri() { 62 | return redirectUri; 63 | } 64 | 65 | public void setRedirectUri(String redirectUri) { 66 | this.redirectUri = redirectUri; 67 | } 68 | 69 | public String getState() { 70 | return state; 71 | } 72 | 73 | public void setState(String state) { 74 | this.state = state; 75 | } 76 | 77 | /* 78 | * http://localhost:8080/oauth/authorize?client_id=unity-client&redirect_uri=http%3a%2f%2flocalhost%3a8080%2funity%2fdashboard.htm&response_type=code&scope=read 79 | * */ 80 | public String getFullUri() throws UnsupportedEncodingException { 81 | String redirect = URLEncoder.encode(redirectUri, "UTF-8"); 82 | return String.format("%s?response_type=%s&scope=%s&client_id=%s&redirect_uri=%s&state=%s", userAuthorizationUri, responseType, scope, clientId, redirect, state); 83 | } 84 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/dto/RefreshAccessTokenDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * http://localhost:8080/spring-oauth-server/oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=refresh_token&refresh_token=b36f4978-a172-4aa8-af89-60f58abe3ba1 9 | * 10 | * @author Shengzhao Li 11 | * @since 1.1.0 12 | */ 13 | public class RefreshAccessTokenDto implements Serializable { 14 | 15 | private static final long serialVersionUID = -8617579193689091944L; 16 | private String refreshAccessTokenUri; 17 | private String clientId; 18 | private String clientSecret; 19 | 20 | private String grantType = "refresh_token"; 21 | 22 | private String refreshToken; 23 | 24 | 25 | public RefreshAccessTokenDto() { 26 | } 27 | 28 | public String getRefreshAccessTokenUri() { 29 | return refreshAccessTokenUri; 30 | } 31 | 32 | public void setRefreshAccessTokenUri(String refreshAccessTokenUri) { 33 | this.refreshAccessTokenUri = refreshAccessTokenUri; 34 | } 35 | 36 | public String getClientId() { 37 | return clientId; 38 | } 39 | 40 | public void setClientId(String clientId) { 41 | this.clientId = clientId; 42 | } 43 | 44 | public String getClientSecret() { 45 | return clientSecret; 46 | } 47 | 48 | public void setClientSecret(String clientSecret) { 49 | this.clientSecret = clientSecret; 50 | } 51 | 52 | public String getGrantType() { 53 | return grantType; 54 | } 55 | 56 | public void setGrantType(String grantType) { 57 | this.grantType = grantType; 58 | } 59 | 60 | public String getRefreshToken() { 61 | return refreshToken; 62 | } 63 | 64 | public void setRefreshToken(String refreshToken) { 65 | this.refreshToken = refreshToken; 66 | } 67 | 68 | /* 69 | * http://localhost:8080/spring-oauth-server/oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=refresh_token&refresh_token=b36f4978-a172-4aa8-af89-60f58abe3ba1 70 | * */ 71 | public Map getRefreshTokenParams() { 72 | Map map = new HashMap<>(); 73 | map.put("client_id", clientId); 74 | 75 | map.put("client_secret", clientSecret); 76 | map.put("grant_type", grantType); 77 | map.put("refresh_token", refreshToken); 78 | 79 | return map; 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/service/dto/UserInfoDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.service.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | *

10 |  *     {"openid":"Ajlt9ZwVyGUvxrJCdKlFA4AataAVKVgH6gxYeCxD6J","username":"mobile","phone":null,"email":"mobile@qc8.me","create_time":0,"privileges":["USER","ADMIN","UNITY","MOBILE"]}
11 |  * 
12 | * 13 | * @author Shengzhao Li 14 | * @since 1.1.0 15 | */ 16 | public class UserInfoDto extends AbstractOauthDto { 17 | 18 | 19 | private static final long serialVersionUID = -4028887815415395655L; 20 | 21 | @JsonProperty("create_time") 22 | private long createTime; 23 | private String email; 24 | private String openid; 25 | 26 | private String phone; 27 | private String username; 28 | 29 | private List privileges = new ArrayList<>(); 30 | 31 | 32 | public UserInfoDto() { 33 | } 34 | 35 | public UserInfoDto(String error, String errorDescription) { 36 | this.error = error; 37 | this.errorDescription = errorDescription; 38 | } 39 | 40 | 41 | public long getCreateTime() { 42 | return createTime; 43 | } 44 | 45 | public void setCreateTime(long createTime) { 46 | this.createTime = createTime; 47 | } 48 | 49 | public String getOpenid() { 50 | return openid; 51 | } 52 | 53 | public void setOpenid(String openid) { 54 | this.openid = openid; 55 | } 56 | 57 | public String getEmail() { 58 | return email; 59 | } 60 | 61 | public void setEmail(String email) { 62 | this.email = email; 63 | } 64 | 65 | 66 | public String getPhone() { 67 | return phone; 68 | } 69 | 70 | public void setPhone(String phone) { 71 | this.phone = phone; 72 | } 73 | 74 | public String getUsername() { 75 | return username; 76 | } 77 | 78 | public void setUsername(String username) { 79 | this.username = username; 80 | } 81 | 82 | public List getPrivileges() { 83 | return privileges; 84 | } 85 | 86 | public void setPrivileges(List privileges) { 87 | this.privileges = privileges; 88 | } 89 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/WebUtils.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web; 2 | 3 | 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | /** 10 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | public abstract class WebUtils { 15 | 16 | 17 | private WebUtils() { 18 | } 19 | 20 | 21 | /* 22 | * Save state to ServletContext, key = value = state 23 | */ 24 | public static void saveState(HttpServletRequest request, String state) { 25 | final ServletContext servletContext = request.getSession().getServletContext(); 26 | servletContext.setAttribute(state, state); 27 | } 28 | 29 | /* 30 | * Validate state when callback from Oauth Server. 31 | * If validation successful, will remove it from ServletContext. 32 | */ 33 | public static boolean validateState(HttpServletRequest request, String state) { 34 | if (StringUtils.isBlank(state)) { 35 | return false; 36 | } 37 | final ServletContext servletContext = request.getSession().getServletContext(); 38 | final Object value = servletContext.getAttribute(state); 39 | 40 | if (value != null) { 41 | servletContext.removeAttribute(state); 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | 48 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/context/OIDCApplicationContextAware.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.context; 2 | 3 | 4 | import myoidc.client.domain.shared.Application; 5 | import myoidc.client.domain.shared.BeanProvider; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.BeansException; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.ApplicationContext; 11 | import org.springframework.context.ApplicationContextAware; 12 | import org.springframework.stereotype.Component; 13 | 14 | /** 15 | * 2018/03/22 16 | *

17 | * 18 | * @author Shengzhao Li 19 | */ 20 | @Component 21 | public class OIDCApplicationContextAware implements ApplicationContextAware { 22 | 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(OIDCApplicationContextAware.class); 25 | 26 | 27 | @Value("${spring.application.name}") 28 | private String applicationName; 29 | 30 | 31 | @Value("${application.host}") 32 | private String applicationHost; 33 | 34 | 35 | public OIDCApplicationContextAware() { 36 | } 37 | 38 | @Override 39 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 40 | BeanProvider.initialize(applicationContext); 41 | 42 | if (LOG.isDebugEnabled()) { 43 | LOG.debug("Initialed BeanProvider from ApplicationContext: {}", applicationContext); 44 | } 45 | LOG.info("{} context initialized, Version: {}, applicationHost: {}\n", this.applicationName, Application.VERSION, this.applicationHost); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/context/OIDCServletContextAware.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.context; 2 | 3 | import myoidc.client.domain.shared.Application; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.context.ServletContextAware; 8 | 9 | import javax.servlet.ServletContext; 10 | 11 | /** 12 | * 2020/5/7 13 | * 14 | * @author Shengzhao Li 15 | * @since 1.1.1 16 | */ 17 | @Component 18 | public class OIDCServletContextAware implements ServletContextAware { 19 | 20 | private static final Logger LOG = LoggerFactory.getLogger(OIDCServletContextAware.class); 21 | 22 | public OIDCServletContextAware() { 23 | } 24 | 25 | @Override 26 | public void setServletContext(ServletContext servletContext) { 27 | 28 | //主版本号 29 | servletContext.setAttribute("mainVersion", Application.VERSION); 30 | LOG.debug("Initialed: {}, mainVersion: {}", this, Application.VERSION); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/controller/ClientCredentialsController.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.controller; 2 | 3 | 4 | import myoidc.client.domain.DiscoveryEndpointInfo; 5 | import myoidc.client.domain.RPHolder; 6 | import myoidc.client.service.MyOIDCClientService; 7 | import myoidc.client.service.dto.AccessTokenDto; 8 | import myoidc.client.service.dto.AuthAccessTokenDto; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.ui.Model; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RequestMethod; 17 | import org.springframework.web.bind.annotation.ResponseBody; 18 | 19 | import javax.servlet.http.HttpServletResponse; 20 | 21 | 22 | /** 23 | * Handle 'client_credentials' type actions 24 | * 25 | * @author Shengzhao Li 26 | * @since 1.1.0 27 | */ 28 | @Controller 29 | public class ClientCredentialsController { 30 | 31 | 32 | private static final Logger LOG = LoggerFactory.getLogger(ClientCredentialsController.class); 33 | 34 | 35 | @Autowired 36 | private MyOIDCClientService clientService; 37 | 38 | /** 39 | * Entrance: step-1 40 | */ 41 | @GetMapping(value = "client_credentials") 42 | public String password(Model model) { 43 | RPHolder rpHoldDto = clientService.loadRPHolder(); 44 | //异常跳转回主页 45 | if (!rpHoldDto.isConfigRP()) { 46 | return "redirect:/"; 47 | } 48 | DiscoveryEndpointInfo endpointInfo = rpHoldDto.getDiscoveryEndpointInfo(); 49 | LOG.debug("Go to 'client_credentials' page, accessTokenUri = {}", endpointInfo.getToken_endpoint()); 50 | model.addAttribute("rpHoldDto", rpHoldDto); 51 | model.addAttribute("endpointInfo", endpointInfo); 52 | return "client_credentials"; 53 | } 54 | 55 | 56 | /** 57 | * Ajax call , get access_token 58 | */ 59 | @GetMapping(value = "credentials_access_token") 60 | @ResponseBody 61 | public AccessTokenDto getAccessToken(AuthAccessTokenDto authAccessTokenDto) { 62 | return clientService.retrieveCredentialsAccessTokenDto(authAccessTokenDto); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/controller/ImplicitController.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.controller; 2 | 3 | import myoidc.client.domain.DiscoveryEndpointInfo; 4 | import myoidc.client.domain.RPHolder; 5 | import myoidc.client.domain.shared.Application; 6 | import myoidc.client.service.MyOIDCClientService; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.ui.Model; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | 14 | /** 15 | * Handle 'implicit' type actions 16 | * 17 | * @author Shengzhao Li 18 | * @since 1.1.0 19 | */ 20 | @Controller 21 | public class ImplicitController { 22 | 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(ImplicitController.class); 25 | 26 | 27 | @Autowired 28 | private MyOIDCClientService clientService; 29 | 30 | 31 | /** 32 | * Entrance: step-1 33 | */ 34 | @GetMapping(value = "implicit") 35 | public String password(Model model) { 36 | RPHolder rpHoldDto = clientService.loadRPHolder(); 37 | //异常跳转回主页 38 | if (!rpHoldDto.isConfigRP()) { 39 | return "redirect:/"; 40 | } 41 | DiscoveryEndpointInfo endpointInfo = rpHoldDto.getDiscoveryEndpointInfo(); 42 | LOG.debug("Go to 'implicit' page: {}",endpointInfo); 43 | model.addAttribute("rpHoldDto", rpHoldDto); 44 | model.addAttribute("endpointInfo", endpointInfo); 45 | // model.addAttribute("userAuthorizationUri", userAuthorizationUri); 46 | // model.addAttribute("unityUserInfoUri", unityUserInfoUri); 47 | model.addAttribute("host", Application.host()); 48 | return "implicit"; 49 | } 50 | 51 | 52 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/controller/PasswordController.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.controller; 2 | 3 | import myoidc.client.domain.DiscoveryEndpointInfo; 4 | import myoidc.client.domain.RPHolder; 5 | import myoidc.client.service.MyOIDCClientService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.ui.Model; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | 13 | /** 14 | * Handle 'password' type actions 15 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 16 | * 17 | * @author Shengzhao Li 18 | * @since 1.1.0 19 | */ 20 | @Controller 21 | public class PasswordController { 22 | 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(PasswordController.class); 25 | 26 | 27 | @Autowired 28 | private MyOIDCClientService clientService; 29 | 30 | 31 | /** 32 | * Entrance: step-1 33 | */ 34 | @GetMapping(value = "password") 35 | public String password(Model model) { 36 | RPHolder rpHoldDto = clientService.loadRPHolder(); 37 | //异常跳转回主页 38 | if (!rpHoldDto.isConfigRP()) { 39 | return "redirect:/"; 40 | } 41 | DiscoveryEndpointInfo endpointInfo = rpHoldDto.getDiscoveryEndpointInfo(); 42 | LOG.debug("Go to 'password' page, accessTokenUri = {}", endpointInfo.getToken_endpoint()); 43 | model.addAttribute("accessTokenUri", endpointInfo.getToken_endpoint()); 44 | model.addAttribute("rpHoldDto", rpHoldDto); 45 | return "password"; 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/controller/RefreshTokenController.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.controller; 2 | 3 | 4 | import myoidc.client.domain.DiscoveryEndpointInfo; 5 | import myoidc.client.domain.RPHolder; 6 | import myoidc.client.service.MyOIDCClientService; 7 | import myoidc.client.service.dto.AccessTokenDto; 8 | import myoidc.client.service.dto.AuthAccessTokenDto; 9 | import myoidc.client.service.dto.RefreshAccessTokenDto; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.ui.Model; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.ResponseBody; 17 | 18 | 19 | /** 20 | * Handle 'refresh_token' type actions 21 | * From spring-oauth-client(https://gitee.com/mkk/spring-oauth-client) 22 | * 23 | * @author Shengzhao Li 24 | * @since 1.1.0 25 | */ 26 | @Controller 27 | public class RefreshTokenController { 28 | 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(RefreshTokenController.class); 31 | 32 | 33 | @Autowired 34 | private MyOIDCClientService clientService; 35 | 36 | /** 37 | * Entrance: step-1 38 | */ 39 | @GetMapping(value = "refresh_token") 40 | public String refresh(Model model) { 41 | RPHolder rpHoldDto = clientService.loadRPHolder(); 42 | //异常跳转回主页 43 | if (!rpHoldDto.isConfigRP()) { 44 | return "redirect:/"; 45 | } 46 | DiscoveryEndpointInfo endpointInfo = rpHoldDto.getDiscoveryEndpointInfo(); 47 | LOG.debug("Go to 'refresh_token' page, DiscoveryEndpointInfo = {}", endpointInfo); 48 | model.addAttribute("rpHoldDto", rpHoldDto); 49 | model.addAttribute("endpointInfo", endpointInfo); 50 | return "refresh_token"; 51 | } 52 | 53 | /** 54 | * Ajax call , get access_token 55 | */ 56 | @GetMapping(value = "password_access_token") 57 | @ResponseBody 58 | public AccessTokenDto getAccessToken(AuthAccessTokenDto authAccessTokenDto) { 59 | return clientService.retrievePasswordAccessTokenDto(authAccessTokenDto); 60 | } 61 | 62 | /** 63 | * Ajax call , refresh access_token 64 | */ 65 | @GetMapping(value = "refresh_access_token") 66 | @ResponseBody 67 | public AccessTokenDto refreshAccessToken(RefreshAccessTokenDto refreshAccessTokenDto) { 68 | return clientService.refreshAccessTokenDto(refreshAccessTokenDto); 69 | } 70 | 71 | 72 | } -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/controller/StartupController.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.controller; 2 | 3 | 4 | import myoidc.client.domain.shared.Application; 5 | import myoidc.client.service.MyOIDCClientService; 6 | import myoidc.client.domain.RPHolder; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.ui.Model; 12 | import org.springframework.validation.BindingResult; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import javax.validation.Valid; 16 | import java.util.Map; 17 | 18 | 19 | /** 20 | * 2018/2/5 21 | *

22 | * 引导 入口 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | @Controller 27 | public class StartupController { 28 | 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(StartupController.class); 31 | 32 | 33 | @Autowired 34 | private MyOIDCClientService clientService; 35 | 36 | /** 37 | * 首页 38 | */ 39 | @GetMapping("/") 40 | public String index(Model model) { 41 | RPHolder rpHoldDto = clientService.loadRPHolder(); 42 | model.addAttribute("host", Application.host()); 43 | model.addAttribute("formDto", rpHoldDto); 44 | return "index"; 45 | } 46 | 47 | /** 48 | * submit 49 | * 提交RP信息 50 | * 51 | * @since 1.1.0 52 | */ 53 | @PostMapping("/submit") 54 | public String submit(@ModelAttribute("formDto") @Valid RPHolder formDto, BindingResult result, Model model) { 55 | if (result.hasErrors()) { 56 | return "index"; 57 | } 58 | boolean ok = clientService.saveRPHolder(formDto); 59 | model.addAttribute("saveResult", ok); 60 | return "redirect:/"; 61 | } 62 | 63 | 64 | /** 65 | * Common handle oauth error , 66 | * show the error message. 67 | * 68 | * @since 1..1.0 69 | */ 70 | @RequestMapping("oauth_error") 71 | public String oauthError(String error, String message, Model model) { 72 | model.addAttribute("error", error); 73 | model.addAttribute("message", message); 74 | 75 | LOG.debug("Go to oauth_error, error={},message={}", error, message); 76 | return "oauth_error"; 77 | } 78 | 79 | 80 | /** 81 | * verify id_token 82 | * 83 | * @param token token 84 | * @return map 85 | * @since 1.1.0 86 | */ 87 | @GetMapping("verify_token") 88 | @ResponseBody 89 | public Map verifyIdToken(@RequestParam String token) { 90 | return clientService.verifyToken(token); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /myoidc-client/src/main/java/myoidc/client/web/controller/UserInfoController.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.web.controller; 2 | 3 | import myoidc.client.service.MyOIDCClientService; 4 | import myoidc.client.service.dto.UserInfoDto; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | 10 | /** 11 | * 2020/4/11 12 | * 13 | * @author Shengzhao Li 14 | * @since 1.1.0 15 | */ 16 | @Controller 17 | public class UserInfoController { 18 | 19 | 20 | @Autowired 21 | private MyOIDCClientService clientService; 22 | 23 | 24 | /** 25 | * user_info API 26 | */ 27 | @GetMapping("user_info") 28 | public String unityUserInfo(String access_token, Model model) { 29 | UserInfoDto userDto = clientService.loadUserInfoDto(access_token); 30 | 31 | if (userDto.error()) { 32 | //error 33 | model.addAttribute("message", userDto.getErrorDescription()); 34 | model.addAttribute("error", userDto.getError()); 35 | return "redirect:oauth_error"; 36 | } else { 37 | model.addAttribute("userDto", userDto); 38 | return "user_info"; 39 | } 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # MyOIDC -Client V-1.1.0 2 | # 3 | spring.application.name=MyOIDC[Client] 4 | spring.main.allow-bean-definition-overriding=true 5 | spring.jmx.enabled=false 6 | # 7 | # 8 | # MVC 9 | spring.mvc.ignore-default-model-on-redirect=false 10 | spring.http.encoding.enabled=true 11 | spring.http.encoding.charset=UTF-8 12 | spring.http.encoding.force=true 13 | # 14 | #THYMELEAF (ThymeleafAutoConfiguration) 15 | # 16 | #spring.thymeleaf.prefix=/WEB-INF/view/ 17 | #spring.thymeleaf.suffix=.html 18 | #spring.thymeleaf.mode=HTML5 19 | spring.thymeleaf.encoding=UTF-8 20 | # ;charset= is added 21 | # set to false for hot refresh 22 | spring.thymeleaf.cache=false 23 | # 24 | # Logging INFO 25 | # 26 | logging.level.root=INFO 27 | #logging.config=classpath:log4j2.xml 28 | #logging.level.org.springframework.transaction.interceptor=TRACE 29 | # 30 | # Security 31 | # 32 | # 33 | #Tomcat Server Config 34 | # 35 | server.tomcat.accesslog.enabled=true 36 | server.tomcat.uri-encoding=UTF-8 37 | server.port=8087 38 | # 39 | # gzip, compression 40 | server.compression.enabled=true 41 | server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain 42 | server.compression.min-response-size=1024 43 | # 44 | #Application host url, end by '/' 45 | application.host=http://localhost:${server.port}/ 46 | 47 | -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-client/src/main/resources/static/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-client/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/templates/error/405.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Error-405 . MyOIDC[RP] 8 | 9 | 10 | 11 | 12 | 13 |

14 | 15 |
16 |

405 17 | 18 | Method Not Allowed 19 | 20 |

21 |
22 | 回主页 23 |
24 | 25 | 26 |
27 | 28 | 29 |
30 |
31 | 32 | -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/templates/fragment/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Fragment Footer 6 | 7 | 8 | 9 |
10 | 11 |

© 2017-2020  MyOIDC  13 | V

14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/templates/fragment/header.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Fragment Header 7 | 8 | 9 |
10 | 12 |
13 | 14 | 15 | 16 | 17 |
18 | 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/templates/oauth_error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | OAuth2 Error . MyOIDC[RP] 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 |
16 |

OAuth2 Error

17 | 18 |
19 |

error

20 |
err
21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /myoidc-client/src/main/resources/templates/user_info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | User Info . MyOIDC[RP] 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 |

User Info 18 | 数据来源于 'myoidc-server' 中提供的User Info API接口 19 |

20 | 21 |
22 |
username
23 |
user1
24 |
openid
25 |
oows
26 |
phone
27 |
se
28 |
email
29 |
sz
30 |
privileges
31 |
32 |
createTime
33 |
34 | 35 |
36 | 37 | Back 38 |
39 | 40 | 41 |
42 |
43 | 44 | -------------------------------------------------------------------------------- /myoidc-client/src/test/java/myoidc/client/MyOIDCClientApplicationTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.client; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.TestPropertySource; 7 | import org.springframework.test.context.junit4.SpringRunner; 8 | 9 | import static org.junit.Assert.*; 10 | 11 | /** 12 | * 2018/5/26 13 | * 14 | * @author Shengzhao Li 15 | */ 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | @TestPropertySource(locations = "classpath:application-test.properties") 19 | public class MyOIDCClientApplicationTest { 20 | 21 | 22 | 23 | @Test 24 | public void contextLoads() { 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /myoidc-client/src/test/java/myoidc/client/domain/DiscoveryEndpointInfoTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.domain; 2 | 3 | import org.junit.Ignore; 4 | import org.junit.Test; 5 | import org.springframework.web.client.RestTemplate; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | /** 10 | * 2020/4/7 11 | * 12 | * @author Shengzhao Li 13 | * @since 1.1.0 14 | */ 15 | public class DiscoveryEndpointInfoTest { 16 | 17 | 18 | @Test 19 | @Ignore 20 | public void test() { 21 | 22 | RestTemplate restTemplate = new RestTemplate(); 23 | DiscoveryEndpointInfo info = restTemplate.getForObject("http://localhost:8080/myoidc-server/.well-known/openid-configuration", DiscoveryEndpointInfo.class); 24 | 25 | assertNotNull(info); 26 | 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /myoidc-client/src/test/java/myoidc/client/infrastructure/RPHolderRepositoryDefaultTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.client.infrastructure; 2 | 3 | import myoidc.client.domain.RPHolder; 4 | import org.junit.Ignore; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | /** 10 | * 2020/4/7 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | public class RPHolderRepositoryDefaultTest { 15 | 16 | 17 | private RPHolderRepositoryDefault repositoryDefault = new RPHolderRepositoryDefault(); 18 | 19 | 20 | @Test 21 | @Ignore 22 | public void test() { 23 | 24 | 25 | RPHolder rpHolder = repositoryDefault.findRPHolder(); 26 | assertNotNull(rpHolder); 27 | // assertFalse(rpHolder.isConfigRP()); 28 | 29 | 30 | rpHolder = new RPHolder(); 31 | rpHolder.setClientId("clientId"); 32 | rpHolder.setClientSecret("clientSecret"); 33 | rpHolder.setDiscoveryEndpoint("https://..."); 34 | 35 | boolean ok = repositoryDefault.saveRPHolder(rpHolder); 36 | assertTrue(ok); 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /myoidc-client/src/test/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | # MyOIDC -Client V-1.1.0 2 | # 3 | spring.application.name=MyOIDC[Client] 4 | # 5 | # 6 | # MVC 7 | spring.mvc.ignore-default-model-on-redirect=false 8 | spring.http.encoding.enabled=true 9 | spring.http.encoding.charset=UTF-8 10 | spring.http.encoding.force=true 11 | # 12 | #THYMELEAF (ThymeleafAutoConfiguration) 13 | # 14 | spring.thymeleaf.prefix=/WEB-INF/view/ 15 | spring.thymeleaf.suffix=.html 16 | #spring.thymeleaf.mode=HTML5 17 | spring.thymeleaf.encoding=UTF-8 18 | # ;charset= is added 19 | # set to false for hot refresh 20 | spring.thymeleaf.cache=false 21 | # 22 | # Logging INFO 23 | # 24 | logging.level.root=INFO 25 | #logging.config=classpath:log4j2.xml 26 | #logging.level.org.springframework.transaction.interceptor=TRACE 27 | # 28 | # Security 29 | # 30 | # 31 | #Tomcat Server Config 32 | # 33 | server.tomcat.accesslog.enabled=true 34 | server.tomcat.uri-encoding=UTF-8 35 | server.port=8080 36 | # 37 | # gzip, compression 38 | server.compression.enabled=true 39 | server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain 40 | server.compression.min-response-size=1024 41 | # 42 | #Application host url, end by '/' 43 | application.host=http://localhost:8080/myoidc-client/ 44 | 45 | -------------------------------------------------------------------------------- /myoidc-server/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /myoidc-server/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip 2 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/Constants.java: -------------------------------------------------------------------------------- 1 | package myoidc.server; 2 | 3 | import org.jose4j.jwk.JsonWebKey; 4 | import org.jose4j.jwk.Use; 5 | import org.jose4j.jws.AlgorithmIdentifiers; 6 | 7 | /** 8 | * 2020/3/11 9 | * 10 | * @author Shengzhao Li 11 | * @since 1.1.0 12 | */ 13 | public interface Constants { 14 | 15 | /*Fixed, resource-id */ 16 | String RESOURCE_ID = "myoidc-resource"; 17 | 18 | /** 19 | * Fixed keyId 20 | * 21 | * @since 1.1.0 22 | */ 23 | String DEFAULT_KEY_ID = "myoidc-keyid"; 24 | 25 | /** 26 | * 长度 至少 1024, 建议 2048 27 | * 28 | * @since 1.1.0 29 | */ 30 | int DEFAULT_KEY_SIZE = 2048; 31 | 32 | 33 | /** 34 | * keystore file name 35 | * 36 | * @since 1.1.0 37 | */ 38 | String KEYSTORE_NAME = "jwks.json"; 39 | 40 | /** 41 | * Default ALG: RS256 42 | * 43 | * @since 1.1.0 44 | */ 45 | String OIDC_ALG = AlgorithmIdentifiers.RSA_USING_SHA256; 46 | 47 | /** 48 | * OIDC key use: sig or enc 49 | * 50 | * @since 1.1.0 51 | */ 52 | String USE_SIG = Use.SIGNATURE; 53 | String USE_ENC = Use.ENCRYPTION; 54 | 55 | /** 56 | * id_token constants 57 | * 58 | * @since 1.1.0 59 | */ 60 | String ID_TOKEN = "id_token"; 61 | 62 | /** 63 | * JWT keyid 64 | * 65 | * @since 1.1.0 66 | */ 67 | String KEY_ID = JsonWebKey.KEY_ID_PARAMETER; 68 | 69 | 70 | //系统字符编码 71 | String ENCODING = "UTF-8"; 72 | 73 | String PROJECT_HOME = "https://github.com/monkeyk/MyOIDC"; 74 | 75 | //Current version 76 | String VERSION = "1.1.1"; 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/MyOIDCServerApplication.java: -------------------------------------------------------------------------------- 1 | package myoidc.server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Spring Boot bootstrap 8 | */ 9 | @SpringBootApplication 10 | public class MyOIDCServerApplication { 11 | 12 | 13 | /** 14 | * Run it directly 15 | * 16 | * @param args args 17 | */ 18 | public static void main(String[] args) { 19 | SpringApplication.run(MyOIDCServerApplication.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/config/MVCConfiguration.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.config; 2 | 3 | 4 | import myoidc.server.domain.shared.Application; 5 | import myoidc.server.web.filter.ExtCharacterEncodingFilter; 6 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.converter.HttpMessageConverter; 10 | import org.springframework.http.converter.StringHttpMessageConverter; 11 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 12 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 13 | 14 | import javax.servlet.Filter; 15 | import java.nio.charset.Charset; 16 | import java.util.List; 17 | 18 | /** 19 | * 2018/1/30 20 | *

21 | * Spring MVC 扩展配置 22 | *

23 | * 24 | * @author Shengzhao Li 25 | */ 26 | @Configuration 27 | public class MVCConfiguration implements WebMvcConfigurer { 28 | 29 | 30 | /** 31 | * 扩展拦截器 32 | */ 33 | @Override 34 | public void addInterceptors(InterceptorRegistry registry) { 35 | 36 | WebMvcConfigurer.super.addInterceptors(registry); 37 | } 38 | 39 | 40 | /** 41 | * 字符编码配置 UTF-8 42 | */ 43 | @Bean 44 | public FilterRegistrationBean encodingFilter() { 45 | FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); 46 | registrationBean.setFilter(new ExtCharacterEncodingFilter()); 47 | registrationBean.addUrlPatterns("/*"); 48 | return registrationBean; 49 | } 50 | 51 | 52 | /** 53 | * 解决乱码问题 54 | * For UTF-8 55 | */ 56 | @Override 57 | public void configureMessageConverters(List> converters) { 58 | WebMvcConfigurer.super.configureMessageConverters(converters); 59 | converters.add(new StringHttpMessageConverter(Charset.forName(Application.ENCODING))); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/config/MyOIDCConfiguration.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.config; 2 | 3 | 4 | import myoidc.server.domain.shared.Application; 5 | import org.hibernate.SessionFactory; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.orm.hibernate5.HibernateTransactionManager; 10 | import org.springframework.orm.hibernate5.LocalSessionFactoryBean; 11 | import org.springframework.transaction.PlatformTransactionManager; 12 | import org.springframework.transaction.annotation.EnableTransactionManagement; 13 | 14 | import javax.sql.DataSource; 15 | import java.util.Properties; 16 | 17 | 18 | /** 19 | * 2018/1/30 20 | *

21 | * 22 | * @author Shengzhao Li 23 | */ 24 | @Configuration 25 | @EnableTransactionManagement 26 | public class MyOIDCConfiguration { 27 | 28 | 29 | @Value("${application.host}") 30 | private String host; 31 | 32 | 33 | // Application 34 | @Bean 35 | public Application application() { 36 | Application application = new Application(); 37 | application.setHost(host); 38 | return application; 39 | } 40 | 41 | 42 | 43 | @Bean 44 | public LocalSessionFactoryBean sessionFactory(DataSource dataSource) { 45 | LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); 46 | factoryBean.setDataSource(dataSource); 47 | factoryBean.setPackagesToScan("myoidc.server.domain"); 48 | 49 | Properties properties = new Properties(); 50 | properties.setProperty("hibernate.show_sql", "false"); 51 | properties.setProperty("jdbc.use_scrollable_resultset", "false"); 52 | properties.setProperty("hibernate.query.substitutions", "true=1,false=0"); 53 | properties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL57Dialect"); 54 | properties.setProperty("hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext"); 55 | factoryBean.setHibernateProperties(properties); 56 | 57 | return factoryBean; 58 | } 59 | 60 | 61 | @Bean 62 | public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) { 63 | HibernateTransactionManager transactionManager = new HibernateTransactionManager(); 64 | transactionManager.setSessionFactory(sessionFactory); 65 | return transactionManager; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/config/OAuth2MethodSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; 5 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 6 | import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; 7 | import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler; 8 | 9 | /** 10 | * 2018/3/22 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | @Configuration 15 | @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) 16 | public class OAuth2MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration { 17 | 18 | 19 | @Override 20 | protected MethodSecurityExpressionHandler createExpressionHandler() { 21 | return new OAuth2MethodSecurityExpressionHandler(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/AbstractDomain.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain; 2 | 3 | 4 | import myoidc.server.domain.shared.UUIDGenerator; 5 | 6 | import javax.persistence.*; 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author Shengzhao Li 12 | */ 13 | @MappedSuperclass 14 | public abstract class AbstractDomain implements Serializable { 15 | 16 | private static final long serialVersionUID = 913921286328215144L; 17 | /** 18 | * Database id 19 | */ 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | @Column(name = "id") 23 | protected int id; 24 | 25 | @Column(name = "archived", columnDefinition = "tinyint(1)") 26 | protected boolean archived; 27 | 28 | /** 29 | * 乐观锁 30 | */ 31 | @Version 32 | @Column(name = "version") 33 | protected int version; 34 | 35 | /** 36 | * Domain business uuid. 37 | */ 38 | @Column(name = "uuid", unique = true) 39 | protected String uuid = UUIDGenerator.generate(); 40 | 41 | /** 42 | * The domain create time. 43 | */ 44 | @Column(name = "create_time") 45 | // @Type(type = "org.hibernate.type.LocalDateTimeType") 46 | protected LocalDateTime createTime = LocalDateTime.now(); 47 | 48 | 49 | public AbstractDomain() { 50 | } 51 | 52 | public int id() { 53 | return id; 54 | } 55 | 56 | public void id(int id) { 57 | this.id = id; 58 | } 59 | 60 | public boolean archived() { 61 | return archived; 62 | } 63 | 64 | public AbstractDomain archived(boolean archived) { 65 | this.archived = archived; 66 | return this; 67 | } 68 | 69 | public String uuid() { 70 | return uuid; 71 | } 72 | 73 | public void uuid(String uuid) { 74 | this.uuid = uuid; 75 | } 76 | 77 | public LocalDateTime createTime() { 78 | return createTime; 79 | } 80 | 81 | public boolean isNewly() { 82 | return id == 0; 83 | } 84 | 85 | @Override 86 | public boolean equals(Object o) { 87 | if (this == o) { 88 | return true; 89 | } 90 | if (!(o instanceof AbstractDomain)) { 91 | return false; 92 | } 93 | AbstractDomain that = (AbstractDomain) o; 94 | return uuid.equals(that.uuid); 95 | } 96 | 97 | @Override 98 | public int hashCode() { 99 | return uuid.hashCode(); 100 | } 101 | 102 | 103 | @Override 104 | public String toString() { 105 | final StringBuilder sb = new StringBuilder(); 106 | sb.append("{id=").append(id); 107 | sb.append(", archived=").append(archived); 108 | sb.append(", version=").append(version); 109 | sb.append(", uuid='").append(uuid).append('\''); 110 | sb.append(", createTime=").append(createTime); 111 | sb.append('}'); 112 | return sb.toString(); 113 | } 114 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/README.txt: -------------------------------------------------------------------------------- 1 | 2 | All Domain, shared in Here -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/oauth/OauthRepository.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.oauth; 2 | 3 | 4 | import java.util.List; 5 | 6 | /** 7 | * 处理 OAuth 相关业务的 Repository 8 | * 9 | * @author Shengzhao Li 10 | */ 11 | public interface OauthRepository { 12 | 13 | OauthClientDetails findOauthClientDetails(String clientId); 14 | 15 | List findAllOauthClientDetails(String clientId); 16 | 17 | int updateOauthClientDetailsArchive(String clientId, boolean archive); 18 | 19 | void saveOauthClientDetails(OauthClientDetails clientDetails); 20 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/security/OIDCUserDetails.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.security; 2 | 3 | 4 | import myoidc.server.domain.user.Privilege; 5 | import myoidc.server.domain.user.User; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.Collection; 13 | import java.util.List; 14 | 15 | /** 16 | * @author Shengzhao Li 17 | */ 18 | public class OIDCUserDetails implements UserDetails { 19 | 20 | 21 | protected static final String ROLE_PREFIX = "ROLE_"; 22 | private static final long serialVersionUID = 5161957098952238466L; 23 | 24 | protected User user; 25 | 26 | protected List authorities = new ArrayList<>(); 27 | 28 | public OIDCUserDetails() { 29 | } 30 | 31 | public OIDCUserDetails(User user) { 32 | this.user = user; 33 | initialPrivileges(); 34 | } 35 | 36 | private void initialPrivileges() { 37 | List privilegeList = privilegeList(); 38 | for (Privilege privilege : privilegeList) { 39 | this.authorities.add(new SimpleGrantedAuthority(ROLE_PREFIX + privilege.name())); 40 | } 41 | } 42 | 43 | private List privilegeList() { 44 | //defaultUser 有所有权限 45 | if (user.defaultUser()) { 46 | return Arrays.asList(Privilege.values()); 47 | } else { 48 | //固定值 49 | final List privileges = user.privileges(); 50 | privileges.add(Privilege.USER); 51 | return privileges; 52 | } 53 | } 54 | 55 | @Override 56 | public Collection getAuthorities() { 57 | return authorities; 58 | } 59 | 60 | @Override 61 | public String getPassword() { 62 | return user.password(); 63 | } 64 | 65 | @Override 66 | public String getUsername() { 67 | return user.username(); 68 | } 69 | 70 | @Override 71 | public boolean isAccountNonExpired() { 72 | return true; 73 | } 74 | 75 | @Override 76 | public boolean isAccountNonLocked() { 77 | return true; 78 | } 79 | 80 | @Override 81 | public boolean isCredentialsNonExpired() { 82 | return true; 83 | } 84 | 85 | @Override 86 | public boolean isEnabled() { 87 | return true; 88 | } 89 | 90 | public User user() { 91 | return user; 92 | } 93 | 94 | 95 | @Override 96 | public String toString() { 97 | return "{" + 98 | "user=" + user + 99 | ", authorities=" + authorities + 100 | '}'; 101 | } 102 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/security/SecurityHolder.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.security; 2 | 3 | /** 4 | * @author Shengzhao Li 5 | */ 6 | 7 | public interface SecurityHolder { 8 | 9 | OIDCUserDetails userDetails(); 10 | 11 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/security/SecurityUtils.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.security; 2 | 3 | 4 | import myoidc.server.domain.user.User; 5 | 6 | /** 7 | * @author Shengzhao Li 8 | */ 9 | public class SecurityUtils { 10 | 11 | private static SecurityHolder securityHolder; 12 | 13 | public void setSecurityHolder(SecurityHolder securityHolder) { 14 | SecurityUtils.securityHolder = securityHolder; 15 | } 16 | 17 | 18 | /** 19 | * 当前登录用户 20 | * 21 | * @return Current user 22 | * @since 1.1.0 23 | */ 24 | public static User currentUser() { 25 | OIDCUserDetails userDetails = securityHolder.userDetails(); 26 | return userDetails != null ? userDetails.user() : null; 27 | } 28 | 29 | 30 | /** 31 | * 当前登录用户名 32 | * 33 | * @return Current username 34 | * @since 1.1.0 35 | */ 36 | public static String currentUsername() { 37 | final User user = currentUser(); 38 | return user != null ? user.username() : "unknown"; 39 | } 40 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/shared/Application.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.shared; 2 | 3 | 4 | import myoidc.server.Constants; 5 | import org.springframework.beans.factory.InitializingBean; 6 | import org.springframework.util.Assert; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | public class Application implements InitializingBean, Constants { 12 | 13 | 14 | //application host 15 | private static String host; 16 | 17 | 18 | /* 19 | * default 20 | * */ 21 | public Application() { 22 | } 23 | 24 | 25 | public static String host() { 26 | return host; 27 | } 28 | 29 | public void setHost(String host) { 30 | Application.host = host.endsWith("/") ? host : host + "/"; 31 | } 32 | 33 | 34 | @Override 35 | public void afterPropertiesSet() throws Exception { 36 | Assert.notNull(host, "host is null"); 37 | } 38 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/shared/BeanProvider.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.shared; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | /** 6 | * @author Shengzhao Li 7 | */ 8 | public abstract class BeanProvider { 9 | 10 | private static ApplicationContext applicationContext; 11 | 12 | protected BeanProvider() { 13 | } 14 | 15 | public static void initialize(ApplicationContext applicationContext) { 16 | BeanProvider.applicationContext = applicationContext; 17 | } 18 | 19 | /** 20 | * Get Bean by clazz. 21 | * 22 | * @param clazz Class 23 | * @param class type 24 | * @return Bean instance 25 | */ 26 | public static T getBean(Class clazz) { 27 | if (applicationContext == null) { 28 | return null; 29 | } 30 | return applicationContext.getBean(clazz); 31 | } 32 | 33 | @SuppressWarnings("unchecked") 34 | public static T getBean(String beanId) { 35 | if (applicationContext == null) { 36 | return null; 37 | } 38 | return (T) applicationContext.getBean(beanId); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/shared/Repository.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.shared; 2 | 3 | 4 | import myoidc.server.domain.AbstractDomain; 5 | 6 | import java.util.Collection; 7 | import java.util.List; 8 | 9 | /** 10 | * @author Shengzhao Li 11 | */ 12 | 13 | public interface Repository { 14 | 15 | T findById(Integer id, Class clazz); 16 | 17 | T findByUuid(Class clazz, String uuid); 18 | 19 | void saveOrUpdate(T domain); 20 | 21 | void saveOrUpdateAll(Collection collection); 22 | 23 | void delete(T domain); 24 | 25 | void deleteByUuid(Class clazz, String uuid); 26 | 27 | void deleteAll(Collection elements); 28 | 29 | List findAll(Class clazz, boolean active); 30 | 31 | List findByUuids(Class clazz, List uuids); 32 | 33 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/shared/UUIDGenerator.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.shared; 2 | 3 | 4 | import org.apache.commons.lang3.RandomStringUtils; 5 | 6 | /** 7 | * @author Shengzhao Li 8 | */ 9 | public abstract class UUIDGenerator { 10 | 11 | 12 | protected UUIDGenerator() { 13 | } 14 | 15 | 16 | public static String generate() { 17 | return RandomStringUtils.random(42, true, true); 18 | } 19 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/user/Privilege.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.user; 2 | 3 | 4 | /** 5 | * @author Shengzhao Li 6 | */ 7 | 8 | public enum Privilege { 9 | 10 | //Any user have the default privilege 11 | USER("User"), 12 | 13 | ADMIN("Admin"), //管理 权限 14 | 15 | CLIENT("Client"), //注册 client 16 | UNITY("Unity"), //资源 权限 17 | MOBILE("Mobile"); //资源 权限 18 | 19 | 20 | private String label; 21 | 22 | 23 | Privilege(String label) { 24 | this.label = label; 25 | } 26 | 27 | public String getLabel() { 28 | return label; 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/user/UserPrivilege.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.user; 2 | 3 | 4 | 5 | import myoidc.server.domain.AbstractDomain; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * @author Shengzhao Li 11 | */ 12 | @Entity 13 | @Table(name = "user_privilege") 14 | public class UserPrivilege extends AbstractDomain { 15 | 16 | private static final long serialVersionUID = -7207158121413995079L; 17 | @ManyToOne 18 | @JoinColumn(name = "user_id") 19 | private User user; 20 | 21 | @Column(name = "privilege") 22 | @Enumerated(value = EnumType.STRING) 23 | private Privilege privilege; 24 | 25 | public UserPrivilege() { 26 | } 27 | 28 | public UserPrivilege(User user, Privilege privilege) { 29 | this.user = user; 30 | this.privilege = privilege; 31 | } 32 | 33 | public Privilege privilege() { 34 | return privilege; 35 | } 36 | 37 | public User user() { 38 | return user; 39 | } 40 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/domain/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.user; 2 | 3 | 4 | import myoidc.server.domain.shared.Repository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | 12 | public interface UserRepository extends Repository { 13 | 14 | 15 | User findLoginUserByUsername(String username); 16 | 17 | List findUserPrivileges(String userUuid); 18 | 19 | List findUsersByUsername(String username); 20 | 21 | /** 22 | * 无 archived 条件 23 | * 24 | * @param username username 25 | * @return User 26 | * @since 1.1.1 27 | */ 28 | User findUserByUsernameNoArchived(String username); 29 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/PasswordHandler.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | import myoidc.server.domain.shared.BeanProvider; 4 | import org.apache.commons.lang3.RandomStringUtils; 5 | import org.springframework.security.crypto.password.PasswordEncoder; 6 | import org.springframework.util.Assert; 7 | 8 | /** 9 | * 2016/3/25 10 | *

11 | * From spring-oauth-server 12 | * 13 | * @author Shengzhao Li 14 | */ 15 | public abstract class PasswordHandler { 16 | 17 | 18 | // private PasswordEncoder passwordEncoder = SOSContextHolder.getBean(PasswordEncoder.class); 19 | 20 | 21 | private PasswordHandler() { 22 | } 23 | 24 | 25 | public static String encode(String password) { 26 | PasswordEncoder passwordEncoder = BeanProvider.getBean(PasswordEncoder.class); 27 | Assert.notNull(passwordEncoder, "passwordEncoder is null"); 28 | // BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 29 | return passwordEncoder.encode(password); 30 | } 31 | 32 | 33 | /** 34 | * 生成新的随机密码, 长度: 12 35 | * 36 | * @return Random password 37 | * @since 1.1.0 38 | */ 39 | public static String randomPassword() { 40 | return RandomStringUtils.random(12, true, true); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/README.txt: -------------------------------------------------------------------------------- 1 | 2 | All DAO, Data, Utils in Here -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | 4 | import org.apache.commons.lang3.RandomStringUtils; 5 | 6 | /** 7 | * 2016/12/25 8 | * 9 | * @author Shengzhao Li 10 | */ 11 | public abstract class RandomUtils { 12 | 13 | 14 | public static String randomText() { 15 | return RandomStringUtils.random(32, true, true); 16 | } 17 | 18 | 19 | private RandomUtils() { 20 | } 21 | 22 | //全数字的随机值 23 | public static String randomNumber() { 24 | return RandomStringUtils.random(32, false, true); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/jdbc/OauthClientDetailsRowMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package myoidc.server.infrastructure.jdbc; 13 | 14 | 15 | import myoidc.server.domain.oauth.OauthClientDetails; 16 | import org.springframework.jdbc.core.RowMapper; 17 | 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | 21 | /** 22 | * 2015/11/16 23 | *

24 | * from spring-oauth-server 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class OauthClientDetailsRowMapper implements RowMapper { 29 | 30 | 31 | public OauthClientDetailsRowMapper() { 32 | } 33 | 34 | @Override 35 | public OauthClientDetails mapRow(ResultSet rs, int i) throws SQLException { 36 | OauthClientDetails clientDetails = new OauthClientDetails(); 37 | 38 | clientDetails.clientId(rs.getString("client_id")); 39 | clientDetails.resourceIds(rs.getString("resource_ids")); 40 | clientDetails.clientSecret(rs.getString("client_secret")); 41 | 42 | clientDetails.scope(rs.getString("scope")); 43 | clientDetails.authorizedGrantTypes(rs.getString("authorized_grant_types")); 44 | clientDetails.webServerRedirectUri(rs.getString("web_server_redirect_uri")); 45 | 46 | clientDetails.authorities(rs.getString("authorities")); 47 | clientDetails.accessTokenValidity(getInteger(rs, "access_token_validity")); 48 | clientDetails.refreshTokenValidity(getInteger(rs, "refresh_token_validity")); 49 | 50 | clientDetails.additionalInformation(rs.getString("additional_information")); 51 | clientDetails.createTime(rs.getTimestamp("create_time").toLocalDateTime()); 52 | clientDetails.archived(rs.getBoolean("archived")); 53 | 54 | clientDetails.trusted(rs.getBoolean("trusted")); 55 | clientDetails.autoApprove(rs.getString("autoapprove")); 56 | 57 | return clientDetails; 58 | } 59 | 60 | 61 | private Integer getInteger(ResultSet rs, String columnName) throws SQLException { 62 | final Object object = rs.getObject(columnName); 63 | if (object != null) { 64 | return (Integer) object; 65 | } 66 | return null; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/jpa/UserRepositoryHibernate.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.jpa; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import myoidc.server.domain.user.Privilege; 5 | import myoidc.server.domain.user.User; 6 | import myoidc.server.domain.user.UserRepository; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import javax.persistence.Query; 11 | import java.util.List; 12 | 13 | /** 14 | * 2018/3/22 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | @Repository() 19 | public class UserRepositoryHibernate extends AbstractRepositoryHibernate implements UserRepository { 20 | 21 | 22 | @Override 23 | public User findLoginUserByUsername(String username) { 24 | final String hql = "from User u where u.username = :username and u.archived = false"; 25 | final List list = find(hql, ImmutableMap.of("username", username)); 26 | return list.isEmpty() ? null : list.get(0); 27 | } 28 | 29 | @Override 30 | @SuppressWarnings("unchecked") 31 | public List findUserPrivileges(String userUuid) { 32 | final String hql = " select up.privilege from UserPrivilege up where up.archived = false and up.user.uuid = :userUuid"; 33 | final Query query = session().createQuery(hql).setParameter("userUuid", userUuid); 34 | return query.getResultList(); 35 | } 36 | 37 | @Override 38 | public List findUsersByUsername(String username) { 39 | if (StringUtils.isNoneBlank(username)) { 40 | final String hql = "from User u where u.username like :username and u.archived = false order by u.id desc "; 41 | // 右半 %, 使用索引 42 | return find(hql, ImmutableMap.of("username", username + "%")); 43 | } else { 44 | return find("from User u where u.archived = false order by u.id desc "); 45 | } 46 | } 47 | 48 | @Override 49 | public User findUserByUsernameNoArchived(String username) { 50 | final String hql = "from User u where u.username = :username "; 51 | final List list = find(hql, ImmutableMap.of("username", username)); 52 | return list.isEmpty() ? null : list.get(0); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/oidc/MyOIDCAccessTokenConverter.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.oidc; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 6 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 7 | import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * 2020/3/11 13 | *

14 | * Ext. default 15 | * 16 | * @author Shengzhao Li 17 | * @since 1.1.0 18 | */ 19 | public class MyOIDCAccessTokenConverter extends DefaultAccessTokenConverter { 20 | 21 | 22 | private static final Logger LOG = LoggerFactory.getLogger(MyOIDCAccessTokenConverter.class); 23 | 24 | 25 | public MyOIDCAccessTokenConverter() { 26 | } 27 | 28 | @Override 29 | public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { 30 | return super.convertAccessToken(token, authentication); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/oidc/MyOIDCUserAuthenticationConverter.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.oidc; 2 | 3 | import myoidc.server.domain.security.OIDCUserDetails; 4 | import myoidc.server.domain.shared.Application; 5 | import org.jose4j.jwt.ReservedClaimNames; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * 2020/3/11 16 | *

17 | * Ext. default 18 | * 19 | * @author Shengzhao Li 20 | * @since 1.1.0 21 | */ 22 | public class MyOIDCUserAuthenticationConverter extends DefaultUserAuthenticationConverter { 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(MyOIDCUserAuthenticationConverter.class); 25 | 26 | public MyOIDCUserAuthenticationConverter() { 27 | } 28 | 29 | @Override 30 | public Map convertUserAuthentication(Authentication authentication) { 31 | Map myOIDCMap = new HashMap<>(); 32 | Map oldMap = super.convertUserAuthentication(authentication); 33 | myOIDCMap.putAll(oldMap); 34 | 35 | //按协议规范增加 required 属性 36 | // https://openid.net/specs/openid-connect-core-1_0.html#IDToken 37 | myOIDCMap.put(ReservedClaimNames.ISSUER, Application.host()); 38 | myOIDCMap.put(ReservedClaimNames.ISSUED_AT, System.currentTimeMillis() / 1000); 39 | 40 | Object details = authentication.getDetails(); 41 | if (details instanceof OIDCUserDetails) { 42 | OIDCUserDetails userDetails = (OIDCUserDetails) details; 43 | myOIDCMap.put(ReservedClaimNames.SUBJECT, userDetails.user().uuid()); 44 | } else { 45 | myOIDCMap.put(ReservedClaimNames.SUBJECT, myOIDCMap.get(USERNAME)); 46 | } 47 | return myOIDCMap; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/infrastructure/oidc/OIDCUseScene.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.oidc; 2 | 3 | /** 4 | * 2020/3/31 5 | *

6 | * OIDC具体的使用场景 7 | * 8 | * @author Shengzhao Li 9 | * @since 1.1.0 10 | */ 11 | public enum OIDCUseScene { 12 | 13 | WEB(OIDCUtils.GrantType.AUTHORIZATION_CODE, OIDCUtils.GrantType.REFRESH_TOKEN), //浏览器 14 | CELL_PHONE(OIDCUtils.GrantType.PASSWORD, OIDCUtils.GrantType.REFRESH_TOKEN), //移动设备(手机) 15 | DEVICE_CLIENT(OIDCUtils.GrantType.PASSWORD, OIDCUtils.GrantType.REFRESH_TOKEN), // 其他设备 16 | SERVER(OIDCUtils.GrantType.CLIENT_CREDENTIALS); //服务端 17 | 18 | 19 | /** 20 | * 每种场景对应的 grant_types 21 | */ 22 | private OIDCUtils.GrantType[] grantTypes; 23 | 24 | OIDCUseScene(OIDCUtils.GrantType... grantTypes) { 25 | this.grantTypes = grantTypes; 26 | } 27 | 28 | 29 | public OIDCUtils.GrantType[] grantTypes() { 30 | return this.grantTypes; 31 | } 32 | 33 | public boolean isServer() { 34 | return SERVER.equals(this); 35 | } 36 | 37 | public boolean isDeviceClient() { 38 | return DEVICE_CLIENT.equals(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/OauthService.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service; 2 | 3 | 4 | import myoidc.server.domain.oauth.OauthClientDetails; 5 | import myoidc.server.service.dto.OauthClientDetailsDto; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Shengzhao Li 11 | */ 12 | 13 | public interface OauthService { 14 | 15 | OauthClientDetails loadOauthClientDetails(String clientId); 16 | 17 | void archiveOauthClientDetails(String clientId); 18 | 19 | List loadOauthClientDetailsDtos(String clientId); 20 | 21 | String saveOAuthClientDetails(OauthClientDetailsDto formDto); 22 | 23 | OauthClientDetailsDto loadOauthClientDetailsDto(String clientId); 24 | 25 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/README.txt: -------------------------------------------------------------------------------- 1 | 2 | All Service,Business in Here -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/SecurityService.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service; 2 | 3 | import myoidc.server.service.dto.ClientRegistrationFormDto; 4 | import myoidc.server.service.dto.OauthClientDetailsDto; 5 | import myoidc.server.service.dto.UserJsonDto; 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | 8 | /** 9 | * 2018/2/5 10 | * 11 | * @author Shengzhao Li 12 | */ 13 | public interface SecurityService extends UserDetailsService { 14 | 15 | UserJsonDto loadCurrentUserJsonDto(); 16 | 17 | OauthClientDetailsDto saveClientRegistrationForm(ClientRegistrationFormDto formDto); 18 | } 19 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/UserService.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service; 2 | 3 | import myoidc.server.service.dto.UserFormDto; 4 | import myoidc.server.service.dto.UserListDto; 5 | 6 | /** 7 | * 2020/3/18 8 | * 9 | * @author Shengzhao Li 10 | * @since 1.1.0 11 | */ 12 | public interface UserService { 13 | 14 | 15 | UserListDto loadUserListDto(UserListDto listDto); 16 | 17 | boolean isExistedUsername(String username); 18 | 19 | String saveUserForm(UserFormDto formDto); 20 | 21 | boolean archiveUserByUuid(String uuid); 22 | } 23 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/business/ClientRegistrationFormSaver.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.business; 2 | 3 | import myoidc.server.Constants; 4 | import myoidc.server.domain.oauth.OauthClientDetails; 5 | import myoidc.server.domain.oauth.OauthRepository; 6 | import myoidc.server.domain.shared.BeanProvider; 7 | import myoidc.server.domain.user.Privilege; 8 | import myoidc.server.infrastructure.PasswordHandler; 9 | import myoidc.server.infrastructure.oidc.OIDCUseScene; 10 | import myoidc.server.infrastructure.oidc.OIDCUtils; 11 | import myoidc.server.service.dto.ClientRegistrationFormDto; 12 | import myoidc.server.service.dto.OauthClientDetailsDto; 13 | import myoidc.server.web.WebUtils; 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.jose4j.jwt.JwtClaims; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | /** 20 | * 2020/4/1 21 | * 22 | * @author Shengzhao Li 23 | * @since 1.1.0 24 | */ 25 | public class ClientRegistrationFormSaver { 26 | 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(ClientRegistrationFormSaver.class); 29 | 30 | private OauthRepository oauthRepository = BeanProvider.getBean(OauthRepository.class); 31 | 32 | 33 | private ClientRegistrationFormDto formDto; 34 | 35 | public ClientRegistrationFormSaver(ClientRegistrationFormDto formDto) { 36 | this.formDto = formDto; 37 | } 38 | 39 | 40 | public OauthClientDetailsDto save() { 41 | 42 | OauthClientDetails clientDetails = createDomain(); 43 | String clientSecret = OIDCUtils.generateClientSecret(); 44 | // encrypted client secret 45 | clientDetails.clientSecret(PasswordHandler.encode(clientSecret)); 46 | 47 | oauthRepository.saveOauthClientDetails(clientDetails); 48 | LOG.debug("{}|Register OauthClientDetails: {}", WebUtils.getIp(), clientDetails); 49 | 50 | OauthClientDetails oauthClientDetails = oauthRepository.findOauthClientDetails(clientDetails.clientId()); 51 | OauthClientDetailsDto detailsDto = new OauthClientDetailsDto(oauthClientDetails); 52 | detailsDto.setClientSecret(clientSecret); 53 | return detailsDto; 54 | } 55 | 56 | 57 | OauthClientDetails createDomain() { 58 | OIDCUseScene useScene = formDto.getUseScene(); 59 | OauthClientDetails clientDetails = new OauthClientDetails() 60 | .clientId(OIDCUtils.generateClientId()) 61 | .resourceIds(Constants.RESOURCE_ID) 62 | .authorizedGrantTypes(StringUtils.join(useScene.grantTypes(), ",")); 63 | 64 | 65 | //判断scope 66 | if (useScene.isServer()) { 67 | clientDetails.scope(OIDCUtils.SCOPE_READ); 68 | } else { 69 | clientDetails.scope(OIDCUtils.SCOPE_OPENID); 70 | } 71 | clientDetails.webServerRedirectUri(formDto.getWebServerRedirectUri()); 72 | 73 | //权限默认 CLIENT 74 | clientDetails.authorities(Privilege.CLIENT.name()); 75 | 76 | //固定值 77 | clientDetails.accessTokenValidity(OIDCUtils.ACCESS_TOKEN_VALIDITY) 78 | .refreshTokenValidity(OIDCUtils.REFRESH_TOKEN_VALIDITY) 79 | .trusted(false); 80 | 81 | JwtClaims claims = new JwtClaims(); 82 | claims.setStringClaim("appName", formDto.getAppName()); 83 | clientDetails.additionalInformation(claims.toJson()); 84 | 85 | return clientDetails; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/business/OAuthClientDetailsSaver.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.business; 2 | 3 | import myoidc.server.domain.oauth.OauthClientDetails; 4 | import myoidc.server.domain.oauth.OauthRepository; 5 | import myoidc.server.domain.shared.BeanProvider; 6 | import myoidc.server.service.dto.OauthClientDetailsDto; 7 | import myoidc.server.web.WebUtils; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | /** 12 | * 2020/3/21 13 | * 14 | * @author Shengzhao Li 15 | * @since 1.1.0 16 | */ 17 | public class OAuthClientDetailsSaver { 18 | 19 | 20 | private static final Logger LOG = LoggerFactory.getLogger(OAuthClientDetailsSaver.class); 21 | 22 | private OauthRepository oauthRepository = BeanProvider.getBean(OauthRepository.class); 23 | 24 | private OauthClientDetailsDto formDto; 25 | 26 | public OAuthClientDetailsSaver(OauthClientDetailsDto formDto) { 27 | this.formDto = formDto; 28 | } 29 | 30 | public String save() { 31 | OauthClientDetails clientDetails = formDto.createDomain(); 32 | oauthRepository.saveOauthClientDetails(clientDetails); 33 | LOG.debug("{}|Save OauthClientDetails: {}", WebUtils.getIp(), clientDetails); 34 | return clientDetails.clientId(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/business/UserFormSaver.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.business; 2 | 3 | import myoidc.server.domain.security.SecurityUtils; 4 | import myoidc.server.domain.shared.BeanProvider; 5 | import myoidc.server.domain.user.Privilege; 6 | import myoidc.server.domain.user.User; 7 | import myoidc.server.domain.user.UserPrivilege; 8 | import myoidc.server.domain.user.UserRepository; 9 | import myoidc.server.service.dto.UserFormDto; 10 | import myoidc.server.web.WebUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * 2020/3/19 18 | * 19 | * @author Shengzhao Li 20 | * @since 1.1.0 21 | */ 22 | public class UserFormSaver { 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(UserFormSaver.class); 25 | 26 | 27 | private UserRepository userRepository = BeanProvider.getBean(UserRepository.class); 28 | 29 | // private PasswordEncoder passwordEncoder = BeanProvider.getBean(PasswordEncoder.class); 30 | 31 | 32 | private UserFormDto formDto; 33 | 34 | public UserFormSaver(UserFormDto formDto) { 35 | this.formDto = formDto; 36 | } 37 | 38 | public String save() { 39 | 40 | User user = formDto.newUser(); 41 | user.creator(SecurityUtils.currentUser()); 42 | // user.password(passwordEncoder.encode(formDto.getPassword())); 43 | userRepository.saveOrUpdate(user); 44 | 45 | List privileges = formDto.getPrivileges(); 46 | for (Privilege privilege : privileges) { 47 | UserPrivilege userPrivilege = new UserPrivilege(user, privilege); 48 | userRepository.saveOrUpdate(userPrivilege); 49 | } 50 | 51 | LOG.debug("{}|Save User: {}", WebUtils.getIp(), user); 52 | return user.uuid(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/dto/ClientRegistrationFormDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.dto; 2 | 3 | import myoidc.server.infrastructure.oidc.OIDCUseScene; 4 | import org.hibernate.validator.constraints.URL; 5 | 6 | import javax.validation.constraints.NotBlank; 7 | import javax.validation.constraints.NotNull; 8 | import javax.validation.constraints.Size; 9 | import java.io.Serializable; 10 | 11 | /** 12 | * 2020/4/1 13 | *

14 | *

15 | * 客户端 注册 DTO 16 | * 17 | * @author Shengzhao Li 18 | * @since 1.1.0 19 | */ 20 | public class ClientRegistrationFormDto implements Serializable { 21 | private static final long serialVersionUID = -6634612576542523523L; 22 | 23 | 24 | //应用名称 25 | @NotBlank(message = "应用名称不能为空") 26 | @Size(min = 1, max = 20, message = "应用名称最多20字符") 27 | private String appName; 28 | 29 | 30 | @NotBlank(message = "redirect_uri不能为空") 31 | @URL(message = "redirect_uri格式错误") 32 | private String webServerRedirectUri; 33 | 34 | 35 | //场景 36 | @NotNull(message = "useScene is required") 37 | private OIDCUseScene useScene; 38 | 39 | 40 | public ClientRegistrationFormDto() { 41 | } 42 | 43 | public ClientRegistrationFormDto(OIDCUseScene useScene) { 44 | this.useScene = useScene; 45 | } 46 | 47 | 48 | public String getAppName() { 49 | return appName; 50 | } 51 | 52 | public void setAppName(String appName) { 53 | this.appName = appName; 54 | } 55 | 56 | public String getWebServerRedirectUri() { 57 | return webServerRedirectUri; 58 | } 59 | 60 | public void setWebServerRedirectUri(String webServerRedirectUri) { 61 | this.webServerRedirectUri = webServerRedirectUri; 62 | } 63 | 64 | public OIDCUseScene getUseScene() { 65 | return useScene; 66 | } 67 | 68 | public void setUseScene(OIDCUseScene useScene) { 69 | this.useScene = useScene; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/dto/OAuthResourceDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 2018/3/26 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public class OAuthResourceDto implements Serializable { 11 | private static final long serialVersionUID = -7266690020307910479L; 12 | 13 | 14 | private String resourceId; 15 | 16 | private String description; 17 | 18 | 19 | public OAuthResourceDto() { 20 | } 21 | 22 | public OAuthResourceDto(String resourceId, String description) { 23 | this.resourceId = resourceId; 24 | this.description = description; 25 | } 26 | 27 | 28 | public String getResourceId() { 29 | return resourceId; 30 | } 31 | 32 | public void setResourceId(String resourceId) { 33 | this.resourceId = resourceId; 34 | } 35 | 36 | public String getDescription() { 37 | return description; 38 | } 39 | 40 | public void setDescription(String description) { 41 | this.description = description; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/dto/UserFormDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.dto; 2 | 3 | 4 | import myoidc.server.domain.user.Privilege; 5 | import myoidc.server.domain.user.User; 6 | import myoidc.server.infrastructure.PasswordHandler; 7 | import myoidc.server.service.validation.UsernameValidation; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.validation.constraints.Email; 11 | import javax.validation.constraints.NotBlank; 12 | import javax.validation.constraints.Size; 13 | import java.io.Serializable; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * 2016/3/25 19 | *

20 | * From spring-oauth-server 21 | * 22 | * @author Shengzhao Li 23 | * @since 1.1.0 24 | */ 25 | public class UserFormDto implements Serializable { 26 | private static final long serialVersionUID = 7959857016962260738L; 27 | 28 | private String uuid; 29 | 30 | 31 | @UsernameValidation() 32 | private String username; 33 | 34 | 35 | private String phone; 36 | 37 | @Email(message = "邮箱格式不对") 38 | private String email; 39 | 40 | //密码要求至少 10位 41 | @NotBlank(message = "密码不能为空") 42 | @Length(min = 10, message = "密码长度最少10位") 43 | private String password; 44 | 45 | 46 | @Size(min = 1, message = "至少选择一个权限") 47 | private List privileges = new ArrayList<>(); 48 | 49 | 50 | public UserFormDto() { 51 | } 52 | 53 | 54 | public Privilege[] getAllPrivileges() { 55 | return Privilege.values(); 56 | } 57 | 58 | public String getPassword() { 59 | return password; 60 | } 61 | 62 | public void setPassword(String password) { 63 | this.password = password; 64 | } 65 | 66 | public User newUser() { 67 | final User user = new User() 68 | .username(getUsername()) 69 | .phone(getPhone()) 70 | .email(getEmail()) 71 | .password(PasswordHandler.encode(getPassword())); 72 | user.privileges().addAll(getPrivileges()); 73 | return user; 74 | } 75 | 76 | 77 | public String getUuid() { 78 | return uuid; 79 | } 80 | 81 | public void setUuid(String uuid) { 82 | this.uuid = uuid; 83 | } 84 | 85 | public String getUsername() { 86 | return username; 87 | } 88 | 89 | public void setUsername(String username) { 90 | this.username = username; 91 | } 92 | 93 | public String getPhone() { 94 | return phone; 95 | } 96 | 97 | public void setPhone(String phone) { 98 | this.phone = phone; 99 | } 100 | 101 | public String getEmail() { 102 | return email; 103 | } 104 | 105 | public void setEmail(String email) { 106 | this.email = email; 107 | } 108 | 109 | public List getPrivileges() { 110 | return privileges; 111 | } 112 | 113 | public void setPrivileges(List privileges) { 114 | this.privileges = privileges; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/dto/UserJsonDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.dto; 2 | 3 | 4 | import myoidc.server.domain.user.Privilege; 5 | import myoidc.server.domain.user.User; 6 | 7 | import java.io.Serializable; 8 | import java.time.temporal.ChronoField; 9 | import java.time.temporal.TemporalField; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * @author Shengzhao Li 15 | */ 16 | public class UserJsonDto implements Serializable { 17 | 18 | 19 | private static final long serialVersionUID = 2310668385840569887L; 20 | 21 | private String openid; 22 | // private boolean archived; 23 | 24 | private String username; 25 | private String phone; 26 | private String email; 27 | 28 | private long create_time; 29 | 30 | private List privileges = new ArrayList<>(); 31 | 32 | public UserJsonDto() { 33 | } 34 | 35 | public UserJsonDto(User user) { 36 | this.openid = user.uuid(); 37 | // this.archived = user.archived(); 38 | this.username = user.username(); 39 | this.create_time = user.createTime().getLong(ChronoField.MILLI_OF_SECOND); 40 | 41 | this.phone = user.phone(); 42 | this.email = user.email(); 43 | 44 | final List privilegeList = user.privileges(); 45 | for (Privilege privilege : privilegeList) { 46 | this.privileges.add(privilege.name()); 47 | } 48 | } 49 | 50 | 51 | public long getCreate_time() { 52 | return create_time; 53 | } 54 | 55 | public void setCreate_time(long create_time) { 56 | this.create_time = create_time; 57 | } 58 | 59 | public String getOpenid() { 60 | return openid; 61 | } 62 | 63 | public void setOpenid(String openid) { 64 | this.openid = openid; 65 | } 66 | 67 | // public boolean isArchived() { 68 | // return archived; 69 | // } 70 | 71 | // public void setArchived(boolean archived) { 72 | // this.archived = archived; 73 | // } 74 | 75 | 76 | public String getUsername() { 77 | return username; 78 | } 79 | 80 | public void setUsername(String username) { 81 | this.username = username; 82 | } 83 | 84 | public String getPhone() { 85 | return phone; 86 | } 87 | 88 | public void setPhone(String phone) { 89 | this.phone = phone; 90 | } 91 | 92 | public String getEmail() { 93 | return email; 94 | } 95 | 96 | public void setEmail(String email) { 97 | this.email = email; 98 | } 99 | 100 | public List getPrivileges() { 101 | return privileges; 102 | } 103 | 104 | public void setPrivileges(List privileges) { 105 | this.privileges = privileges; 106 | } 107 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/dto/UserListDto.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * 2016/3/12 9 | * 10 | * @author Shengzhao Li 11 | */ 12 | public class UserListDto implements Serializable { 13 | private static final long serialVersionUID = 2023379587030489248L; 14 | 15 | 16 | private String username; 17 | 18 | 19 | private List userDtos = new ArrayList<>(); 20 | 21 | 22 | public UserListDto() { 23 | } 24 | 25 | public int getSize() { 26 | return userDtos.size(); 27 | } 28 | 29 | public String getUsername() { 30 | return username; 31 | } 32 | 33 | public void setUsername(String username) { 34 | this.username = username; 35 | } 36 | 37 | public List getUserDtos() { 38 | return userDtos; 39 | } 40 | 41 | public void setUserDtos(List userDtos) { 42 | this.userDtos = userDtos; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/impl/OauthServiceImpl.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.impl; 2 | 3 | import myoidc.server.domain.oauth.OauthClientDetails; 4 | import myoidc.server.domain.oauth.OauthRepository; 5 | import myoidc.server.service.OauthService; 6 | import myoidc.server.service.business.OAuthClientDetailsSaver; 7 | import myoidc.server.service.dto.OauthClientDetailsDto; 8 | import myoidc.server.web.WebUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * 2018/3/24 19 | *

20 | * from spring-oauth-server 21 | * 22 | * @author Shengzhao Li 23 | */ 24 | @Service("oauthService") 25 | public class OauthServiceImpl implements OauthService { 26 | 27 | private static final Logger LOG = LoggerFactory.getLogger(OauthServiceImpl.class); 28 | 29 | 30 | @Autowired 31 | private OauthRepository oauthRepository; 32 | 33 | 34 | @Transactional(readOnly = true) 35 | @Override 36 | public OauthClientDetails loadOauthClientDetails(String clientId) { 37 | return oauthRepository.findOauthClientDetails(clientId); 38 | } 39 | 40 | 41 | @Transactional() 42 | @Override 43 | public void archiveOauthClientDetails(String clientId) { 44 | int i = oauthRepository.updateOauthClientDetailsArchive(clientId, true); 45 | LOG.debug("{}|Archived client: {}, {}", WebUtils.getIp(), clientId, i); 46 | } 47 | 48 | @Transactional(readOnly = true) 49 | @Override 50 | public List loadOauthClientDetailsDtos(String clientId) { 51 | //暂时不加分页 52 | List clientDetailses = oauthRepository.findAllOauthClientDetails(clientId); 53 | return OauthClientDetailsDto.toDtos(clientDetailses); 54 | } 55 | 56 | @Transactional() 57 | @Override 58 | public String saveOAuthClientDetails(OauthClientDetailsDto formDto) { 59 | OAuthClientDetailsSaver saver = new OAuthClientDetailsSaver(formDto); 60 | return saver.save(); 61 | } 62 | 63 | @Transactional(readOnly = true) 64 | @Override 65 | public OauthClientDetailsDto loadOauthClientDetailsDto(String clientId) { 66 | final OauthClientDetails oauthClientDetails = oauthRepository.findOauthClientDetails(clientId); 67 | return oauthClientDetails != null ? new OauthClientDetailsDto(oauthClientDetails) : null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/impl/SecurityServiceImpl.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.impl; 2 | 3 | import myoidc.server.domain.security.OIDCUserDetails; 4 | import myoidc.server.domain.user.User; 5 | import myoidc.server.domain.user.UserRepository; 6 | import myoidc.server.service.SecurityService; 7 | import myoidc.server.service.business.ClientRegistrationFormSaver; 8 | import myoidc.server.service.dto.ClientRegistrationFormDto; 9 | import myoidc.server.service.dto.OauthClientDetailsDto; 10 | import myoidc.server.service.dto.UserJsonDto; 11 | import myoidc.server.service.oauth.CurrentUserJsonDtoLoader; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.transaction.annotation.Transactional; 19 | 20 | /** 21 | * 2018/2/5 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | @Service() 26 | public class SecurityServiceImpl implements SecurityService { 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(SecurityServiceImpl.class); 29 | 30 | @Autowired 31 | private UserRepository userRepository; 32 | 33 | 34 | @Transactional(readOnly = true) 35 | @Override 36 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 37 | LOG.debug("Try load User by username: {}", username); 38 | User user = userRepository.findLoginUserByUsername(username); 39 | if (user == null) { 40 | throw new UsernameNotFoundException("Not found by username: " + username); 41 | } 42 | return new OIDCUserDetails(user); 43 | } 44 | 45 | 46 | /** 47 | * 获取当前登录用户 的信息 , JSON 48 | */ 49 | @Override 50 | @Transactional(readOnly = true) 51 | public UserJsonDto loadCurrentUserJsonDto() { 52 | CurrentUserJsonDtoLoader loader = new CurrentUserJsonDtoLoader(); 53 | return loader.load(); 54 | } 55 | 56 | @Override 57 | @Transactional() 58 | public OauthClientDetailsDto saveClientRegistrationForm(ClientRegistrationFormDto formDto) { 59 | ClientRegistrationFormSaver formSaver = new ClientRegistrationFormSaver(formDto); 60 | return formSaver.save(); 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.impl; 2 | 3 | import myoidc.server.domain.user.User; 4 | import myoidc.server.domain.user.UserRepository; 5 | import myoidc.server.service.UserService; 6 | import myoidc.server.service.business.UserFormSaver; 7 | import myoidc.server.service.dto.UserDto; 8 | import myoidc.server.service.dto.UserFormDto; 9 | import myoidc.server.service.dto.UserListDto; 10 | import myoidc.server.web.WebUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 2020/3/18 21 | * 22 | * @author Shengzhao Li 23 | * @since 1.1.0 24 | */ 25 | @Service 26 | public class UserServiceImpl implements UserService { 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class); 29 | 30 | 31 | @Autowired 32 | private UserRepository userRepository; 33 | 34 | 35 | @Override 36 | @Transactional(readOnly = true) 37 | public UserListDto loadUserListDto(UserListDto listDto) { 38 | //暂不支持分页 39 | List users = userRepository.findUsersByUsername(listDto.getUsername()); 40 | listDto.setUserDtos(UserDto.toDtos(users)); 41 | return listDto; 42 | } 43 | 44 | @Override 45 | @Transactional(readOnly = true) 46 | public boolean isExistedUsername(String username) { 47 | final User user = userRepository.findUserByUsernameNoArchived(username); 48 | return user != null; 49 | } 50 | 51 | @Override 52 | @Transactional() 53 | public String saveUserForm(UserFormDto formDto) { 54 | UserFormSaver saver = new UserFormSaver(formDto); 55 | return saver.save(); 56 | } 57 | 58 | @Override 59 | @Transactional() 60 | public boolean archiveUserByUuid(String uuid) { 61 | User user = userRepository.findByUuid(User.class, uuid); 62 | if (user == null || user.defaultUser()) { 63 | LOG.debug("{}|Null or defaultUser: {}", WebUtils.getIp(), user); 64 | return false; 65 | } 66 | user.archiveMe(); 67 | return true; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/oauth/CurrentUserJsonDtoLoader.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.oauth; 2 | 3 | import myoidc.server.domain.security.OIDCUserDetails; 4 | import myoidc.server.domain.shared.BeanProvider; 5 | import myoidc.server.domain.user.User; 6 | import myoidc.server.domain.user.UserRepository; 7 | import myoidc.server.service.dto.UserJsonDto; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.security.core.GrantedAuthority; 12 | import org.springframework.security.core.context.SecurityContextHolder; 13 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 14 | 15 | import java.util.Collection; 16 | 17 | /** 18 | * 2020/3/11 19 | * 20 | * @author Shengzhao Li 21 | * @since 1.1.0 22 | */ 23 | public class CurrentUserJsonDtoLoader { 24 | 25 | private static final Logger LOG = LoggerFactory.getLogger(CurrentUserJsonDtoLoader.class); 26 | 27 | 28 | private transient UserRepository userRepository = BeanProvider.getBean(UserRepository.class); 29 | 30 | public CurrentUserJsonDtoLoader() { 31 | } 32 | 33 | public UserJsonDto load() { 34 | final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 35 | final Object principal = authentication.getPrincipal(); 36 | 37 | if (authentication instanceof OAuth2Authentication && 38 | (principal instanceof String || principal instanceof org.springframework.security.core.userdetails.User)) { 39 | return loadOauthUserJsonDto((OAuth2Authentication) authentication); 40 | } else { 41 | final OIDCUserDetails userDetails = (OIDCUserDetails) principal; 42 | return new UserJsonDto(userRepository.findByUuid(User.class, userDetails.user().uuid())); 43 | } 44 | } 45 | 46 | 47 | private UserJsonDto loadOauthUserJsonDto(OAuth2Authentication oAuth2Authentication) { 48 | String name = oAuth2Authentication.getName(); 49 | User user = userRepository.findLoginUserByUsername(name); 50 | UserJsonDto userJsonDto; 51 | if (user != null) { 52 | LOG.debug("Load OAuth user from User: {}", user); 53 | userJsonDto = new UserJsonDto(user); 54 | } else { 55 | userJsonDto = new UserJsonDto(); 56 | userJsonDto.setUsername(name); 57 | 58 | final Collection authorities = oAuth2Authentication.getAuthorities(); 59 | for (GrantedAuthority authority : authorities) { 60 | userJsonDto.getPrivileges().add(authority.getAuthority()); 61 | } 62 | } 63 | return userJsonDto; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/oauth/CustomJdbcClientDetailsService.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.oauth; 2 | 3 | import org.springframework.security.oauth2.common.exceptions.InvalidClientException; 4 | import org.springframework.security.oauth2.provider.ClientDetails; 5 | import org.springframework.security.oauth2.provider.NoSuchClientException; 6 | import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; 7 | 8 | import javax.sql.DataSource; 9 | 10 | 11 | /** 12 | * 扩展 默认的 ClientDetailsService, 增加逻辑删除判断( archived = 0) 13 | * SQL中添加 archived = 0 条件 14 | *

15 | * from spring-oauth-server 16 | * 17 | * @author Shengzhao Li 18 | */ 19 | public class CustomJdbcClientDetailsService extends JdbcClientDetailsService { 20 | 21 | private static final String SELECT_CLIENT_DETAILS_SQL = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, " + 22 | "web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove " + 23 | "from oauth_client_details where client_id = ? and archived = 0 "; 24 | 25 | 26 | public CustomJdbcClientDetailsService(DataSource dataSource) { 27 | super(dataSource); 28 | setSelectClientDetailsSql(SELECT_CLIENT_DETAILS_SQL); 29 | } 30 | 31 | 32 | @Override 33 | // @Cacheable(value = CLIENT_DETAILS_CACHE, key = "#clientId") 34 | public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException { 35 | return super.loadClientByClientId(clientId); 36 | } 37 | 38 | 39 | @Override 40 | // @CacheEvict(value = CLIENT_DETAILS_CACHE, key = "#clientDetails.getClientId()") 41 | public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClientException { 42 | super.updateClientDetails(clientDetails); 43 | } 44 | 45 | @Override 46 | // @CacheEvict(value = CLIENT_DETAILS_CACHE, key = "#clientId") 47 | public void updateClientSecret(String clientId, String secret) throws NoSuchClientException { 48 | super.updateClientSecret(clientId, secret); 49 | } 50 | 51 | @Override 52 | // @CacheEvict(value = CLIENT_DETAILS_CACHE, key = "#clientId") 53 | public void removeClientDetails(String clientId) throws NoSuchClientException { 54 | super.removeClientDetails(clientId); 55 | } 56 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/oauth/CustomJdbcTokenStore.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.oauth; 2 | 3 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 4 | import org.springframework.security.oauth2.common.OAuth2RefreshToken; 5 | import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; 6 | 7 | import javax.sql.DataSource; 8 | 9 | 10 | 11 | /** 12 | * 2016/7/26 13 | *

14 | * 扩展默认的 TokenStore, 增加对缓存的支持 15 | * 16 | * 17 | * from spring-oauth-server 18 | * 19 | * @author Shengzhao Li 20 | */ 21 | public class CustomJdbcTokenStore extends JdbcTokenStore { 22 | 23 | 24 | public CustomJdbcTokenStore(DataSource dataSource) { 25 | super(dataSource); 26 | } 27 | 28 | 29 | // @Cacheable(value = ACCESS_TOKEN_CACHE, key = "#tokenValue") 30 | public OAuth2AccessToken readAccessToken(String tokenValue) { 31 | return super.readAccessToken(tokenValue); 32 | } 33 | 34 | // @CacheEvict(value = ACCESS_TOKEN_CACHE, key = "#token.value") 35 | @Override 36 | public void removeAccessToken(OAuth2AccessToken token) { 37 | super.removeAccessToken(token); 38 | } 39 | 40 | // @Cacheable(value = REFRESH_TOKEN_CACHE, key = "#token") 41 | public OAuth2RefreshToken readRefreshToken(String token) { 42 | return super.readRefreshToken(token); 43 | } 44 | 45 | // @CacheEvict(value = REFRESH_TOKEN_CACHE, key = "#token.value") 46 | @Override 47 | public void removeRefreshToken(OAuth2RefreshToken token) { 48 | super.removeRefreshToken(token); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/oauth/OauthUserApprovalHandler.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.oauth; 2 | 3 | 4 | import myoidc.server.domain.oauth.OauthClientDetails; 5 | import myoidc.server.service.OauthService; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.oauth2.provider.AuthorizationRequest; 8 | import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler; 9 | 10 | /** 11 | * 处理OAuth 中用户授权确认的逻辑 12 | * 这在grant_type 为 authorization_code, implicit 会使用到 13 | *

14 | * from spring-oauth-server 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | public class OauthUserApprovalHandler extends TokenStoreUserApprovalHandler { 19 | 20 | private OauthService oauthService; 21 | 22 | public OauthUserApprovalHandler() { 23 | // Do nothing 24 | } 25 | 26 | 27 | /** 28 | * 这儿扩展了默认的逻辑, 若 OauthClientDetails 中的 trusted 字段为true, 将会自动跳过 授权流程 29 | * 30 | * @param authorizationRequest AuthorizationRequest 31 | * @param userAuthentication Authentication 32 | * @return True is approved 33 | */ 34 | public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { 35 | if (super.isApproved(authorizationRequest, userAuthentication)) { 36 | return true; 37 | } 38 | if (!userAuthentication.isAuthenticated()) { 39 | return false; 40 | } 41 | 42 | OauthClientDetails clientDetails = oauthService.loadOauthClientDetails(authorizationRequest.getClientId()); 43 | return clientDetails != null && clientDetails.trusted(); 44 | 45 | } 46 | 47 | public void setOauthService(OauthService oauthService) { 48 | this.oauthService = oauthService; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/oauth/SOSAuthorizationCodeServices.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.oauth; 2 | 3 | import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; 4 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 5 | import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; 6 | 7 | import javax.sql.DataSource; 8 | 9 | 10 | /** 11 | * 2016/7/23 12 | *

13 | * from spring-oauth-server 14 | * 15 | * @author Shengzhao Li 16 | */ 17 | public class SOSAuthorizationCodeServices extends JdbcAuthorizationCodeServices { 18 | 19 | 20 | // 扩展长度 18 21 | private RandomValueStringGenerator generator = new RandomValueStringGenerator(18); 22 | 23 | 24 | public SOSAuthorizationCodeServices(DataSource dataSource) { 25 | super(dataSource); 26 | } 27 | 28 | 29 | public String createAuthorizationCode(OAuth2Authentication authentication) { 30 | String code = generator.generate(); 31 | store(code, authentication); 32 | return code; 33 | } 34 | 35 | @Override 36 | // @Cacheable(value = AUTHORIZATION_CODE_CACHE, key = "#code") 37 | protected void store(String code, OAuth2Authentication authentication) { 38 | super.store(code, authentication); 39 | } 40 | 41 | @Override 42 | // @CacheEvict(value = AUTHORIZATION_CODE_CACHE, key = "#code") 43 | public OAuth2Authentication remove(String code) { 44 | return super.remove(code); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/validation/ClientIdValidation.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.validation; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * 2020/3/21 9 | * 10 | * @author Shengzhao Li 11 | * @since 1.1.0 12 | */ 13 | @Documented 14 | @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Constraint(validatedBy = ClientIdValidator.class) 17 | public @interface ClientIdValidation { 18 | 19 | String message() default "client_id不能为空(或已存在)"; 20 | 21 | Class[] groups() default {}; 22 | 23 | Class[] payload() default {}; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/validation/ClientIdValidator.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.validation; 2 | 3 | import myoidc.server.service.OauthService; 4 | import myoidc.server.service.dto.OauthClientDetailsDto; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | 10 | import javax.validation.ConstraintValidator; 11 | import javax.validation.ConstraintValidatorContext; 12 | 13 | /** 14 | * 2020/3/21 15 | * 16 | * @author Shengzhao Li 17 | * @since 1.1.0 18 | */ 19 | public class ClientIdValidator implements ConstraintValidator { 20 | 21 | 22 | private static final Logger LOG = LoggerFactory.getLogger(ClientIdValidator.class); 23 | 24 | @Autowired 25 | private OauthService oauthService; 26 | 27 | @Override 28 | public boolean isValid(String clientId, ConstraintValidatorContext context) { 29 | if (StringUtils.isBlank(clientId)) { 30 | LOG.debug("ClientId is blank"); 31 | return false; 32 | } 33 | 34 | 35 | OauthClientDetailsDto detailsDto = oauthService.loadOauthClientDetailsDto(clientId); 36 | if (detailsDto != null) { 37 | LOG.warn("ClientId: {} existed", clientId); 38 | return false; 39 | } 40 | 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/validation/UsernameValidation.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.validation; 2 | 3 | import javax.validation.Constraint; 4 | import javax.validation.Payload; 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * 2020/3/18 9 | * 10 | * @author Shengzhao Li 11 | * @since 1.1.0 12 | */ 13 | @Documented 14 | @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Constraint(validatedBy = UsernameValidator.class) 17 | public @interface UsernameValidation { 18 | 19 | String message() default "账号已经存在"; 20 | 21 | Class[] groups() default {}; 22 | 23 | Class[] payload() default {}; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/service/validation/UsernameValidator.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.validation; 2 | 3 | import myoidc.server.service.UserService; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import javax.validation.ConstraintValidator; 10 | import javax.validation.ConstraintValidatorContext; 11 | 12 | /** 13 | * 2020/3/18 14 | * 15 | * @author Shengzhao Li 16 | * @since 1.1.0 17 | */ 18 | public class UsernameValidator implements ConstraintValidator { 19 | 20 | 21 | private static final Logger LOG = LoggerFactory.getLogger(UsernameValidator.class); 22 | 23 | @Autowired 24 | private UserService userService; 25 | 26 | @Override 27 | public boolean isValid(String username, ConstraintValidatorContext constraintValidatorContext) { 28 | if (StringUtils.isBlank(username)) { 29 | LOG.debug("Username is blank"); 30 | return false; 31 | } 32 | 33 | boolean existed = userService.isExistedUsername(username); 34 | if (existed) { 35 | LOG.debug("Username: {} existed", username); 36 | return false; 37 | } 38 | 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/README.txt: -------------------------------------------------------------------------------- 1 | 2 | All WEB in Here -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/WebUtils.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web; 2 | 3 | 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | /** 9 | * Web 操作的 封装 工具类 10 | * 11 | * @author Shengzhao Li 12 | */ 13 | public abstract class WebUtils { 14 | 15 | 16 | private static ThreadLocal ipThreadLocal = new ThreadLocal<>(); 17 | 18 | 19 | private WebUtils() { 20 | } 21 | 22 | public static void setIp(String ip) { 23 | ipThreadLocal.set(ip); 24 | } 25 | 26 | public static String getIp() { 27 | return ipThreadLocal.get(); 28 | } 29 | 30 | /** 31 | * Retrieve client ip address 32 | * 获取请求时的 客户端(浏览器) IP地址 33 | * 34 | * @param request HttpServletRequest 35 | * @return IP 36 | */ 37 | public static String retrieveClientIp(HttpServletRequest request) { 38 | String ip = request.getHeader("x-forwarded-for"); 39 | if (isUnAvailableIp(ip)) { 40 | ip = request.getHeader("Proxy-Client-IP"); 41 | } 42 | if (isUnAvailableIp(ip)) { 43 | ip = request.getHeader("WL-Proxy-Client-IP"); 44 | } 45 | if (isUnAvailableIp(ip)) { 46 | ip = request.getRemoteAddr(); 47 | } 48 | return ip; 49 | } 50 | 51 | private static boolean isUnAvailableIp(String ip) { 52 | return StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip); 53 | } 54 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/context/OIDCApplicationContextAware.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.context; 2 | 3 | 4 | import myoidc.server.domain.shared.Application; 5 | import myoidc.server.domain.shared.BeanProvider; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.BeansException; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.ApplicationContext; 11 | import org.springframework.context.ApplicationContextAware; 12 | import org.springframework.stereotype.Component; 13 | 14 | /** 15 | * 2018/03/22 16 | *

17 | * 18 | * @author Shengzhao Li 19 | */ 20 | @Component 21 | public class OIDCApplicationContextAware implements ApplicationContextAware { 22 | 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(OIDCApplicationContextAware.class); 25 | 26 | @Value("${spring.application.name}") 27 | private String applicationName; 28 | 29 | 30 | @Value("${application.host}") 31 | private String applicationHost; 32 | 33 | 34 | public OIDCApplicationContextAware() { 35 | } 36 | 37 | @Override 38 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 39 | BeanProvider.initialize(applicationContext); 40 | 41 | if (LOG.isDebugEnabled()) { 42 | LOG.debug("Initialed BeanProvider from ApplicationContext: {}", applicationContext); 43 | } 44 | LOG.info("{} context initialized, Version: {}, applicationHost: {}\n", this.applicationName, Application.VERSION, this.applicationHost); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/context/OIDCServletContextAware.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.context; 2 | 3 | 4 | import myoidc.server.domain.shared.Application; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.context.ServletContextAware; 9 | 10 | import javax.servlet.ServletContext; 11 | 12 | /** 13 | * 2020/5/7 14 | * 15 | * @author Shengzhao Li 16 | * @since 1.1.1 17 | */ 18 | @Component 19 | public class OIDCServletContextAware implements ServletContextAware { 20 | 21 | private static final Logger LOG = LoggerFactory.getLogger(OIDCServletContextAware.class); 22 | 23 | public OIDCServletContextAware() { 24 | } 25 | 26 | @Override 27 | public void setServletContext(ServletContext servletContext) { 28 | 29 | //主版本号 30 | servletContext.setAttribute("mainVersion", Application.VERSION); 31 | LOG.debug("Initialed: {}, mainVersion: {}", this, Application.VERSION); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/context/SpringSecurityHolder.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.context; 2 | 3 | 4 | import myoidc.server.domain.security.OIDCUserDetails; 5 | import myoidc.server.domain.security.SecurityHolder; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | 9 | /** 10 | * @author Shengzhao Li 11 | */ 12 | public class SpringSecurityHolder implements SecurityHolder { 13 | 14 | @Override 15 | public OIDCUserDetails userDetails() { 16 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 17 | if (authentication == null) { 18 | return null; 19 | } 20 | Object principal = authentication.getPrincipal(); 21 | if (principal instanceof OIDCUserDetails) { 22 | return (OIDCUserDetails) principal; 23 | } 24 | return null; 25 | } 26 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/MyOIDCController.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller; 2 | 3 | import myoidc.server.web.WebUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | 11 | import static myoidc.server.domain.shared.Application.host; 12 | 13 | 14 | /** 15 | * 2018/2/5 16 | * 17 | * @author Shengzhao Li 18 | */ 19 | @Controller 20 | public class MyOIDCController { 21 | 22 | 23 | private static final Logger LOG = LoggerFactory.getLogger(MyOIDCController.class); 24 | 25 | 26 | /** 27 | * 首页 28 | */ 29 | @RequestMapping(value = "/") 30 | public String index(Model model) { 31 | model.addAttribute("host", host()); 32 | return "index"; 33 | } 34 | 35 | 36 | //Go login 37 | @GetMapping(value = {"/login"}) 38 | public String login(Model model) { 39 | LOG.debug("Go to login, IP: {}", WebUtils.getIp()); 40 | model.addAttribute("host", host()); 41 | return "login"; 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/admin/AdminRPController.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.admin; 2 | 3 | import myoidc.server.service.OauthService; 4 | import myoidc.server.service.dto.OauthClientDetailsDto; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.validation.Valid; 12 | import java.util.List; 13 | 14 | import static myoidc.server.domain.shared.Application.host; 15 | 16 | /** 17 | * 2020/3/18 18 | *

19 | * 客户端[RP] 管理 20 | * 21 | * @author Shengzhao Li 22 | * @since 1.1.0 23 | */ 24 | @Controller 25 | @RequestMapping("/admin/rp/") 26 | public class AdminRPController { 27 | 28 | 29 | @Autowired 30 | private OauthService oauthService; 31 | 32 | 33 | // RP 列表 34 | @GetMapping("list") 35 | public String rpList(String clientId, Model model) { 36 | List clientDetailsDtoList = oauthService.loadOauthClientDetailsDtos(clientId); 37 | model.addAttribute("dtoList", clientDetailsDtoList); 38 | model.addAttribute("clientId", clientId); 39 | return "admin/rp_list"; 40 | } 41 | 42 | 43 | /** 44 | * Archive ,逻辑删除 45 | */ 46 | @GetMapping("archive_client/{clientId}") 47 | public String archiveClient(@PathVariable("clientId") String clientId) { 48 | oauthService.archiveOauthClientDetails(clientId); 49 | return "redirect:../list"; 50 | } 51 | 52 | 53 | /** 54 | * 添加客户端 55 | */ 56 | @GetMapping("form/plus") 57 | public String addClient(Model model) { 58 | model.addAttribute("formDto", new OauthClientDetailsDto().initialized()); 59 | return "admin/rp_form"; 60 | } 61 | 62 | 63 | /** 64 | * 添加客户端 65 | */ 66 | @PostMapping("form/plus") 67 | public String submitClient(@ModelAttribute("formDto") @Valid OauthClientDetailsDto formDto, BindingResult result, Model model) { 68 | if (result.hasErrors()) { 69 | return "admin/rp_form"; 70 | } 71 | String clientId = oauthService.saveOAuthClientDetails(formDto); 72 | model.addAttribute("newClientId", clientId); 73 | return "redirect:../list"; 74 | } 75 | 76 | 77 | /** 78 | * Test client 79 | */ 80 | @RequestMapping("test_client/{clientId}") 81 | public String testClient(@PathVariable("clientId") String clientId, Model model) { 82 | OauthClientDetailsDto clientDetailsDto = oauthService.loadOauthClientDetailsDto(clientId); 83 | model.addAttribute("clientDetailsDto", clientDetailsDto); 84 | model.addAttribute("host", host()); 85 | return "admin/rp_client_test"; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/admin/AdminUserController.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.admin; 2 | 3 | import myoidc.server.service.UserService; 4 | import myoidc.server.service.dto.UserFormDto; 5 | import myoidc.server.service.dto.UserListDto; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.ui.Model; 9 | import org.springframework.validation.BindingResult; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import javax.validation.Valid; 13 | 14 | /** 15 | * 2020/3/18 16 | *

17 | * 用户[EU] 管理 18 | * 19 | * @author Shengzhao Li 20 | * @since 1.1.0 21 | */ 22 | @Controller 23 | @RequestMapping("/admin/user/") 24 | public class AdminUserController { 25 | 26 | 27 | @Autowired 28 | private UserService userService; 29 | 30 | 31 | /** 32 | * 用户列表 33 | */ 34 | @GetMapping("list") 35 | public String list(UserListDto listDto, Model model) { 36 | listDto = userService.loadUserListDto(listDto); 37 | model.addAttribute("listDto", listDto); 38 | return "admin/user_list"; 39 | } 40 | 41 | 42 | /** 43 | * 用户表单 44 | */ 45 | @GetMapping(value = "form/plus") 46 | public String showForm(Model model) { 47 | model.addAttribute("formDto", new UserFormDto()); 48 | return "admin/user_form"; 49 | } 50 | 51 | 52 | /** 53 | * 用户表单 54 | */ 55 | @PostMapping(value = "form/plus") 56 | public String submitRegisterClient(@ModelAttribute("formDto") @Valid UserFormDto formDto, BindingResult result, Model model) { 57 | if (result.hasErrors()) { 58 | return "admin/user_form"; 59 | } 60 | String uuid = userService.saveUserForm(formDto); 61 | model.addAttribute("uuid", uuid).addAttribute("alert", "SaveOK"); 62 | return "redirect:../list"; 63 | } 64 | 65 | 66 | /** 67 | * archive 68 | */ 69 | @GetMapping("archive/{uuid}") 70 | public String archive(@PathVariable String uuid, Model model) { 71 | boolean ok = userService.archiveUserByUuid(uuid); 72 | model.addAttribute("alert", ok ? "ArchivedOK" : "ArchivedFailed"); 73 | return "redirect:../list"; 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/endpoint/DiscoveryEndpoint.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.endpoint; 2 | 3 | import myoidc.server.infrastructure.oidc.OIDCUtils; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import static myoidc.server.Constants.ID_TOKEN; 13 | import static myoidc.server.Constants.OIDC_ALG; 14 | import static myoidc.server.domain.shared.Application.host; 15 | import static myoidc.server.infrastructure.oidc.OIDCUtils.SCOPE_OPENID; 16 | import static myoidc.server.infrastructure.oidc.OIDCUtils.SCOPE_READ; 17 | import static myoidc.server.infrastructure.oidc.OIDCUtils.SCOPE_WRITE; 18 | 19 | /** 20 | * 2020/3/11 21 | *

22 | * Discovery API 23 | * https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata 24 | * 25 | * @author Shengzhao Li 26 | * @since 1.1.0 27 | */ 28 | @RestController 29 | public class DiscoveryEndpoint { 30 | 31 | 32 | /** 33 | * https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest 34 | * 35 | * @return view 36 | * @throws Exception Exception 37 | */ 38 | @GetMapping("/.well-known/openid-configuration") 39 | public Map configuration() throws Exception { 40 | Map model = new HashMap<>(); 41 | String host = host(); 42 | model.put("issuer", host); 43 | model.put("authorization_endpoint", OIDCUtils.authorizeEndpoint(host)); 44 | model.put("token_endpoint", OIDCUtils.tokenEndpoint(host)); 45 | model.put("userinfo_endpoint", OIDCUtils.userinfoEndpoint(host)); 46 | 47 | model.put("jwks_uri", OIDCUtils.jwksURI(host)); 48 | model.put("registration_endpoint", OIDCUtils.registrationEndpoint(host)); 49 | 50 | model.put("scopes_supported", Arrays.asList(SCOPE_OPENID, SCOPE_READ, SCOPE_WRITE)); 51 | model.put("grant_types_supported", OIDCUtils.GrantType.types()); 52 | model.put("response_types_supported", Arrays.asList("token", "code", ID_TOKEN)); 53 | //ALG: 54 | model.put("id_token_signing_alg_values_supported", Collections.singletonList(OIDC_ALG)); 55 | // "pairwise", 56 | model.put("subject_types_supported", Arrays.asList("public")); 57 | model.put("claims_supported", Arrays.asList("sub", "aud", "scope", "iss", "exp", "iat", "client_id", "authorities", "user_name")); 58 | return model; 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/endpoint/JWKSEndpoint.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.endpoint; 2 | 3 | import myoidc.server.web.WebUtils; 4 | import org.jose4j.jwk.JsonWebKey; 5 | import org.jose4j.jwk.JsonWebKeySet; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * 2020/3/12 15 | *

16 | * JWKS URL API 17 | * 18 | * @author Shengzhao Li 19 | * @since 1.1.0 20 | */ 21 | @RestController 22 | public class JWKSEndpoint { 23 | 24 | 25 | private static final Logger LOG = LoggerFactory.getLogger(JWKSEndpoint.class); 26 | 27 | @Autowired 28 | private JsonWebKeySet jsonWebKeySet; 29 | 30 | 31 | @GetMapping(value = "/public/jwks", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 32 | public String jwks() throws Exception { 33 | if (LOG.isDebugEnabled()) { 34 | LOG.debug("Call 'jwks' API from IP: {}", WebUtils.getIp()); 35 | } 36 | return jsonWebKeySet.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/endpoint/RegistrationEndpoint.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.endpoint; 2 | 3 | import myoidc.server.domain.shared.Application; 4 | import myoidc.server.infrastructure.oidc.OIDCUseScene; 5 | import myoidc.server.service.OauthService; 6 | import myoidc.server.service.SecurityService; 7 | import myoidc.server.service.dto.ClientRegistrationFormDto; 8 | import myoidc.server.service.dto.OauthClientDetailsDto; 9 | import myoidc.server.web.WebUtils; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.ui.Model; 15 | import org.springframework.validation.BindingResult; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import javax.validation.Valid; 19 | 20 | /** 21 | * 2020/3/11 22 | *

23 | * Registration client API 24 | * 25 | * @author Shengzhao Li 26 | * @since 1.1.0 27 | */ 28 | @Controller 29 | @RequestMapping("/public/") 30 | public class RegistrationEndpoint { 31 | 32 | private static final Logger LOG = LoggerFactory.getLogger(RegistrationEndpoint.class); 33 | 34 | 35 | @Autowired 36 | private SecurityService securityService; 37 | 38 | 39 | // 引导 注册 40 | @GetMapping("registration") 41 | public String preRegistration(Model model) { 42 | LOG.debug("{}|Pre registration, model: {}", WebUtils.getIp(), model); 43 | return "registration_pre"; 44 | } 45 | 46 | 47 | /** 48 | * 开始注册 form 49 | * 50 | * @param useScene 使用场景, 默认为 WEB 51 | * @param model Model 52 | * @return view 53 | */ 54 | @GetMapping("registration_form") 55 | public String registration(@RequestParam("scene") OIDCUseScene useScene, Model model) { 56 | ClientRegistrationFormDto formDto = new ClientRegistrationFormDto(useScene); 57 | model.addAttribute("formDto", formDto); 58 | return "registration_form"; 59 | } 60 | 61 | /** 62 | * 注册客户端提交 63 | */ 64 | @PostMapping("registration_form") 65 | public String submitRegistration(@ModelAttribute("formDto") @Valid ClientRegistrationFormDto formDto, BindingResult result, Model model) { 66 | if (result.hasErrors()) { 67 | return "registration_form"; 68 | } 69 | OauthClientDetailsDto clientDetailsDto = securityService.saveClientRegistrationForm(formDto); 70 | model.addAttribute("clientDetailsDto", clientDetailsDto); 71 | model.addAttribute("host", Application.host()); 72 | return "registration_success"; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/endpoint/UserInfoEndpoint.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.endpoint; 2 | 3 | import myoidc.server.service.SecurityService; 4 | import myoidc.server.service.dto.UserJsonDto; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * 2020/3/11 12 | *

13 | * UserInfo API 14 | *

15 | * https://openid.net/specs/openid-connect-core-1_0.html#UserInfo 16 | * 17 | * @author Shengzhao Li 18 | * @since 1.1.0 19 | */ 20 | @RestController 21 | @RequestMapping("/api/") 22 | public class UserInfoEndpoint { 23 | 24 | 25 | @Autowired 26 | private SecurityService securityService; 27 | 28 | 29 | @GetMapping("userinfo") 30 | public UserJsonDto userinfo() { 31 | return securityService.loadCurrentUserJsonDto(); 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/resource/MobileController.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.resource; 2 | 3 | 4 | import myoidc.server.service.SecurityService; 5 | import myoidc.server.service.dto.OAuthResourceDto; 6 | import myoidc.server.service.dto.UserJsonDto; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import static myoidc.server.Constants.RESOURCE_ID; 14 | 15 | /** 16 | * Mobile Resource API 17 | * 18 | * @author Shengzhao Li 19 | */ 20 | @Controller 21 | @RequestMapping("/m/") 22 | public class MobileController { 23 | 24 | 25 | @Autowired 26 | private SecurityService securityService; 27 | 28 | 29 | @GetMapping("dashboard") 30 | @ResponseBody 31 | public OAuthResourceDto dashboard() { 32 | return new OAuthResourceDto(RESOURCE_ID, "Just mobile-Resource"); 33 | } 34 | 35 | @GetMapping("user_info") 36 | @ResponseBody 37 | public UserJsonDto userInfo() { 38 | return securityService.loadCurrentUserJsonDto(); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/controller/resource/UnityController.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.controller.resource; 2 | 3 | 4 | import myoidc.server.service.SecurityService; 5 | import myoidc.server.service.dto.OAuthResourceDto; 6 | import myoidc.server.service.dto.UserJsonDto; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import static myoidc.server.Constants.RESOURCE_ID; 14 | 15 | /** 16 | * Unity Resource API 17 | * 18 | * @author Shengzhao Li 19 | */ 20 | @Controller 21 | @RequestMapping("/unity/") 22 | public class UnityController { 23 | 24 | 25 | @Autowired 26 | private SecurityService securityService; 27 | 28 | 29 | @GetMapping("dashboard") 30 | @ResponseBody 31 | public OAuthResourceDto dashboard() { 32 | return new OAuthResourceDto(RESOURCE_ID, "Just unity-Resource"); 33 | } 34 | 35 | @GetMapping("user_info") 36 | @ResponseBody 37 | public UserJsonDto userInfo() { 38 | return securityService.loadCurrentUserJsonDto(); 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/java/myoidc/server/web/filter/ExtCharacterEncodingFilter.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.web.filter; 2 | 3 | 4 | import myoidc.server.domain.shared.Application; 5 | import myoidc.server.web.WebUtils; 6 | import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter; 7 | 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | /** 15 | * Wrap the spring CharacterEncodingFilter, add retrieve client ip action 16 | *

17 | *

18 | * 扩展 默认的 CharacterEncodingFilter, 添加对IP 地址的获取 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | public class ExtCharacterEncodingFilter extends OrderedCharacterEncodingFilter { 23 | 24 | 25 | public ExtCharacterEncodingFilter() { 26 | setEncoding(Application.ENCODING); 27 | } 28 | 29 | @Override 30 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 31 | throws ServletException, IOException { 32 | 33 | persistIp(request); 34 | super.doFilterInternal(request, response, filterChain); 35 | 36 | } 37 | 38 | /** 39 | * 将IP地址 放置在 ThreadLocal 中 40 | */ 41 | private void persistIp(HttpServletRequest request) { 42 | final String clientIp = WebUtils.retrieveClientIp(request); 43 | WebUtils.setIp(clientIp); 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # MyOIDC -Server V-1.1.0 2 | # 3 | spring.application.name=MyOIDC[Server] 4 | spring.main.allow-bean-definition-overriding=true 5 | spring.jmx.enabled=false 6 | # 7 | #JDBC 8 | #Connection 9 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 10 | spring.datasource.url=jdbc:mysql://localhost:3306/myoidc_server?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC 11 | spring.datasource.username=andaily 12 | spring.datasource.password=andaily 13 | #Datasource properties 14 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 15 | spring.datasource.hikari.maximum-pool-size=20 16 | spring.datasource.hikari.minimum-idle=2 17 | #JPA 18 | spring.data.jpa.repositories.enabled=false 19 | spring.jpa.open-in-view=false 20 | # 21 | # MVC 22 | spring.mvc.ignore-default-model-on-redirect=false 23 | spring.http.encoding.enabled=true 24 | spring.http.encoding.charset=UTF-8 25 | spring.http.encoding.force=true 26 | # 27 | #THYMELEAF (ThymeleafAutoConfiguration) 28 | # 29 | #spring.thymeleaf.prefix=/WEB-INF/view/ 30 | #spring.thymeleaf.suffix=.html 31 | #spring.thymeleaf.mode=HTML5 32 | spring.thymeleaf.encoding=UTF-8 33 | # ;charset= is added 34 | # set to false for hot refresh 35 | spring.thymeleaf.cache=false 36 | # 37 | # Logging INFO 38 | # 39 | logging.level.root=INFO 40 | #logging.config=classpath:log4j2.xml 41 | #logging.level.org.springframework.transaction.interceptor=TRACE 42 | # 43 | # Security 44 | # 45 | # 46 | #Tomcat Server Config 47 | # 48 | server.tomcat.accesslog.enabled=true 49 | server.tomcat.uri-encoding=UTF-8 50 | server.port=8086 51 | # 52 | # gzip, compression 53 | server.compression.enabled=true 54 | server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain 55 | server.compression.min-response-size=1024 56 | # 57 | #Application host url, end by '/' 58 | application.host=http://localhost:${server.port}/ 59 | 60 | -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/jwks.json: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "alg": "RS256", 5 | "d": "PvBAngE3kkTnD3yDKo3wCvHJHm20kb9a0FVGLd0s2Y0E_3H2XnZC8-2zPhN6AQTjPhohSDCew20gzm76lyOvMqRiUP2Zpaopa1d2fGvNIQSdM07yKa6EivEYxqPQxa5esoZnexgnb9fom70I8n5OQRNQikwu-az26CsHX2zWMRodzSdN5CXHvb1PV09DmH8azTYwoMElPIqmcTfxiRw2Ov5ucmXXngKRFJgvfUgKd7v4ScBX7sQoQEjWEtt7ta0WvL3Ar5E1RAW4aHxuubZ6AtloxWCf17AAKw03dfP5RDm5TDmgm2B635ecJ7fTvneFmg8W_fdMTPRfBlCGNBp3wQ", 6 | "e": "AQAB", 7 | "n": "qt6yOiI_wCoCVlGO0MySsez0VkSqhPvDl3rfabOslx35mYEO-n4ABfIT5Gn2zN-CeIcOZ5ugAXvIIRWv5H55-tzjFazi5IKkOIMCiz5__MtsdxKCqGlZu2zt-BLpqTOAPiflNPpM3RUAlxKAhnYEqNha6-allPnFQupnW_eTYoyuzuedT7dSp90ry0ZcQDimntXWeaSbrYKCj9Rr9W1jn2uTowUuXaScKXTCjAmJVnsD75JNzQfa8DweklTyWQF-Y5Ky039I0VIu-0CIGhXY48GAFe2EFb8VpNhf07DP63p138RWQ1d3KPEM9mYJVpQC68j3wzDQYSljpLf9by7TGw", 8 | "kty": "RSA", 9 | "kid": "rsa1" 10 | }, 11 | { 12 | "kty": "RSA", 13 | "kid": "myoidc-keyid", 14 | "use": "sig", 15 | "alg": "RS256", 16 | "n": "n6X4_VZSQjxmSqBqmIq5ZbaLynXPP3yCOF2xE250NaYLferU8LX3xAvuNLnZkaUH-4cnr_JuSlN_7JIAwAd5oLHSuSByPcxSJ95uGniDji22s-yQ19rqZCQHLmJwg3WZpWPN-HmwxPOFNlkW_2ETjqMzS-3kGduz-IPfebwNbVFu6RglHT_V6IyaDUbSvV80AAQ7R8Y6xBvu25ZSniu3JHj2u8AtScJgiOqfsImsaCABdmUO4LtMzB1V7pafH-_puRWYCl5_uaYYPMxv-EOonPCyTlzJtC6ZeiiI4LNtxWwEamRyTS0xX8Czt3s5mRW2q6pgMZQsqlL64Df8MDuFpQ", 17 | "e": "AQAB", 18 | "d": "E92YRRXnuHxBkkmx2fdxKHn1nSTZvCGnJpJqBWv6I-7cgTemdal_AjMl2gPCUgBCJQdlZdx54t_PDEYCt-J2PQvDl-u0q4HwOyvPcZXLcPa5RFxMjb-c6QceqaPwMjuA-faYW7Hw0CEpU2D0nqSaxWYDbRBWEO2o0GTAeypuVUrZXGilOLjal68Tho8ZYbmyXsEvEdqCob_iUe6q4c2x0amMmn2ot3bKKqdjbVXMjVfEqHHMPMdnVmrr_yfTUlXN3ZT4Ypp7wDrAVs7pfbvrCKWzLQYlbYNjZeBoKNcGabAA7WuNGxWvi3971gLSdYwRw4TngOweIhVW8kxiiA77QQ", 19 | "p": "2R_SdLqd7d7hVJTAVY4Twx8j7VQq6-TTMVcyD_YLeBGvlkngpSz7NSQu1LTYGEHa_CzeCOFmKgtuLZ84zyS_wUxgF3AH0VD-xNZSAaHfzWXAwLmezYzGBXXF0ho8qpbf2aTNZZx2n5z0cb0loitAfmfrsd9XU226nXpPAgV-gTE", 20 | "q": "vDup5zcW9NwxVs9-C-W1uwL7TpQIKNk9oBvbfgD6XkwIn3JmCfny2Nm-paK45YM169JhnUml7z6On2Bq81rNtPwkqWTp9d2SfsQkuNddtfeYi_FulLqMLeQvCr2TAdFE-4uYKcU_-5u21oomnVm5vgGs8aFzd_J-57i-GfPxjrU", 21 | "dp": "UwpZqm1JQ5WvpnKx0MbjBghd7EH5nHjK0R8hNXuLzWMuPZOJyIKYnS12f8GeuEBPqYzbapgSQ9hVTjuMNaU_dYVpZu1hAAwzNEMn4BnyB5N4Ef2sH79MaQAvJXkFZNUJTis6pzcdI1SbJPkLcKeMJgxG16OsuWrJKbuChiplxLE", 22 | "dq": "aQYJGD6-ikRJKxx-QXkbWoqhWQhzPQdowOqKHtXA29gkf4I-uJZDDwb-vj_6VeRNs5Qgbrfm44PN49LSGZGycKa2deUePNYxpJUfwBo56QuKi5pbjpQ_HmPQc3eujDcM_CS486Vgu6v36eAPB4BGiGM68V6ZpHUipXuIZcacInk", 23 | "qi": "bvay2Ej4FIYrFpD0zW-xEpHoPxXmNJRyR4rL4SGVq-ILghfVqfTQszI2MUnpubcUAUsqYYZUvvemfust35eYiSaYWzUDGsjmUWhZDD8VTKEyxbWwya7GztarLMud2LGn76a41zyStU46g84G1ZPNcZTK_1DIR0_BpayN44jj3kk" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/favicon.ico -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/images/oidc-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/images/oidc-sm.png -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/public/images/openid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/myoidc-server/src/main/resources/public/images/openid.png -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/templates/admin/user_list.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 用户[EU] . MyOIDC 9 | 10 | 11 | 12 | 13 | 14 |

15 | 16 |
17 |

用户[EU]

18 | 19 |
20 |
21 | 23 |
24 | 25 |  Total: [[${listDto.size}]] 26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 51 | 52 | 53 |
账号权限电话邮箱创建时间操作
unity[UNITY]133...xxx@xxx.com2019-xxx 47 | archive 49 | ... 50 |
54 | 55 |
56 | 57 |
58 |
59 | 60 | -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/templates/fragment/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Fragment Footer 7 | 8 | 9 | 10 |
11 | 12 |

© 2017-2020  MyOIDC  14 | V

15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/templates/fragment/header.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Fragment Header 7 | 8 | 9 |
10 | 12 |
13 | 14 | 15 | 16 | 17 |
18 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/templates/registration_form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 注册 . MyOIDC 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | Logo 19 | 20 |

请填写注册信息

21 |
22 | 23 |
24 | 25 |
26 | 28 |
29 |
30 |
31 | 32 |
33 | 36 |
37 |
38 |
39 |
40 |
41 |

43 |
44 |
45 | 46 | 47 |
48 |
49 |
50 | 51 | 返回 52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/templates/registration_pre.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 注册 . MyOIDC 8 | 9 | 10 | 11 | 12 | 13 |
14 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /myoidc-server/src/main/resources/templates/registration_success.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 注册 . MyOIDC 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | Logo 19 | 20 |

注册成功!

21 |

请保存以下注册信息

22 |
23 |
24 |
ClientId
25 |
xxx
26 |
ClientSecret
27 |
xxx
28 |
Redirect Uri
29 |
xxx
30 |
Scope
31 |
xxx
32 |
GrantType
33 |
xxx
34 |
Discovery-Endpoint
35 |
xxx
36 |
37 |
38 | 主页 39 |
40 |
41 |
42 |
43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/ContextTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server; 2 | 3 | 4 | import myoidc.server.domain.security.OIDCUserDetails; 5 | import myoidc.server.domain.security.SecurityUtils; 6 | import myoidc.server.domain.shared.BeanProvider; 7 | import myoidc.server.web.context.SpringSecurityHolder; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.TestPropertySource; 11 | import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | import org.springframework.test.context.transaction.BeforeTransaction; 14 | 15 | 16 | /** 17 | * @author Shengzhao Li 18 | */ 19 | @RunWith(SpringRunner.class) 20 | @SpringBootTest 21 | @TestPropertySource(locations = "classpath:application-test.properties") 22 | public abstract class ContextTest extends AbstractTransactionalJUnit4SpringContextTests { 23 | 24 | 25 | @BeforeTransaction 26 | public void before() throws Exception { 27 | BeanProvider.initialize(applicationContext); 28 | SecurityUtils securityUtils = new SecurityUtils(); 29 | securityUtils.setSecurityHolder(new SpringSecurityHolder() { 30 | @Override 31 | public OIDCUserDetails userDetails() { 32 | return null; 33 | } 34 | }); 35 | } 36 | 37 | 38 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/JwkTokenStoreTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server; 2 | 3 | import org.junit.Ignore; 4 | import org.junit.Test; 5 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 6 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 7 | import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore; 8 | 9 | import java.util.List; 10 | 11 | import static org.junit.Assert.assertNotNull; 12 | 13 | /** 14 | * 2020/3/13 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | public class JwkTokenStoreTest { 19 | 20 | 21 | @Test 22 | @Ignore 23 | public void test() throws Exception { 24 | 25 | String jwkSetUrl = "http://localhost:8080/myoidc-server/public/jwks"; 26 | JwkTokenStore tokenStore = new JwkTokenStore(jwkSetUrl); 27 | 28 | assertNotNull(tokenStore); 29 | 30 | String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6WyJteW9pZGMtcmVzb3VyY2UiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJvcGVuaWQiXSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL215b2lkYy1zZXJ2ZXIvIiwiZXhwIjoxNTg0MDczNDc5LCJpYXQiOjE1ODQwMzAyNzksImF1dGhvcml0aWVzIjpbIlJPTEVfTU9CSUxFIiwiUk9MRV9BRE1JTiIsIlJPTEVfVVNFUiIsIlJPTEVfVU5JVFkiXSwianRpIjoiZmU3MGY3NjktZTIxYi00NzczLWJlN2EtYTQwMGE0MzY2YWYxIiwiY2xpZW50X2lkIjoibW9iaWxlLWNsaWVudCJ9.L7nETF-NDQcJV0YiZVbT25mSF-LPWq7oLoCPR1N5glCnB_wZO3i1wfIbVqo0HAtcTHwiLeRkyPBCDn2BTEdotQqyTxazAloV2dCej_9b2a341mAzqpsVHQygkYdMVNW5Gfo4QaBMab_PCNAeO5w0BRHhlCOVi-WMmvzoaZrPyFaLS0sURMqpCTjvrt7e_XkkCOoY-0WcRbXmWGmgB9Kil0NVA4j67pUVFMMP2sgzoCNmmYXK70vVLTzSRjodbEQqsyS9Q6sU7E28hT8Vu21GVyHIL0S0p1tK5JKXPerb-UGWBXSV90LEynTe0hU5IJxW-urN6YaoxcZfy6eGm8jI9w"; 31 | // OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(token); 32 | // assertNotNull(oAuth2AccessToken); 33 | 34 | OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); 35 | assertNotNull(oAuth2Authentication); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/MyOIDCServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package myoidc.server; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.TestPropertySource; 7 | import org.springframework.test.context.junit4.SpringRunner; 8 | 9 | @RunWith(SpringRunner.class) 10 | @SpringBootTest 11 | @TestPropertySource(locations = "classpath:application-test.properties") 12 | public class MyOIDCServerApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/configuration/SecurityConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.configuration; 2 | 3 | import org.junit.Test; 4 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 5 | 6 | import static org.junit.Assert.*; 7 | 8 | /** 9 | * 2018/3/22 10 | * 11 | * @author Shengzhao Li 12 | */ 13 | public class SecurityConfigurationTest { 14 | @Test 15 | public void passwordEncoder() throws Exception { 16 | 17 | 18 | BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 19 | final String rawPassword = "mobile"; 20 | final String admin = passwordEncoder.encode(rawPassword); 21 | 22 | assertNotNull(admin); 23 | 24 | // System.out.println(rawPassword + " --> " + admin); 25 | 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/domain/shared/UUIDGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.domain.shared; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 2018/3/22 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public class UUIDGeneratorTest { 11 | 12 | 13 | @Test 14 | public void generate() throws Exception { 15 | 16 | System.out.println(UUIDGenerator.generate()); 17 | 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/AbstractRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | import myoidc.server.ContextTest; 4 | import org.junit.Test; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.EntityManagerFactory; 9 | 10 | import static org.junit.Assert.assertNotNull; 11 | 12 | /** 13 | * 2018/3/22 14 | * 15 | * @author Shengzhao Li 16 | */ 17 | public class AbstractRepositoryTest extends ContextTest { 18 | 19 | 20 | @Autowired 21 | private EntityManagerFactory entityManagerFactory; 22 | 23 | 24 | protected EntityManager entityManager() { 25 | return entityManagerFactory.createEntityManager(); 26 | } 27 | 28 | 29 | protected void flush() { 30 | EntityManager entityManager = entityManager(); 31 | entityManager.flush(); 32 | entityManager.clear(); 33 | } 34 | 35 | 36 | @Test 37 | public void test() { 38 | assertNotNull(entityManagerFactory); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/Auth0JwtTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | 4 | import com.auth0.jwt.JWT; 5 | import com.auth0.jwt.JWTVerifier; 6 | import com.auth0.jwt.algorithms.Algorithm; 7 | import com.auth0.jwt.interfaces.DecodedJWT; 8 | import org.junit.Test; 9 | 10 | import java.security.KeyPair; 11 | import java.security.KeyPairGenerator; 12 | import java.security.PrivateKey; 13 | import java.security.PublicKey; 14 | import java.security.interfaces.RSAPrivateKey; 15 | import java.security.interfaces.RSAPublicKey; 16 | 17 | import static org.junit.Assert.assertNotNull; 18 | 19 | /** 20 | * 2018/5/30 21 | *

22 | * OAuth0 jwt 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public class Auth0JwtTest { 27 | 28 | 29 | /** 30 | * Test JWT 31 | * 32 | * @throws Exception Exception 33 | */ 34 | @Test 35 | public void jwt() throws Exception { 36 | 37 | // RSA keyPair Generator 38 | final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 39 | /* 40 | * 长度 至少 1024, 建议 2048 41 | */ 42 | final int keySize = 2048; 43 | keyPairGenerator.initialize(keySize); 44 | 45 | final KeyPair keyPair = keyPairGenerator.genKeyPair(); 46 | 47 | 48 | final PublicKey publicKey = keyPair.getPublic(); 49 | final PrivateKey privateKey = keyPair.getPrivate(); 50 | 51 | 52 | // gen id_token 53 | final Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) publicKey, (RSAPrivateKey) privateKey); 54 | 55 | final String idToken = JWT.create().withJWTId("jwt-id").withAudience("audience").withSubject("subject").sign(algorithm); 56 | 57 | assertNotNull(idToken); 58 | System.out.println(idToken); 59 | 60 | 61 | //verify 62 | // final DecodedJWT decodedJWT = JWT.decode(idToken); 63 | // System.out.println("id_token -> header: " + decodedJWT.getHeader()); 64 | // System.out.println("id_token -> payload: " + decodedJWT.getPayload()); 65 | // System.out.println("id_token -> token: " + decodedJWT.getToken()); 66 | // System.out.println("id_token -> signature: " + decodedJWT.getSignature()); 67 | 68 | 69 | final JWTVerifier verifier = JWT.require(algorithm).build(); 70 | final DecodedJWT verify = verifier.verify(idToken); 71 | 72 | assertNotNull(verify); 73 | System.out.println(verify); 74 | 75 | 76 | // final Algorithm none = Algorithm.none(); 77 | 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/JJwtTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | 4 | import io.jsonwebtoken.*; 5 | import org.apache.commons.lang3.time.DateUtils; 6 | import org.junit.Test; 7 | 8 | import java.security.KeyPair; 9 | import java.security.KeyPairGenerator; 10 | import java.security.PrivateKey; 11 | import java.security.PublicKey; 12 | import java.util.Date; 13 | 14 | import static org.junit.Assert.assertNotNull; 15 | 16 | /** 17 | * 2018/5/30 18 | *

19 | *

20 | * Test JJWT lib 21 | * 22 | * @author Shengzhao Li 23 | */ 24 | public class JJwtTest { 25 | 26 | 27 | @Test 28 | public void idToken() throws Exception { 29 | 30 | // RSA keyPair Generator 31 | final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 32 | /* 33 | * 长度 至少 1024, 建议 2048 34 | */ 35 | final int keySize = 2048; 36 | keyPairGenerator.initialize(keySize); 37 | 38 | final KeyPair keyPair = keyPairGenerator.genKeyPair(); 39 | 40 | final PrivateKey privateKey = keyPair.getPrivate(); 41 | 42 | // gen id_token 43 | final Date exp = DateUtils.addMinutes(new Date(), 5); 44 | final JwtBuilder jwtBuilder = Jwts.builder().setId("jti").setSubject("sub").setExpiration(exp).signWith(SignatureAlgorithm.RS512, privateKey); 45 | final String idToken = jwtBuilder.compact(); 46 | 47 | 48 | assertNotNull(idToken); 49 | System.out.println(idToken); 50 | 51 | 52 | // verify 53 | 54 | final PublicKey publicKey = keyPair.getPublic(); 55 | // final Jwt jwt = Jwts.parser().parse(idToken); 56 | final JwtParser parser = Jwts.parser(); 57 | final Jwt jwt = parser.setSigningKey(publicKey).parse(idToken); 58 | 59 | assertNotNull(jwt); 60 | System.out.println(jwt.getHeader()); 61 | System.out.println(jwt.getBody()); 62 | 63 | 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/JsonWebKeySetTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | import com.google.common.base.Charsets; 4 | import com.google.common.io.CharStreams; 5 | import org.jose4j.jwk.JsonWebKey; 6 | import org.jose4j.jwk.JsonWebKeySet; 7 | import org.jose4j.jws.AlgorithmIdentifiers; 8 | import org.jose4j.jws.JsonWebSignature; 9 | import org.jose4j.jwt.JwtClaims; 10 | import org.junit.Test; 11 | 12 | import java.io.InputStream; 13 | import java.io.InputStreamReader; 14 | 15 | import static org.junit.Assert.assertNotNull; 16 | 17 | /** 18 | * 2020/6/3 19 | * 20 | * @author Shengzhao Li 21 | * @since 1.1.1 22 | */ 23 | public class JsonWebKeySetTest { 24 | 25 | 26 | //RSA 27 | @Test 28 | public void keySet() throws Exception { 29 | 30 | JsonWebKeySet jwkSet; 31 | try (InputStream is = getClass().getClassLoader().getResourceAsStream("jwks_rsa.json")) { 32 | String keyJson = CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8)); 33 | jwkSet = new JsonWebKeySet(keyJson); 34 | } 35 | 36 | JsonWebKey jsonWebKey = jwkSet.getJsonWebKeys().get(0); 37 | assertNotNull(jsonWebKey); 38 | 39 | 40 | } 41 | 42 | 43 | //ECC 44 | @Test 45 | public void keyECCSet() throws Exception { 46 | 47 | JsonWebKeySet jwkSet; 48 | try (InputStream is = getClass().getClassLoader().getResourceAsStream("jwks_ec.json")) { 49 | String keyJson = CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8)); 50 | jwkSet = new JsonWebKeySet(keyJson); 51 | } 52 | 53 | JsonWebKey jsonWebKey = jwkSet.getJsonWebKeys().get(0); 54 | assertNotNull(jsonWebKey); 55 | 56 | 57 | } 58 | 59 | 60 | //OCT 61 | @Test 62 | public void keyOCTSet() throws Exception { 63 | 64 | JsonWebKeySet jwkSet; 65 | try (InputStream is = getClass().getClassLoader().getResourceAsStream("jwks_oct.json")) { 66 | String keyJson = CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8)); 67 | jwkSet = new JsonWebKeySet(keyJson); 68 | } 69 | 70 | JsonWebKey jsonWebKey = jwkSet.getJsonWebKeys().get(0); 71 | assertNotNull(jsonWebKey); 72 | 73 | 74 | JsonWebSignature jws = new JsonWebSignature(); 75 | jws.setKey(jsonWebKey.getKey()); 76 | 77 | JwtClaims claims = new JwtClaims(); 78 | claims.setGeneratedJwtId(); 79 | claims.setIssuedAtToNow(); 80 | claims.setSubject("subject"); 81 | jws.setPayload(claims.toJson()); 82 | 83 | jws.setKeyIdHeaderValue(jsonWebKey.getKeyId()); 84 | jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256); 85 | 86 | String idToken = jws.getCompactSerialization(); 87 | assertNotNull(idToken); 88 | // System.out.println(idToken); 89 | 90 | } 91 | 92 | 93 | } 94 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/PasswordHandlerTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * 2020/3/22 9 | * 10 | * @author Shengzhao Li 11 | */ 12 | public class PasswordHandlerTest { 13 | 14 | 15 | @Test 16 | public void randomPassword() { 17 | 18 | String s = PasswordHandler.randomPassword(); 19 | assertNotNull(s); 20 | assertEquals(s.length(), 12); 21 | System.out.println(s); 22 | 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/PrimeJwtTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | 4 | import org.junit.Test; 5 | import org.primeframework.jwt.JWTUtils; 6 | import org.primeframework.jwt.domain.JWT; 7 | import org.primeframework.jwt.domain.RSAKeyPair; 8 | import org.primeframework.jwt.hmac.HMACSigner; 9 | import org.primeframework.jwt.hmac.HMACVerifier; 10 | import org.primeframework.jwt.rsa.RSASigner; 11 | import org.primeframework.jwt.rsa.RSAVerifier; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | import static org.junit.Assert.assertNotNull; 15 | 16 | /** 17 | * 2018/6/2 18 | *

19 | * Testing 20 | * https://github.com/inversoft/prime-jwt 21 | * 22 | * @author Shengzhao Li 23 | */ 24 | public class PrimeJwtTest { 25 | 26 | 27 | /** 28 | * Test RSA 非对称算法 29 | * 30 | * @throws Exception Exception 31 | */ 32 | @Test 33 | public void jwtRSA() throws Exception { 34 | 35 | 36 | // keypair 37 | final RSAKeyPair rsaKeyPair = JWTUtils.generate2048RSAKeyPair(); 38 | 39 | System.out.println("PublicKey: " + rsaKeyPair.publicKey); 40 | System.out.println("PrivateKey: " + rsaKeyPair.privateKey); 41 | 42 | 43 | // final RSAPublicKey publicKey = RSAUtils.getPublicKeyFromPEM(rsaKeyPair.publicKey); 44 | // final RSAPrivateKey privateKey = RSAUtils.getPrivateKeyFromPEM(rsaKeyPair.privateKey); 45 | 46 | // generate 47 | final RSASigner rsaSigner = RSASigner.newSHA256Signer(rsaKeyPair.privateKey); 48 | final JWT jwt = new JWT().setSubject("subject").setAudience("audi").setUniqueId("uid-id"); 49 | final String idToken = JWT.getEncoder().encode(jwt, rsaSigner); 50 | 51 | assertNotNull(idToken); 52 | System.out.println(idToken); 53 | 54 | //verify 55 | final RSAVerifier rsaVerifier = RSAVerifier.newVerifier(rsaKeyPair.publicKey); 56 | final JWT decode = JWT.getDecoder().decode(idToken, rsaVerifier); 57 | 58 | assertNotNull(decode); 59 | assertEquals(decode.audience, "audi"); 60 | 61 | } 62 | 63 | /** 64 | * Test HMAC, 对称算法 65 | * 66 | * @throws Exception Exception 67 | */ 68 | @Test 69 | public void jwtHMAC() throws Exception { 70 | 71 | 72 | // secret 73 | final String secret = JWTUtils.generateSHA256HMACSecret(); 74 | 75 | System.out.println("secret: " + secret); 76 | 77 | 78 | // generate 79 | 80 | final JWT jwt = new JWT().setSubject("subject").setAudience("audi").setUniqueId("uid-id"); 81 | final HMACSigner hmacSigner = HMACSigner.newSHA256Signer(secret); 82 | final String idToken = JWT.getEncoder().encode(jwt, hmacSigner); 83 | 84 | assertNotNull(idToken); 85 | System.out.println(idToken); 86 | 87 | //verify 88 | final HMACVerifier hmacVerifier = HMACVerifier.newVerifier(secret); 89 | final JWT decode = JWT.getDecoder().decode(idToken, hmacVerifier); 90 | 91 | assertNotNull(decode); 92 | assertEquals(decode.audience, "audi"); 93 | 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/RandomUtilsTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.*; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | public class RandomUtilsTest { 12 | 13 | @Test 14 | public void testRandomText() throws Exception { 15 | 16 | final String random = RandomUtils.randomText(); 17 | assertNotNull(random); 18 | assertEquals(random.length(), 32); 19 | // System.out.println(random); 20 | 21 | } 22 | 23 | @Test 24 | public void testRandomNumber() throws Exception { 25 | 26 | final String number = RandomUtils.randomNumber(); 27 | assertNotNull(number); 28 | assertEquals(number.length(), 32); 29 | // System.out.println(number); 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/VertxAuthJwtTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure; 2 | 3 | 4 | import io.vertx.core.json.JsonObject; 5 | import io.vertx.ext.jwt.JWK; 6 | import io.vertx.ext.jwt.JWT; 7 | import io.vertx.ext.jwt.JWTOptions; 8 | import org.junit.Test; 9 | 10 | import java.security.KeyPair; 11 | import java.security.KeyPairGenerator; 12 | import java.security.PrivateKey; 13 | import java.security.PublicKey; 14 | import java.util.Base64; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | 19 | /** 20 | * 2018/6/2 21 | *

22 | * Test 23 | * https://github.com/vert-x3/vertx-auth 24 | * 25 | * @author Shengzhao Li 26 | */ 27 | public class VertxAuthJwtTest { 28 | 29 | 30 | /** 31 | * Generate/ Verify 32 | * 33 | * @throws Exception Exception 34 | */ 35 | @Test 36 | public void jwt() throws Exception { 37 | 38 | 39 | // RSA keyPair Generator 40 | final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 41 | /* 42 | * 长度 至少 1024, 建议 2048 43 | */ 44 | final int keySize = 2048; 45 | keyPairGenerator.initialize(keySize); 46 | 47 | final KeyPair keyPair = keyPairGenerator.genKeyPair(); 48 | //公钥 49 | final PublicKey publicKey = keyPair.getPublic(); 50 | //私钥 51 | final PrivateKey privateKey = keyPair.getPrivate(); 52 | 53 | 54 | final String pemPub = Base64.getEncoder().encodeToString(publicKey.getEncoded()); 55 | final String pemSec = Base64.getEncoder().encodeToString(privateKey.getEncoded()); 56 | 57 | 58 | //generate 59 | final String algorithm = "RS256"; 60 | JWK jwk = new JWK(algorithm, pemPub, pemSec); 61 | final JWT jwt = new JWT().addJWK(jwk); 62 | 63 | 64 | JsonObject payload = new JsonObject(); 65 | payload.put("appid", "appid"); 66 | 67 | JWTOptions options = new JWTOptions(); 68 | options.setAlgorithm(algorithm); 69 | options.setSubject("subject"); 70 | 71 | String idToken = jwt.sign(payload, options); 72 | 73 | assertNotNull(idToken); 74 | System.out.println(idToken); 75 | 76 | 77 | //verify 78 | JWK jwk2 = new JWK(algorithm, pemPub, pemSec); 79 | final JWT jwtVerify = new JWT().addJWK(jwk2); 80 | 81 | final JsonObject decode = jwtVerify.decode(idToken); 82 | assertNotNull(decode); 83 | assertEquals(decode.getString("appid"), "appid"); 84 | 85 | } 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/jdbc/OauthRepositoryJdbcTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.jdbc; 2 | 3 | import myoidc.server.domain.oauth.OauthClientDetails; 4 | import myoidc.server.infrastructure.AbstractRepositoryTest; 5 | import org.junit.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | import java.util.List; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * 2020/3/19 14 | * 15 | * @author Shengzhao Li 16 | */ 17 | public class OauthRepositoryJdbcTest extends AbstractRepositoryTest { 18 | 19 | 20 | @Autowired 21 | private OauthRepositoryJdbc repositoryJdbc; 22 | 23 | 24 | @Test 25 | public void findAllOauthClientDetails() { 26 | 27 | List list = repositoryJdbc.findAllOauthClientDetails("client_id"); 28 | assertTrue(list.isEmpty()); 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/jpa/UserRepositoryHibernateTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.jpa; 2 | 3 | import myoidc.server.domain.user.Privilege; 4 | import myoidc.server.domain.user.User; 5 | import myoidc.server.domain.user.UserPrivilege; 6 | import myoidc.server.domain.user.UserRepository; 7 | import myoidc.server.infrastructure.AbstractRepositoryTest; 8 | import org.junit.Test; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | 11 | import java.util.List; 12 | 13 | import static org.junit.Assert.assertNotNull; 14 | import static org.junit.Assert.assertNull; 15 | import static org.junit.Assert.assertTrue; 16 | 17 | /** 18 | * 2018/3/22 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | public class UserRepositoryHibernateTest extends AbstractRepositoryTest { 23 | 24 | 25 | @Autowired 26 | private UserRepository userRepository; 27 | 28 | 29 | @Test 30 | public void findUserPrivileges() throws Exception { 31 | 32 | 33 | User user = new User().username("test").password("owesdds"); 34 | userRepository.saveOrUpdate(user); 35 | 36 | UserPrivilege userPrivilege = new UserPrivilege(user, Privilege.USER); 37 | userRepository.saveOrUpdate(userPrivilege); 38 | 39 | // flush(); 40 | 41 | final List privileges = userRepository.findUserPrivileges(user.uuid()); 42 | assertNotNull(privileges); 43 | // System.out.println(privileges); 44 | } 45 | 46 | 47 | @Test 48 | public void findUsersByUsername() { 49 | 50 | List list = userRepository.findUsersByUsername("us"); 51 | assertTrue(list.isEmpty()); 52 | 53 | } 54 | 55 | 56 | @Test 57 | public void findUserByUsernameNoArchived() { 58 | 59 | User user = userRepository.findUserByUsernameNoArchived("user"); 60 | assertNull(user); 61 | 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/infrastructure/oidc/OIDCUtilsTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.infrastructure.oidc; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * 2020/3/23 9 | * 10 | * @author Shengzhao Li 11 | * @since 1.1.0 12 | */ 13 | public class OIDCUtilsTest { 14 | 15 | 16 | @Test 17 | public void isJWT() { 18 | 19 | assertFalse(OIDCUtils.isJWT("aaa")); 20 | assertFalse(OIDCUtils.isJWT("aaa.bb")); 21 | assertFalse(OIDCUtils.isJWT("")); 22 | assertFalse(OIDCUtils.isJWT(null)); 23 | assertFalse(OIDCUtils.isJWT("aaa.bb.cc.dd")); 24 | 25 | assertTrue(OIDCUtils.isJWT("aaa.bb.cc")); 26 | assertTrue(OIDCUtils.isJWT("eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im15b2lkYy1rZXlpZCJ9.eyJzdWIiOiJtb2JpbGUiLCJhdWQiOlsibXlvaWRjLXJlc291cmNlIl0sInVzZXJfbmFtZSI6Im1vYmlsZSIsInNjb3BlIjpbIm9wZW5pZCIsInJlYWQiXSwiYXRpIjoiZjcyMmM3ZTQtZDZkMC00ZWVmLThmYWYtZThjZGU5ODA5N2Y0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL215b2lkYy1zZXJ2ZXIvIiwiZXhwIjoxNTg3NDUwMzU2LCJpYXQiOjE1ODQ4NTgzNTYsImF1dGhvcml0aWVzIjpbIlJPTEVfTU9CSUxFIiwiUk9MRV9VU0VSIl0sImp0aSI6ImRkMzQ1NjEzLWExYWUtNDk0OS05MjVhLThiOTc4OTMwZGZjMCIsImNsaWVudF9pZCI6InVaeWlyQTNSdkFtN09UVkk2In0.gGz8j52iCk-40OUTFcLUVpH7VpxhiyenaVEZJ3_hu634BkdLjzpJwk3eGZBixPUQXLvuF3HUPgkevcYrAxn21u2QF4p3Qqr1P2ebT8ERwD1Sov2eeWrdGW_pr4KgyFFSZ64hczCCLZYILmwpXFDzV_dBiUQx0h2ttUAKm55NOQ6Ve-uE48XIBdXvjR9cJwy1EJ-BHgf6lp9xbZi0uQ2Mw2SEgV7C1q9e-1VJzBFGLRH1tD3xX1e5i4We_fqFg_gyTmd4sciQpExFWR1DaYsPnxYtYpVJYnfzPL5JLpw7eImnnw8oO7EWZiibORWem626T-WgzFRVd4lFaFaXqU33uA")); 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/java/myoidc/server/service/business/ClientRegistrationFormSaverTest.java: -------------------------------------------------------------------------------- 1 | package myoidc.server.service.business; 2 | 3 | import myoidc.server.domain.oauth.OauthClientDetails; 4 | import myoidc.server.infrastructure.oidc.OIDCUseScene; 5 | import myoidc.server.service.dto.ClientRegistrationFormDto; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | /** 11 | * 2020/4/1 12 | * 13 | * @author Shengzhao Li 14 | * @since 1.1.0 15 | */ 16 | public class ClientRegistrationFormSaverTest { 17 | 18 | 19 | @Test 20 | public void createDomain() throws Exception { 21 | 22 | ClientRegistrationFormDto dto = new ClientRegistrationFormDto(OIDCUseScene.WEB); 23 | dto.setAppName("Test"); 24 | dto.setWebServerRedirectUri("https://abc.com/back"); 25 | ClientRegistrationFormSaver formSaver = new ClientRegistrationFormSaver(dto); 26 | 27 | OauthClientDetails secret = formSaver.createDomain(); 28 | assertNotNull(secret); 29 | // System.out.println(secret); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /myoidc-server/src/test/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | # MyOIDC -Server V-1.1.0 2 | # 3 | spring.application.name=MyOIDC 4 | # 5 | #JDBC 6 | #Connection 7 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 8 | spring.datasource.url=jdbc:mysql://localhost:3306/myoidc_server_test?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC 9 | spring.datasource.username=andaily 10 | spring.datasource.password=andaily 11 | #Datasource properties 12 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 13 | spring.datasource.hikari.maximum-pool-size=20 14 | spring.datasource.hikari.minimum-idle=2 15 | # 16 | # MVC 17 | spring.mvc.ignore-default-model-on-redirect=false 18 | spring.http.encoding.enabled=true 19 | spring.http.encoding.charset=UTF-8 20 | spring.http.encoding.force=true 21 | # 22 | #THYMELEAF (ThymeleafAutoConfiguration) 23 | # 24 | spring.thymeleaf.prefix=/WEB-INF/view/ 25 | spring.thymeleaf.suffix=.html 26 | #spring.thymeleaf.mode=HTML5 27 | spring.thymeleaf.encoding=UTF-8 28 | # ;charset= is added 29 | #spring.thymeleaf.content-type=text/html 30 | # set to false for hot refresh 31 | spring.thymeleaf.cache=false 32 | # 33 | # Logging INFO 34 | # 35 | logging.level.root=WARN 36 | #logging.config=classpath:log4j2.xml 37 | #logging.level.org.springframework.transaction.interceptor=TRACE 38 | # 39 | # Security 40 | # 41 | #security.filter-order=8888 42 | # 43 | #Tomcat Server Config 44 | # 45 | server.tomcat.accesslog.enabled=true 46 | server.tomcat.uri-encoding=UTF-8 47 | server.port=8080 48 | # 49 | # gzip, compression 50 | server.compression.enabled=true 51 | server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain 52 | server.compression.min-response-size=1024 53 | # 54 | #Application host url, end by '/' 55 | application.host=http://localhost:7777/myoidc-server/ 56 | 57 | -------------------------------------------------------------------------------- /myoidc-server/src/test/resources/jwks_ec.json: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "kty": "EC", 5 | "d": "bFH2NXpNxjEKGrnnjJCLrrBfEIxKw9o4qfBAYzowdCQ", 6 | "use": "sig", 7 | "crv": "P-256", 8 | "kid": "myoidc-keyid", 9 | "x": "_E35xwg2gODQkkpBGnKr2SsXVp9l13HXC-dtzfnMQ_c", 10 | "y": "VXzxPdrF8Uj7gBYbaHBDCfwkvpfJU-EhO8fd9Q0JLo4", 11 | "alg": "ES256" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /myoidc-server/src/test/resources/jwks_oct.json: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "kty": "oct", 5 | "use": "enc", 6 | "kid": "myoidc-keyid", 7 | "k": "x5nQay6CzVV7kuPeYA7Y23pVk3eJqYZLGMOp9TiwOiVHDyq1vaJzvVrMNJ4qNQaC5YaNn71jmHu3OZ3f1WK9BfpUPIY8RRc-DvssK7Pyjg8oa-2UI_OwY0yIXeaUSC7qJbpI22qyvATiVC6I7kKv3_FXXWeStayJj1gsiQmofqmLl2nmuqyk60jCIQx8TQYN5Fc4dIvIJkYVrOwYfIImAbwxeNifoF-bXeQqLK1DovtJFLg_uA_-Aeabh4QLXAM2VcLUGO9TDhpq-V8WkqX47TooB_r1IhQv0hsHAwvRC_ahHvNkU8OkXdpWUtnlGmtefd8-PWQkq5M0_d-5Jhvnkg", 8 | "alg": "HS256" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /myoidc-server/src/test/resources/jwks_rsa.json: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "p": "7rfP7BCnbEvA3d4oVxCBPfDRdUz6XCzcTPqv5jLI6rQUpFoWjT-alK1t57NeU-E_D7YXyWhH8xt5tEsYF3jZXrjrDPF2rrSFb45QyZOPpvsxc_BK66d3RVHoN-t_0ZpZ-eUwrUHyiDplnSy61r1ygbe3Ygn4dFo58mG5key92Rk", 5 | "kty": "RSA", 6 | "q": "5-W4swQFw64wxwDtbu0vpiKXiDn45hH3UyyJWMGIobFlELH4u8bCHvQtRLOaKj2ulA_gb6jLuJDM6u-JNc23pGWVpdtbAQHPQoxZFpswzLsrDDfU074PepBZqWDe0IGwPCjEP4s_cadCHWnMyC0J6cG0sXN9ZsdEDaJs0T_DqcU", 7 | "d": "wYFbEfaAthdlipSk7YqeBJ-qZJJDcvcvwiIYPlSzwR9b4A_zSDShRhxknqLviFB2CxrqD_Y_fLub5bnEU6wQM2CdMsm5RU5uva20b5fyjeWmOuALg-BuFL8ZmQK0j9LVqHzDlz9oMxgVwdYAImRzVVXvrIR9VS8_EZrIXAGzs-uqJMiI8ahrsRcd2wt4VAxH5qQxp3cdjs69SIlGY6P2GiZg8VB4NIJscBEqyNW18OIaCOpCOBnKCJ45wBMzQt_dAkMJxJnda7DJnEyQdpKabamt6S2IHFHuJgGqlz9MpXYDMgLK0y4stBQpF8fofvZeeGghZuhMnGeWIoxyIH4cQQ", 8 | "e": "AQAB", 9 | "use": "sig", 10 | "kid": "myoidc-keyid", 11 | "qi": "tSpNOLVW0WEgsIqn46Qu6KdJff-3hwlUWhuseR7CyHx6KBy8hXV6NDsEXpxlMvuWojNbZZTSfLUE8cs2uYFK0qp9mNbaUz-sADpT143QogCmIaDliILaBFOWDOy-E2WoonAzkxWCoRv9K785YsjsXe7AUIenSFFDx4Vohbrkijg", 12 | "dp": "DfVBexQeNf7X8CElSrH0XKLQHIO7v9f_qaCe2F7v0IlnC5UY7HljmH3rhzi9szngbhK_oU8vpc9ddmVNq1GtpBQ76i3UOrLjenpfzumJ5MGbSqQqPU01dCAt69chSig0SqBUEE1i2QRRHLeY1SWOpHcRifH7TRJZgQqlxxqIn0E", 13 | "alg": "RS256", 14 | "dq": "Hs8badU3-tZyro3F_b3PXdAst7GUCuUKKee526vivjC2T7CFblUqxzgDp6QA8Gm_fvZZCByx7DR4tSHb5eUN5-6DIkTxY0HdSmchEurNYfXf80CbqwIORmdVMjang6YnRubXo-WZKT1igEvlJBcvwPm2SvkgCP6iYPlaYbaKBU0", 15 | "n": "2D4TRgzqRdNnXgJa5HiiT7KuA6trpE7UWGTl9ZAInbf2Jk7ZgjH_Fif6vXbNphhH2U-v3jKL2xESEaR_WN4v0okw8s3B0XdIb6nA3idz_aBQ4VcYfQA6D9wGE6l9NoS1L8qxXaVk32S1UfxTC3crBbBiNazF3zYaYwcWwTYrqKqADlC2CKA4UgcmqFEO90JmP9SejpM_MryGhsebZTHbK7nsd0z9P-yORri0BPvAoZY8Scgda1TKdTtuaQTBTWPHnRfNreLHzllUF37G_ebBo_4-9Bjxj35KuOaf1VtpSXm6DHszj5bqdvubPuzS_NCWLYXtBRx4-oVRhfkHB3SRPQ" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /myoidc-server/src/test/resources/keystore.jwks: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "alg": "RS256", 5 | "d": "PvBAngE3kkTnD3yDKo3wCvHJHm20kb9a0FVGLd0s2Y0E_3H2XnZC8-2zPhN6AQTjPhohSDCew20gzm76lyOvMqRiUP2Zpaopa1d2fGvNIQSdM07yKa6EivEYxqPQxa5esoZnexgnb9fom70I8n5OQRNQikwu-az26CsHX2zWMRodzSdN5CXHvb1PV09DmH8azTYwoMElPIqmcTfxiRw2Ov5ucmXXngKRFJgvfUgKd7v4ScBX7sQoQEjWEtt7ta0WvL3Ar5E1RAW4aHxuubZ6AtloxWCf17AAKw03dfP5RDm5TDmgm2B635ecJ7fTvneFmg8W_fdMTPRfBlCGNBp3wQ", 6 | "e": "AQAB", 7 | "n": "qt6yOiI_wCoCVlGO0MySsez0VkSqhPvDl3rfabOslx35mYEO-n4ABfIT5Gn2zN-CeIcOZ5ugAXvIIRWv5H55-tzjFazi5IKkOIMCiz5__MtsdxKCqGlZu2zt-BLpqTOAPiflNPpM3RUAlxKAhnYEqNha6-allPnFQupnW_eTYoyuzuedT7dSp90ry0ZcQDimntXWeaSbrYKCj9Rr9W1jn2uTowUuXaScKXTCjAmJVnsD75JNzQfa8DweklTyWQF-Y5Ky039I0VIu-0CIGhXY48GAFe2EFb8VpNhf07DP63p138RWQ1d3KPEM9mYJVpQC68j3wzDQYSljpLf9by7TGw", 8 | "kty": "RSA", 9 | "kid": "rsa1" 10 | }, 11 | { 12 | "kty": "RSA", 13 | "kid": "myoidc-keyid", 14 | "n": "iqMKlSdSeKO9cVN_hjFA_HZ-IcEEnTloUBdPNOx5TpD3DNztyG7XTV3OUE1pMy69M7ngGmNM6w9UJ1lt6IjSvm7hHEIjkhRC4QWlYCdS9twSXXmpUIQ1eAdUFauuftuau-J-9qk-28DIlBpKyrPyjJmX0mqo4CcwjURvhI5RYp853aeNSaeqHA3oR8euKLWj66VOcSdGf9OL71IMEOGmthc9q2ZFk2iSvjNSooG0fgWgeRW9tTHoTyD8xSPY2c65hFRZwwL_kaBKuT8GoKMo3H3W485trmdh1TywJ8Z2L-yxIw91ZjTdVN75UK2E6QyshbrYi1SqUa2CPUJqAq7B6Q", 15 | "e": "AQAB", 16 | "d": "cFWB6q-NDMGobB47M5HPVYHx3AnZYkg09MieXoTKGlYuSFbvuTvO6xp6ZOkEt_tERZh0NQ2HMuQdzTCSdRwAn1uavdn9lo0iT9DSWqIigHJ70xAUmHA4HwTZJiIRZyssKtdxBw7GJywDmrXfKnY6r6B4u3-_TLmUhrMQJXloCp9GA6_PKFwHR08W8LoVREWUt7tYKybShyHzTsRuk9mZJkOmIMiGlABdAg3E_7RYs1ufIkiiCofEllpTcLeK-kiUWS9HGGOuCUrdnMG064llqccVUOmqBUr7YG8eSNHvDz3uI-mDQgESD6O3JEQwcGUIgMwyI4oDOnYTB9I9ZdAOsQ", 17 | "p": "y1lqfZF-JuDCSADDSqet-489TpyIm9yC5RNx2VN4j4t7Sbi2R3FE_Sxh95_XOsi-CvR5f-a76B4u19LCwz_v-7YELgfZUHW4Igiq-X9qZ39MzAYRzAJlTkt9SH9R64qk4rs9QrWf-eNL816tcviD8YWeMD3h2uQZSkYnNNPVliU", 18 | "q": "rohMap15I81HF-M9ksLEcOaXBagSFVZeHT2EliTSMarKe0kd5p1nH7fDd2rO9Rpu7x0IA50Tz0nIfRXsWEnNn91sZTdWrfO_-lWmu8g2n6HE2mhEnNsqVO4007UVsUnZT601dTbvrvcxrW4p6VEI9b9teVWl4NpfsEdqPnjzp3U", 19 | "dp": "a26SFEUJoQCdo-zDQG3WPVEv0phgk_esL9pWC7tNtoi6Wfh8VMJC8H7CQ1DvJN9ph-AhULFWFQvdM6jlvMHKx_EhxC_hX-DRpyltKuNmE8ftityqCl45p2O6jNK3NPnKov7JHrVWD29GcQ1UFam2C6PMLzCCYmKf-d2WWRKRhQE", 20 | "dq": "m2iaQsT9vTdoeojJpwjuymlJSKwjjgRdwUOp79fRopAlxCmTCmpWDRQgZREiP3XOGfSL0kvn-8gDUf5XeTYedp8_idEAydwlsc7arJLWsMXm92Oo1NMCmqWRPIIeUsMjUaM12q2UNwO9pGRXxX12sPxHiqcNEW7hjaHJpN8mdpE", 21 | "qi": "rjLpojc7yHt_yqYrT5M4iG2vM0lU8QDcKEEMlsMeF8g4l-f6J4F5MDCRrZ7EbdFQHP-kq6cv8LdeRpr9Hl7OHTdedeXZ5INpuZc3D_9-9_H61qegkO6VY45nzskw6NTDB4_xRF4ENX63ZU9umIEJi36sLLKOwQIyPa3V_zNFv1o" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /others/How-To-Use.txt: -------------------------------------------------------------------------------- 1 | 2 | 说明 如何部署, 如何使用 MyOIDC 3 | 4 | 5 | [myoidc-server] 6 | 7 | 1. 在MySQL中创建数据库: myoidc_server 8 | create database if not exists myoidc_server default character set utf8; 9 | 10 | 2.在数据库中执行SQL文件: myoidc-server.ddl, initial-db.ddl (others/database/ 目录) 11 | source myoidc-server.ddl 12 | source initial-db.ddl 13 | 14 | 3.修改 application.properties 中的 数据库连接信息 与 application.host 15 | 4.直接运行 MyOIDCServerApplication.java , 访问的默认端口 8086, 初始账号/密码: admin/MyOIDC-2017 16 | 5. 若使用jar方式启动,则命令为 17 | java -jar myoidc-server-{version}.jar 18 | 若使用自定义的 application.properties 文件,则命名为 19 | java -jar myoidc-server-{version}.jar --spring.config.location=application.properties 20 | 21 | 22 | 23 | 24 | [myoidc-client] 25 | 26 | 1. 修改 application.properties 中的 application.host 27 | 2. 直接运行 MyOIDCClientApplication.java , 访问的默认端口 8087 28 | 3. 若使用jar方式启动,则命令为 29 | java -jar myoidc-client-{version}.jar 30 | 若使用自定义的 application.properties 文件,则命名为 31 | java -jar myoidc-client-{version}.jar --spring.config.location=application.properties 32 | 33 | 注意:启动前最好确保 myoidc-server 已经在运行 34 | 35 | -------------------------------------------------------------------------------- /others/OpenID Connect Standard for Federation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/others/OpenID Connect Standard for Federation.pdf -------------------------------------------------------------------------------- /others/database/initial-db.ddl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -- 5 | -- Insert default user: admin/MyOIDC-2017 6 | truncate user_; 7 | INSERT INTO user_ (id, uuid, create_time, archived, version, username, password, phone, email, default_user) 8 | VALUES 9 | (21, 'wR4XwW4UdCbfOWuMCYj8lafxApKZHtgl6uls55Ij2i', now(), 0, 0, 'admin', '$2a$10$K2bdNUA09wrgKOMYGCMWeeyb7V49sZluTolXeNf0J14ArEzfn82Qi', NULL, 10 | 'admin@qc8.me', 1); 11 | 12 | -- unity/MyOIDC-2017 13 | INSERT INTO user_ (id, uuid, create_time, archived, version, username, password, phone, email, default_user) 14 | VALUES 15 | (22, 'fFVLrIx6MgVwXDhKUHE23KR3w0KqOulHjSNyf6rC04', now(), 0, 0, 'unity', '$2a$10$K2bdNUA09wrgKOMYGCMWeeyb7V49sZluTolXeNf0J14ArEzfn82Qi', NULL, 16 | 'unity@qc8.me', 1); 17 | 18 | -- mobile/MyOIDC-2017 19 | INSERT INTO user_ (id, uuid, create_time, archived, version, username, password, phone, email, default_user) 20 | VALUES 21 | (23, 'Ajlt9ZwVyGUvxrJCdKlFA4AataAVKVgH6gxYeCxD6J', now(), 0, 0, 'mobile', '$2a$10$K2bdNUA09wrgKOMYGCMWeeyb7V49sZluTolXeNf0J14ArEzfn82Qi', NULL, 22 | 'mobile@qc8.me', 1); 23 | 24 | 25 | 26 | -- user-privilege 27 | truncate user_privilege; 28 | insert into user_privilege(uuid,create_time,user_id,privilege) values ('HJvLBVf1FuOBfEi782TIfoJOxLIKFKPdCTJGlX5ulo',now(),22,'UNITY'); 29 | insert into user_privilege(uuid,create_time,user_id,privilege) values ('YAHsOvr8Z57UKeyiRPDn5IpS8HVZ87gEvlfUy8ynAW',now(),23,'MOBILE'); 30 | 31 | 32 | 33 | -- initial oauth client details test data 34 | -- 'unity-client' support browser, js(flash) visit, secret: unity 35 | -- 'mobile-client' only support mobile-device visit, secret: mobile 36 | truncate oauth_client_details; 37 | insert into oauth_client_details 38 | (client_id, resource_ids, client_secret, scope, authorized_grant_types, 39 | web_server_redirect_uri,authorities, access_token_validity, 40 | refresh_token_validity, additional_information, create_time, archived, trusted) 41 | values 42 | ('unity-client','myoidc-resource', '$2a$10$QQTKDdNfj9sPjak6c8oWaumvTsa10MxOBOV6BW3DvLWU6VrjDfDam', 'read,openid','authorization_code,refresh_token,implicit', 43 | 'http://localhost:8080/myoidc-server/unity/dashboard','ROLE_CLIENT',null, 44 | null,null, now(), 0, 0), 45 | ('mobile-client','myoidc-resource', '$2a$10$uLvpxfvm3CuUyjIvYq7a9OUmd9b3tHFKrUaMyU/jC01thrTdkBDVm', 'read,openid','password,refresh_token', 46 | null,'ROLE_CLIENT',null, 47 | null,null, now(), 0, 0); 48 | 49 | -------------------------------------------------------------------------------- /others/development-log.txt: -------------------------------------------------------------------------------- 1 | 2 | 记录开发的点点滴滴! 3 | 4 | 5 | 6 | 2020-03-14 7 | 1. keys 按要求来实现, 增加 use --ok 8 | 2. 生成的token中增加 kid, -- ok 9 | 3.openid scope时要有 access_token, id_token -- ok 10 | 4. 去掉 jpa, 用 hibernate --ok 11 | 12 | 13 | 2020-03-18 14 | 1.初始密码修改至少10位 ok 15 | 2.完成客户端RP管理 ok 16 | 3.完成用户EU管理 ok 17 | 4.API提供基础实现 ok 18 | 19 | 20 | 21 | 2020-03-19 22 | 1.API完善并进行各API具体的测试 --ok 23 | 2.考虑把 access_token不使用 id_token 格式 --取消 24 | 3. myoidc-client 准备设计与实现 25 | 4.升级 spring security oauth2, jwt 版本并测试 -- 保持不变 26 | 5.db_table_description.html检查内容 --ok 27 | 28 | 29 | 30 | 2020-03-22 31 | 1.用户EU增加 archive 功能(默认用户不能archived) ok 32 | 33 | 34 | 2020-03-25 35 | 1.注册客户端API实现 36 | 37 | -------------------------------------------------------------------------------- /others/images/Security-Token-Service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/others/images/Security-Token-Service.png -------------------------------------------------------------------------------- /others/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/others/images/favicon.ico -------------------------------------------------------------------------------- /others/images/openid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/others/images/openid.png -------------------------------------------------------------------------------- /others/key/private_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "kty": "RSA", 3 | "kid": "myoidc-keyid", 4 | "use": "sig", 5 | "alg": "RS256", 6 | "n": "n6X4_VZSQjxmSqBqmIq5ZbaLynXPP3yCOF2xE250NaYLferU8LX3xAvuNLnZkaUH-4cnr_JuSlN_7JIAwAd5oLHSuSByPcxSJ95uGniDji22s-yQ19rqZCQHLmJwg3WZpWPN-HmwxPOFNlkW_2ETjqMzS-3kGduz-IPfebwNbVFu6RglHT_V6IyaDUbSvV80AAQ7R8Y6xBvu25ZSniu3JHj2u8AtScJgiOqfsImsaCABdmUO4LtMzB1V7pafH-_puRWYCl5_uaYYPMxv-EOonPCyTlzJtC6ZeiiI4LNtxWwEamRyTS0xX8Czt3s5mRW2q6pgMZQsqlL64Df8MDuFpQ", 7 | "e": "AQAB", 8 | "d": "E92YRRXnuHxBkkmx2fdxKHn1nSTZvCGnJpJqBWv6I-7cgTemdal_AjMl2gPCUgBCJQdlZdx54t_PDEYCt-J2PQvDl-u0q4HwOyvPcZXLcPa5RFxMjb-c6QceqaPwMjuA-faYW7Hw0CEpU2D0nqSaxWYDbRBWEO2o0GTAeypuVUrZXGilOLjal68Tho8ZYbmyXsEvEdqCob_iUe6q4c2x0amMmn2ot3bKKqdjbVXMjVfEqHHMPMdnVmrr_yfTUlXN3ZT4Ypp7wDrAVs7pfbvrCKWzLQYlbYNjZeBoKNcGabAA7WuNGxWvi3971gLSdYwRw4TngOweIhVW8kxiiA77QQ", 9 | "p": "2R_SdLqd7d7hVJTAVY4Twx8j7VQq6-TTMVcyD_YLeBGvlkngpSz7NSQu1LTYGEHa_CzeCOFmKgtuLZ84zyS_wUxgF3AH0VD-xNZSAaHfzWXAwLmezYzGBXXF0ho8qpbf2aTNZZx2n5z0cb0loitAfmfrsd9XU226nXpPAgV-gTE", 10 | "q": "vDup5zcW9NwxVs9-C-W1uwL7TpQIKNk9oBvbfgD6XkwIn3JmCfny2Nm-paK45YM169JhnUml7z6On2Bq81rNtPwkqWTp9d2SfsQkuNddtfeYi_FulLqMLeQvCr2TAdFE-4uYKcU_-5u21oomnVm5vgGs8aFzd_J-57i-GfPxjrU", 11 | "dp": "UwpZqm1JQ5WvpnKx0MbjBghd7EH5nHjK0R8hNXuLzWMuPZOJyIKYnS12f8GeuEBPqYzbapgSQ9hVTjuMNaU_dYVpZu1hAAwzNEMn4BnyB5N4Ef2sH79MaQAvJXkFZNUJTis6pzcdI1SbJPkLcKeMJgxG16OsuWrJKbuChiplxLE", 12 | "dq": "aQYJGD6-ikRJKxx-QXkbWoqhWQhzPQdowOqKHtXA29gkf4I-uJZDDwb-vj_6VeRNs5Qgbrfm44PN49LSGZGycKa2deUePNYxpJUfwBo56QuKi5pbjpQ_HmPQc3eujDcM_CS486Vgu6v36eAPB4BGiGM68V6ZpHUipXuIZcacInk", 13 | "qi": "bvay2Ej4FIYrFpD0zW-xEpHoPxXmNJRyR4rL4SGVq-ILghfVqfTQszI2MUnpubcUAUsqYYZUvvemfust35eYiSaYWzUDGsjmUWhZDD8VTKEyxbWwya7GztarLMud2LGn76a41zyStU46g84G1ZPNcZTK_1DIR0_BpayN44jj3kk" 14 | } -------------------------------------------------------------------------------- /others/key/public_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "kty": "RSA", 3 | "kid": "myoidc-keyid", 4 | "use": "sig", 5 | "alg": "RS256", 6 | "n": "n6X4_VZSQjxmSqBqmIq5ZbaLynXPP3yCOF2xE250NaYLferU8LX3xAvuNLnZkaUH-4cnr_JuSlN_7JIAwAd5oLHSuSByPcxSJ95uGniDji22s-yQ19rqZCQHLmJwg3WZpWPN-HmwxPOFNlkW_2ETjqMzS-3kGduz-IPfebwNbVFu6RglHT_V6IyaDUbSvV80AAQ7R8Y6xBvu25ZSniu3JHj2u8AtScJgiOqfsImsaCABdmUO4LtMzB1V7pafH-_puRWYCl5_uaYYPMxv-EOonPCyTlzJtC6ZeiiI4LNtxWwEamRyTS0xX8Czt3s5mRW2q6pgMZQsqlL64Df8MDuFpQ", 7 | "e": "AQAB" 8 | } -------------------------------------------------------------------------------- /others/springboot/myoidc.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/others/springboot/myoidc.zip -------------------------------------------------------------------------------- /others/springboot/spring-boot-reference(2.0.0).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/MyOIDC/e477f9651bb00bc3adf7787ce64907a281b7e871/others/springboot/spring-boot-reference(2.0.0).pdf -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | myoidc 8 | MyOIDC 9 | 1.1.1 10 | ${project.artifactId} 11 | pom 12 | OpenID Connect Implements 13 | 14 | 15 | UTF-8 16 | 17 | 18 | 19 | 20 | myoidc-server 21 | myoidc-client 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-compiler-plugin 31 | 2.3.2 32 | 33 | utf-8 34 | 1.8 35 | 1.8 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | --------------------------------------------------------------------------------