├── .gitignore ├── README.md ├── bin ├── main │ ├── application.properties │ ├── com │ │ └── sinol │ │ │ └── oauth │ │ │ ├── config │ │ │ ├── OAuth2AuthorizationServerConfig.class │ │ │ ├── ServerWebSecurityConfig.class │ │ │ └── SinolsOauthApplication.class │ │ │ ├── model │ │ │ ├── Authority.class │ │ │ ├── OauthAccessToken.class │ │ │ ├── OauthClientDetails.class │ │ │ ├── OauthClientToken.class │ │ │ ├── OauthCode.class │ │ │ ├── OauthRefreshToken.class │ │ │ ├── User.class │ │ │ ├── UserAuthority.class │ │ │ └── dto │ │ │ │ ├── CustomGrantedAuthority.class │ │ │ │ └── CustomUserDetails.class │ │ │ ├── persistence │ │ │ └── UserDao.class │ │ │ └── service │ │ │ └── UserDetailsServiceImpl.class │ └── import.sql └── test │ └── com │ └── lionrocks │ └── oauth │ └── lionrocksoauth │ └── LionrocksOauthApplicationTests.class ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main ├── java │ └── com │ │ └── sinol │ │ └── oauth │ │ ├── config │ │ ├── OAuth2AuthorizationServerConfig.java │ │ ├── ServerWebSecurityConfig.java │ │ └── SinolsOauthApplication.java │ │ ├── model │ │ ├── Authority.java │ │ ├── OauthAccessToken.java │ │ ├── OauthClientDetails.java │ │ ├── OauthClientToken.java │ │ ├── OauthCode.java │ │ ├── OauthRefreshToken.java │ │ ├── User.java │ │ ├── UserAuthority.java │ │ └── dto │ │ │ ├── CustomGrantedAuthority.java │ │ │ └── CustomUserDetails.java │ │ ├── persistence │ │ └── UserDao.java │ │ └── service │ │ └── UserDetailsServiceImpl.java └── resources │ ├── application.properties │ └── import.sql └── test └── java └── com └── lionrocks └── oauth └── lionrocksoauth └── LionrocksOauthApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | /bin 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oAuth2 2 | Implements spring oauth2 with JWT token store 3 | 4 | The required spring oauth data structure is created as JPA entities. 5 | 6 | How to run 7 | ========================================================================= 8 | Simply clone and update database cofig. Then run SinolsOauthApplication. 9 | 10 | It will create tables and insert sample data to test the Oauth2 server 11 | -------------------------------------------------------------------------------- /bin/main/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8095 2 | 3 | # Dev 4 | spring.datasource.url = jdbc:mysql://localhost:3306/oauth2_jwt?createDatabaseIfNotExist=true&useUnicode=yes&characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=UTC 5 | spring.datasource.username = root 6 | spring.datasource.password = admin 7 | 8 | # Naming strategy 9 | spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy 10 | 11 | # Use spring.jpa.properties.* for Hibernate native properties (the prefix is 12 | # stripped before adding them to the entity manager) 13 | 14 | # The SQL dialect makes Hibernate generate better SQL for the chosen database 15 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect 16 | 17 | spring.jpa.properties.hibernate.connection.characterEncoding = utf-8 18 | spring.jpa.properties.hibernate.connection.CharSet = utf-8 19 | spring.jpa.properties.hibernate.connection.useUnicode = true 20 | 21 | # Show or not log for each sql query 22 | spring.jpa.show-sql = true 23 | spring.jpa.hibernate.ddl-auto=create -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/config/OAuth2AuthorizationServerConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/config/OAuth2AuthorizationServerConfig.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/config/ServerWebSecurityConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/config/ServerWebSecurityConfig.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/config/SinolsOauthApplication.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/config/SinolsOauthApplication.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/Authority.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/Authority.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/OauthAccessToken.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/OauthAccessToken.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/OauthClientDetails.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/OauthClientDetails.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/OauthClientToken.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/OauthClientToken.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/OauthCode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/OauthCode.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/OauthRefreshToken.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/OauthRefreshToken.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/User.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/UserAuthority.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/UserAuthority.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/dto/CustomGrantedAuthority.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/dto/CustomGrantedAuthority.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/model/dto/CustomUserDetails.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/model/dto/CustomUserDetails.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/persistence/UserDao.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/persistence/UserDao.class -------------------------------------------------------------------------------- /bin/main/com/sinol/oauth/service/UserDetailsServiceImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/main/com/sinol/oauth/service/UserDetailsServiceImpl.class -------------------------------------------------------------------------------- /bin/main/import.sql: -------------------------------------------------------------------------------- 1 | insert ignore into `oauth_client_details`(`client_id`,`resource_ids`,`client_secret`,`scope`,`authorized_grant_types`,`web_server_redirect_uri`,`authorities`,`access_token_validity`,`refresh_token_validity`,`additional_information`,`autoapprove`) values ('oauth2-jwt-client','resource-server-rest-api','$2a$08$qvrzQZ7jJ7oy2p/msL4M0.l83Cd0jNsX6AJUitbgRXGzge4j035ha','read','password,authorization_code,refresh_token,client_credentials,implicit','https://www.getpostman.com/oauth2/callback','USER',10800,2592000,null,null); 2 | insert ignore into `authority`(`name`) values ('ADMIN'); 3 | insert ignore into `user`(`account_expired`,`account_locked`,`credentials_expired`,`enabled`,`password`,`user_name`) values (0,0,0,1,'$2a$08$qvrzQZ7jJ7oy2p/msL4M0.l83Cd0jNsX6AJUitbgRXGzge4j035ha','admin'); 4 | insert ignore into `user_authority`(`authority_id`,`user_id`) values (1,1); -------------------------------------------------------------------------------- /bin/test/com/lionrocks/oauth/lionrocksoauth/LionrocksOauthApplicationTests.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/bin/test/com/lionrocks/oauth/lionrocksoauth/LionrocksOauthApplicationTests.class -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.1.1.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | } 11 | } 12 | 13 | apply plugin: 'java' 14 | apply plugin: 'eclipse' 15 | apply plugin: 'org.springframework.boot' 16 | apply plugin: 'io.spring.dependency-management' 17 | 18 | group = 'com.lionrocks.oauth' 19 | version = '0.0.1-SNAPSHOT' 20 | sourceCompatibility = 10 21 | 22 | repositories { 23 | mavenCentral() 24 | maven { url "https://repo.spring.io/milestone" } 25 | } 26 | 27 | ext['springCloudVersion'] = 'Greenwich.RC1' 28 | 29 | dependencies { 30 | implementation('org.springframework.boot:spring-boot-starter-data-jpa') 31 | implementation('org.springframework.cloud:spring-cloud-starter-oauth2') 32 | implementation('org.springframework.boot:spring-boot-starter-security') 33 | testImplementation('org.springframework.boot:spring-boot-starter-test') 34 | compile('mysql:mysql-connector-java:8.0.11') 35 | compile('org.springframework.security:spring-security-jwt:1.0.9.RELEASE') 36 | compile('com.sun.xml.bind:jaxb-impl:2.1.2') 37 | } 38 | 39 | dependencyManagement { 40 | imports { 41 | mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderSinol/oAuth2/5182830a255892cd0bac14be4a412894c34be549/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'lionrocks-oauth' 2 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/config/OAuth2AuthorizationServerConfig.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.config; 2 | 3 | import javax.sql.DataSource; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Import; 10 | import org.springframework.context.annotation.Primary; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 | import org.springframework.security.crypto.password.PasswordEncoder; 15 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 16 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 17 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 18 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 19 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 20 | import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; 21 | import org.springframework.security.oauth2.provider.token.DefaultTokenServices; 22 | import org.springframework.security.oauth2.provider.token.TokenStore; 23 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 24 | import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; 25 | 26 | @Configuration 27 | @EnableAuthorizationServer 28 | @Import(ServerWebSecurityConfig.class) 29 | public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 30 | 31 | @Autowired 32 | private AuthenticationManager authenticationManager; 33 | 34 | @Autowired 35 | @Qualifier("dataSource") 36 | private DataSource dataSource; 37 | 38 | @Autowired 39 | private UserDetailsService userDetailsService; 40 | 41 | @Override 42 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 43 | endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter()).authenticationManager(authenticationManager).userDetailsService(userDetailsService); 44 | } 45 | 46 | @Override 47 | public void configure(AuthorizationServerSecurityConfigurer oauthServer) { 48 | oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("permitAll()"); 49 | } 50 | 51 | @Bean 52 | public TokenStore tokenStore() { 53 | return new JwtTokenStore(accessTokenConverter()); 54 | } 55 | 56 | @Override 57 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 58 | JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource); 59 | clients.withClientDetails(jdbcClientDetailsService); 60 | } 61 | 62 | @Bean 63 | public JwtAccessTokenConverter accessTokenConverter() { 64 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 65 | converter.setSigningKey("123"); 66 | return converter; 67 | } 68 | 69 | @Bean 70 | @Primary 71 | public DefaultTokenServices tokenServices() { 72 | DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 73 | defaultTokenServices.setTokenStore(tokenStore()); 74 | defaultTokenServices.setSupportRefreshToken(true); 75 | return defaultTokenServices; 76 | } 77 | 78 | @Bean 79 | public PasswordEncoder userPasswordEncoder() { 80 | return new BCryptPasswordEncoder(4); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/config/ServerWebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.authentication.AuthenticationManager; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 | 10 | @Configuration 11 | @EnableWebSecurity 12 | public class ServerWebSecurityConfig extends WebSecurityConfigurerAdapter { 13 | 14 | @Override 15 | @Bean 16 | public AuthenticationManager authenticationManagerBean() throws Exception { 17 | return super.authenticationManagerBean(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/config/SinolsOauthApplication.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.config; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 8 | 9 | @SpringBootApplication 10 | @EntityScan("com.sinol") 11 | @EnableJpaRepositories("com.sinol") 12 | @ComponentScan("com.sinol") 13 | public class SinolsOauthApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(SinolsOauthApplication.class, args); 17 | } 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/Authority.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | 4 | import javax.persistence.Column; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.Table; 10 | import javax.persistence.UniqueConstraint; 11 | 12 | @Entity 13 | @Table(name="authority", uniqueConstraints = @UniqueConstraint(columnNames = {"name"}, name="AUTHORITY_UNIQUE_NAME")) 14 | public class Authority { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | @Column(name = "ID", columnDefinition = "bigint unsigned") 19 | private Integer id; 20 | 21 | @Column(length=20) 22 | private String name; 23 | 24 | public Integer getId() { 25 | return id; 26 | } 27 | 28 | public void setId(Integer id) { 29 | this.id = id; 30 | } 31 | 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/OauthAccessToken.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.Lob; 9 | import javax.persistence.Table; 10 | 11 | @Entity 12 | @Table(name="oauth_access_token") 13 | public class OauthAccessToken { 14 | 15 | @Id 16 | @GeneratedValue(strategy = GenerationType.IDENTITY) 17 | @Column(name = "ID", columnDefinition = "bigint unsigned") 18 | private Integer id; 19 | 20 | @Column(name="token_id") 21 | private String tokenId; 22 | 23 | @Lob 24 | @Column(name="token", columnDefinition = "mediumblob") 25 | private byte[] token; 26 | 27 | @Column(name="authentication_id") 28 | private String authenticationId; 29 | 30 | @Column(name="user_name") 31 | private String userName; 32 | 33 | @Column(name="client_id") 34 | private String clientId; 35 | 36 | @Lob 37 | @Column(name="authentication", columnDefinition = "mediumblob") 38 | private byte[] authentication; 39 | 40 | @Column(name="refresh_token") 41 | private String refreshToken; 42 | 43 | public Integer getId() { 44 | return id; 45 | } 46 | 47 | public void setId(Integer id) { 48 | this.id = id; 49 | } 50 | 51 | public String getTokenId() { 52 | return tokenId; 53 | } 54 | 55 | public void setTokenId(String tokenId) { 56 | this.tokenId = tokenId; 57 | } 58 | 59 | public byte[] getToken() { 60 | return token; 61 | } 62 | 63 | public void setToken(byte[] token) { 64 | this.token = token; 65 | } 66 | 67 | public String getAuthenticationId() { 68 | return authenticationId; 69 | } 70 | 71 | public void setAuthenticationId(String authenticationId) { 72 | this.authenticationId = authenticationId; 73 | } 74 | 75 | public String getUserName() { 76 | return userName; 77 | } 78 | 79 | public void setUserName(String userName) { 80 | this.userName = userName; 81 | } 82 | 83 | public String getClientId() { 84 | return clientId; 85 | } 86 | 87 | public void setClientId(String clientId) { 88 | this.clientId = clientId; 89 | } 90 | 91 | public byte[] getAuthentication() { 92 | return authentication; 93 | } 94 | 95 | public void setAuthentication(byte[] authentication) { 96 | this.authentication = authentication; 97 | } 98 | 99 | public String getRefreshToken() { 100 | return refreshToken; 101 | } 102 | 103 | public void setRefreshToken(String refreshToken) { 104 | this.refreshToken = refreshToken; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/OauthClientDetails.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.Table; 11 | import javax.persistence.Transient; 12 | 13 | @Entity 14 | @Table(name="oauth_client_details") 15 | public class OauthClientDetails { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | @Column(name = "ID", columnDefinition = "bigint unsigned") 20 | private Integer id; 21 | 22 | @Column(name="client_id") 23 | private String clientId; 24 | 25 | @Column(name="client_name") 26 | private String clientName; 27 | 28 | @Column(name="resource_ids") 29 | private String resourceIds; 30 | 31 | @Column(name="client_secret") 32 | private String clientSecret; 33 | 34 | @Column(name="scope") 35 | private String scope; 36 | 37 | @Column(name="authorized_grant_types") 38 | private String authorizedGrantTypes; 39 | 40 | @Column(name="web_server_redirect_uri") 41 | private String webServerRedirectUri; 42 | 43 | @Column(name="authorities") 44 | private String authorities; 45 | 46 | @Column(name="access_token_validity", length=11) 47 | private Integer accessTokenValidity; 48 | 49 | @Column(name="refresh_token_validity", length=11) 50 | private Integer refreshTokenValidity; 51 | 52 | @Column(name="additional_information", length=4096) 53 | private String additionalInformation; 54 | 55 | @Column(name="autoapprove", columnDefinition = "TINYINT(4)") 56 | private Integer autoapprove; 57 | 58 | @Column(name="uuid") 59 | private String uuid; 60 | 61 | @Column 62 | private Date created; 63 | 64 | @Column(columnDefinition ="boolean default true") 65 | private Boolean enabled; 66 | 67 | @Transient 68 | private String[] scopes; 69 | 70 | @Transient 71 | private String[] grantTypes; 72 | 73 | @Transient 74 | private String ownerEmail; 75 | 76 | public Integer getId() { 77 | return id; 78 | } 79 | 80 | public void setId(Integer id) { 81 | this.id = id; 82 | } 83 | 84 | public String getClientId() { 85 | return clientId; 86 | } 87 | 88 | public void setClientId(String clientId) { 89 | this.clientId = clientId; 90 | } 91 | 92 | public String getClientName() { 93 | return clientName; 94 | } 95 | 96 | public void setClientName(String clientName) { 97 | this.clientName = clientName; 98 | } 99 | 100 | public String getResourceIds() { 101 | return resourceIds; 102 | } 103 | 104 | public void setResourceIds(String resourceIds) { 105 | this.resourceIds = resourceIds; 106 | } 107 | 108 | public String getClientSecret() { 109 | return clientSecret; 110 | } 111 | 112 | public void setClientSecret(String clientSecret) { 113 | this.clientSecret = clientSecret; 114 | } 115 | 116 | public String getScope() { 117 | return scope; 118 | } 119 | 120 | public void setScope(String scope) { 121 | this.scope = scope; 122 | } 123 | 124 | public String getAuthorizedGrantTypes() { 125 | return authorizedGrantTypes; 126 | } 127 | 128 | public void setAuthorizedGrantTypes(String authorizedGrantTypes) { 129 | this.authorizedGrantTypes = authorizedGrantTypes; 130 | } 131 | 132 | public String getWebServerRedirectUri() { 133 | return webServerRedirectUri; 134 | } 135 | 136 | public void setWebServerRedirectUri(String webServerRedirectUri) { 137 | this.webServerRedirectUri = webServerRedirectUri; 138 | } 139 | 140 | public String getAuthorities() { 141 | return authorities; 142 | } 143 | 144 | public void setAuthorities(String authorities) { 145 | this.authorities = authorities; 146 | } 147 | 148 | public Integer getAccessTokenValidity() { 149 | return accessTokenValidity; 150 | } 151 | 152 | public void setAccessTokenValidity(Integer accessTokenValidity) { 153 | this.accessTokenValidity = accessTokenValidity; 154 | } 155 | 156 | public Integer getRefreshTokenValidity() { 157 | return refreshTokenValidity; 158 | } 159 | 160 | public void setRefreshTokenValidity(Integer refreshTokenValidity) { 161 | this.refreshTokenValidity = refreshTokenValidity; 162 | } 163 | 164 | public String getAdditionalInformation() { 165 | return additionalInformation; 166 | } 167 | 168 | public void setAdditionalInformation(String additionalInformation) { 169 | this.additionalInformation = additionalInformation; 170 | } 171 | 172 | public Integer getAutoapprove() { 173 | return autoapprove; 174 | } 175 | 176 | public void setAutoapprove(Integer autoapprove) { 177 | this.autoapprove = autoapprove; 178 | } 179 | 180 | public String getUuid() { 181 | return uuid; 182 | } 183 | 184 | public void setUuid(String uuid) { 185 | this.uuid = uuid; 186 | } 187 | 188 | public Date getCreated() { 189 | return created; 190 | } 191 | 192 | public void setCreated(Date created) { 193 | this.created = created; 194 | } 195 | 196 | public Boolean getEnabled() { 197 | return enabled; 198 | } 199 | 200 | public void setEnabled(Boolean enabled) { 201 | this.enabled = enabled; 202 | } 203 | 204 | public String[] getScopes() { 205 | return scopes; 206 | } 207 | 208 | public void setScopes(String[] scopes) { 209 | this.scopes = scopes; 210 | } 211 | 212 | public String[] getGrantTypes() { 213 | return grantTypes; 214 | } 215 | 216 | public void setGrantTypes(String[] grantTypes) { 217 | this.grantTypes = grantTypes; 218 | } 219 | 220 | public String getOwnerEmail() { 221 | return ownerEmail; 222 | } 223 | 224 | public void setOwnerEmail(String ownerEmail) { 225 | this.ownerEmail = ownerEmail; 226 | } 227 | 228 | 229 | } 230 | 231 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/OauthClientToken.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.Lob; 9 | import javax.persistence.Table; 10 | 11 | @Entity 12 | @Table(name="oauth_client_token") 13 | public class OauthClientToken { 14 | 15 | @Id 16 | @GeneratedValue(strategy = GenerationType.IDENTITY) 17 | @Column(name = "ID", columnDefinition = "bigint unsigned") 18 | private Integer id; 19 | 20 | @Column(name="token_id") 21 | private String tokenId; 22 | 23 | @Lob 24 | @Column(name="token", columnDefinition = "mediumblob") 25 | private byte[] token; 26 | 27 | @Column(name="authentication_id") 28 | private String authenticationId; 29 | 30 | @Column(name="user_name") 31 | private String userName; 32 | 33 | @Column(name="client_id") 34 | private String clientId; 35 | 36 | public Integer getId() { 37 | return id; 38 | } 39 | 40 | public void setId(Integer id) { 41 | this.id = id; 42 | } 43 | 44 | public String getTokenId() { 45 | return tokenId; 46 | } 47 | 48 | public void setTokenId(String tokenId) { 49 | this.tokenId = tokenId; 50 | } 51 | 52 | public byte[] getToken() { 53 | return token; 54 | } 55 | 56 | public void setToken(byte[] token) { 57 | this.token = token; 58 | } 59 | 60 | public String getAuthenticationId() { 61 | return authenticationId; 62 | } 63 | 64 | public void setAuthenticationId(String authenticationId) { 65 | this.authenticationId = authenticationId; 66 | } 67 | 68 | public String getUserName() { 69 | return userName; 70 | } 71 | 72 | public void setUserName(String userName) { 73 | this.userName = userName; 74 | } 75 | 76 | public String getClientId() { 77 | return clientId; 78 | } 79 | 80 | public void setClientId(String clientId) { 81 | this.clientId = clientId; 82 | } 83 | 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/OauthCode.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.Lob; 9 | import javax.persistence.Table; 10 | 11 | @Entity 12 | @Table(name="oauth_code") 13 | public class OauthCode { 14 | 15 | @Id 16 | @GeneratedValue(strategy = GenerationType.IDENTITY) 17 | @Column(name = "ID", columnDefinition = "bigint unsigned") 18 | private Integer id; 19 | 20 | @Column(name="code") 21 | private String code; 22 | 23 | @Lob 24 | @Column(name="authentication", columnDefinition = "mediumblob") 25 | private byte[] authentication; 26 | 27 | public Integer getId() { 28 | return id; 29 | } 30 | 31 | public void setId(Integer id) { 32 | this.id = id; 33 | } 34 | 35 | public String getCode() { 36 | return code; 37 | } 38 | 39 | public void setCode(String code) { 40 | this.code = code; 41 | } 42 | 43 | public byte[] getAuthentication() { 44 | return authentication; 45 | } 46 | 47 | public void setAuthentication(byte[] authentication) { 48 | this.authentication = authentication; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/OauthRefreshToken.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | 4 | import javax.persistence.Column; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.Lob; 10 | import javax.persistence.Table; 11 | 12 | @Entity 13 | @Table(name="oauth_refresh_token") 14 | public class OauthRefreshToken { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.IDENTITY) 18 | @Column(name = "ID", columnDefinition = "bigint unsigned") 19 | private Integer id; 20 | 21 | @Column(name="token_id") 22 | private String tokenId; 23 | 24 | @Lob 25 | @Column(name="token", columnDefinition = "mediumblob") 26 | private byte[] token; 27 | 28 | @Lob 29 | @Column(name="authentication", columnDefinition = "mediumblob") 30 | private byte[] authentication; 31 | 32 | public Integer getId() { 33 | return id; 34 | } 35 | 36 | public void setId(Integer id) { 37 | this.id = id; 38 | } 39 | 40 | public String getTokenId() { 41 | return tokenId; 42 | } 43 | 44 | public void setTokenId(String tokenId) { 45 | this.tokenId = tokenId; 46 | } 47 | 48 | public byte[] getToken() { 49 | return token; 50 | } 51 | 52 | public void setToken(byte[] token) { 53 | this.token = token; 54 | } 55 | 56 | public byte[] getAuthentication() { 57 | return authentication; 58 | } 59 | 60 | public void setAuthentication(byte[] authentication) { 61 | this.authentication = authentication; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/User.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | import javax.persistence.CascadeType; 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.FetchType; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.GenerationType; 13 | import javax.persistence.Id; 14 | import javax.persistence.OneToMany; 15 | import javax.persistence.Table; 16 | import javax.persistence.UniqueConstraint; 17 | 18 | @Entity 19 | @Table(name="user", uniqueConstraints = @UniqueConstraint(columnNames = {"userName"}, name="USER_UNIQUE_USERNAME")) 20 | public class User { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | @Column(name = "ID", columnDefinition = "bigint unsigned") 25 | private Integer id; 26 | 27 | @Column(length=50) 28 | private String userName; 29 | 30 | @Column 31 | private String password; 32 | 33 | @Column 34 | private Boolean accountExpired; 35 | 36 | @Column 37 | private Boolean accountLocked; 38 | 39 | @Column 40 | private Boolean credentialsExpired; 41 | 42 | @Column 43 | private Boolean enabled; 44 | 45 | @OneToMany(mappedBy = "user", targetEntity = UserAuthority.class, cascade = { 46 | CascadeType.ALL }, orphanRemoval = true, fetch = FetchType.EAGER) 47 | private Set userAuthorities = new HashSet(); 48 | 49 | public Integer getId() { 50 | return id; 51 | } 52 | 53 | public void setId(Integer id) { 54 | this.id = id; 55 | } 56 | 57 | public String getUserName() { 58 | return userName; 59 | } 60 | 61 | public void setUserName(String userName) { 62 | this.userName = userName; 63 | } 64 | 65 | public String getPassword() { 66 | return password; 67 | } 68 | 69 | public void setPassword(String password) { 70 | this.password = password; 71 | } 72 | 73 | public Boolean getAccountExpired() { 74 | return accountExpired; 75 | } 76 | 77 | public void setAccountExpired(Boolean accountExpired) { 78 | this.accountExpired = accountExpired; 79 | } 80 | 81 | public Boolean getAccountLocked() { 82 | return accountLocked; 83 | } 84 | 85 | public void setAccountLocked(Boolean accountLocked) { 86 | this.accountLocked = accountLocked; 87 | } 88 | 89 | public Boolean getCredentialsExpired() { 90 | return credentialsExpired; 91 | } 92 | 93 | public void setCredentialsExpired(Boolean credentialsExpired) { 94 | this.credentialsExpired = credentialsExpired; 95 | } 96 | 97 | public Boolean getEnabled() { 98 | return enabled; 99 | } 100 | 101 | public void setEnabled(Boolean enabled) { 102 | this.enabled = enabled; 103 | } 104 | 105 | public Set getUserAuthorities() { 106 | return userAuthorities; 107 | } 108 | 109 | public void setUserAuthorities(Set userAuthorities) { 110 | this.userAuthorities = userAuthorities; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/UserAuthority.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model; 2 | 3 | import javax.persistence.*; 4 | 5 | @Entity 6 | @Table(name="user_authority", uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "authority_id"}, name="USER_AUTHORITY_UNIQUE_USER_ID_AND_AUTHORITY_ID")) 7 | public class UserAuthority { 8 | 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.IDENTITY) 11 | @Column(name = "ID", columnDefinition = "bigint unsigned") 12 | private Integer id; 13 | 14 | @ManyToOne(cascade = CascadeType.ALL) 15 | @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_USER_AUTHORITY_USER_ID")) 16 | private User user; 17 | 18 | @ManyToOne(cascade = CascadeType.ALL) 19 | @JoinColumn(name = "AUTHORITY_ID", foreignKey = @ForeignKey(name = "FK_USER_AUTHORITY_AUTHORITY_ID")) 20 | private Authority authority; 21 | 22 | public Integer getId() { 23 | return id; 24 | } 25 | 26 | public void setId(Integer id) { 27 | this.id = id; 28 | } 29 | 30 | public User getUser() { 31 | return user; 32 | } 33 | 34 | public void setUser(User user) { 35 | this.user = user; 36 | } 37 | 38 | public Authority getAuthority() { 39 | return authority; 40 | } 41 | 42 | public void setAuthority(Authority authority) { 43 | this.authority = authority; 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/dto/CustomGrantedAuthority.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.springframework.security.core.GrantedAuthority; 6 | 7 | public class CustomGrantedAuthority implements GrantedAuthority, Serializable { 8 | 9 | private String name; 10 | 11 | public CustomGrantedAuthority(String name) { 12 | this.name = name; 13 | } 14 | 15 | @Override 16 | public String getAuthority() { 17 | return name; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/model/dto/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.model.dto; 2 | 3 | import java.util.Collection; 4 | import java.util.Set; 5 | 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | 9 | @SuppressWarnings("serial") 10 | public class CustomUserDetails implements UserDetails { 11 | 12 | private String userName; 13 | 14 | private String password; 15 | 16 | private Set grantedAuthorities; 17 | 18 | public CustomUserDetails() { 19 | 20 | } 21 | 22 | @Override 23 | public Collection getAuthorities() { 24 | return grantedAuthorities; 25 | } 26 | 27 | @Override 28 | public String getPassword() { 29 | return password; 30 | } 31 | 32 | @Override 33 | public String getUsername() { 34 | return userName; 35 | } 36 | 37 | @Override 38 | public boolean isAccountNonExpired() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public boolean isAccountNonLocked() { 44 | return true; 45 | } 46 | 47 | @Override 48 | public boolean isCredentialsNonExpired() { 49 | return true; 50 | } 51 | 52 | @Override 53 | public boolean isEnabled() { 54 | return true; 55 | } 56 | 57 | public void setUserName(String userName) { 58 | this.userName = userName; 59 | } 60 | 61 | public Set getGrantedAuthorities() { 62 | return grantedAuthorities; 63 | } 64 | 65 | public void setGrantedAuthorities(Set grantedAuthorities) { 66 | this.grantedAuthorities = grantedAuthorities; 67 | } 68 | 69 | public void setPassword(String password) { 70 | this.password = password; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/persistence/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.persistence; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.data.repository.query.Param; 6 | 7 | import com.sinol.oauth.model.User; 8 | 9 | public interface UserDao extends JpaRepository { 10 | 11 | @Query("SELECT DISTINCT u FROM User u WHERE u.userName = :username") 12 | User findByUsername(@Param("username") String username); 13 | } -------------------------------------------------------------------------------- /src/main/java/com/sinol/oauth/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sinol.oauth.service; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import javax.transaction.Transactional; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 13 | import org.springframework.stereotype.Service; 14 | 15 | import com.sinol.oauth.model.User; 16 | import com.sinol.oauth.model.UserAuthority; 17 | import com.sinol.oauth.model.dto.CustomGrantedAuthority; 18 | import com.sinol.oauth.model.dto.CustomUserDetails; 19 | import com.sinol.oauth.persistence.UserDao; 20 | 21 | @Service 22 | @Transactional 23 | public class UserDetailsServiceImpl implements UserDetailsService { 24 | 25 | @Autowired 26 | private UserDao userDao; 27 | 28 | @Override 29 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 30 | User user = userDao.findByUsername(username); 31 | if (user != null) { 32 | CustomUserDetails customUserDetails = new CustomUserDetails(); 33 | customUserDetails.setUserName(user.getUserName()); 34 | customUserDetails.setPassword(user.getPassword()); 35 | Set authorities = new HashSet(); 36 | for (UserAuthority authority : user.getUserAuthorities()) { 37 | authorities.add(new CustomGrantedAuthority(authority.getAuthority().getName())); 38 | } 39 | customUserDetails.setGrantedAuthorities(authorities); 40 | return customUserDetails; 41 | } 42 | throw new UsernameNotFoundException(username); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8095 2 | 3 | # Dev 4 | spring.datasource.url = jdbc:mysql://localhost:3306/oauth2_jwt?createDatabaseIfNotExist=true&useUnicode=yes&characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=UTC 5 | spring.datasource.username = root 6 | spring.datasource.password = admin 7 | 8 | # Naming strategy 9 | spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy 10 | 11 | # Use spring.jpa.properties.* for Hibernate native properties (the prefix is 12 | # stripped before adding them to the entity manager) 13 | 14 | # The SQL dialect makes Hibernate generate better SQL for the chosen database 15 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect 16 | 17 | spring.jpa.properties.hibernate.connection.characterEncoding = utf-8 18 | spring.jpa.properties.hibernate.connection.CharSet = utf-8 19 | spring.jpa.properties.hibernate.connection.useUnicode = true 20 | 21 | # Show or not log for each sql query 22 | spring.jpa.show-sql = true 23 | spring.jpa.hibernate.ddl-auto=create -------------------------------------------------------------------------------- /src/main/resources/import.sql: -------------------------------------------------------------------------------- 1 | insert ignore into `oauth_client_details`(`client_id`,`resource_ids`,`client_secret`,`scope`,`authorized_grant_types`,`web_server_redirect_uri`,`authorities`,`access_token_validity`,`refresh_token_validity`,`additional_information`,`autoapprove`) values ('oauth2-jwt-client','resource-server-rest-api','$2a$08$qvrzQZ7jJ7oy2p/msL4M0.l83Cd0jNsX6AJUitbgRXGzge4j035ha','read','password,authorization_code,refresh_token,client_credentials,implicit','https://www.getpostman.com/oauth2/callback','USER',10800,2592000,null,null); 2 | insert ignore into `authority`(`name`) values ('ADMIN'); 3 | insert ignore into `user`(`account_expired`,`account_locked`,`credentials_expired`,`enabled`,`password`,`user_name`) values (0,0,0,1,'$2a$08$qvrzQZ7jJ7oy2p/msL4M0.l83Cd0jNsX6AJUitbgRXGzge4j035ha','admin'); 4 | insert ignore into `user_authority`(`authority_id`,`user_id`) values (1,1); -------------------------------------------------------------------------------- /src/test/java/com/lionrocks/oauth/lionrocksoauth/LionrocksOauthApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.lionrocks.oauth.lionrocksoauth; 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.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class LionrocksOauthApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | 18 | --------------------------------------------------------------------------------