├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── arjun │ │ └── gateway │ │ ├── GatewayApplication.java │ │ ├── bean │ │ └── auth │ │ │ ├── AuthResponse.java │ │ │ ├── JwtToken.java │ │ │ ├── LoginRequest.java │ │ │ ├── MongoUserDetails.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ ├── controller │ │ └── LoginController.java │ │ ├── exception │ │ ├── CustomException.java │ │ └── GlobalExceptionHandlerController.java │ │ ├── repository │ │ ├── JwtTokenRepository.java │ │ └── UserRepository.java │ │ ├── security │ │ ├── JwtTokenFilter.java │ │ ├── JwtTokenFilterConfigurer.java │ │ ├── JwtTokenProvider.java │ │ ├── UserService.java │ │ └── WebSecurityConfig.java │ │ └── service │ │ ├── ILoginService.java │ │ └── serviceimpl │ │ └── LoginService.java └── resources │ └── application.properties └── test └── java └── com └── arjun └── gateway └── GatewayApplicationTests.java /.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 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjunbalussery/gateway/4d5555a8faa4d79377948494a0a9b603ffadb032/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gateway -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.arjun 7 | gateway 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | gateway 12 | Gateway 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | Finchley.SR1 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-netflix-eureka-server 36 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-starter-netflix-zuul 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | test 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-security 50 | 51 | 52 | org.springframework.security 53 | spring-security-test 54 | test 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-data-mongodb 60 | 61 | 62 | io.jsonwebtoken 63 | jjwt 64 | 0.9.1 65 | 66 | 67 | org.springframework.security 68 | spring-security-core 69 | RELEASE 70 | compile 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.springframework.cloud 78 | spring-cloud-dependencies 79 | ${spring-cloud.version} 80 | pom 81 | import 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-maven-plugin 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 7 | 8 | @EnableZuulProxy 9 | @EnableEurekaServer 10 | @SpringBootApplication 11 | public class GatewayApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(GatewayApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/bean/auth/AuthResponse.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.bean.auth; 2 | 3 | public class AuthResponse { 4 | private String accessToken ; 5 | 6 | public AuthResponse(String accessToken) { 7 | this.accessToken = accessToken; 8 | } 9 | 10 | public AuthResponse() { 11 | } 12 | 13 | public String getAccessToken() { 14 | return accessToken; 15 | } 16 | 17 | public void setAccessToken(String accessToken) { 18 | this.accessToken = accessToken; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/bean/auth/JwtToken.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.bean.auth; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document 7 | public class JwtToken { 8 | @Id 9 | private String token; 10 | 11 | public JwtToken(String token) { 12 | this.token = token; 13 | } 14 | 15 | public JwtToken() { 16 | } 17 | 18 | public String getToken() { 19 | return token; 20 | } 21 | 22 | public void setToken(String token) { 23 | this.token = token; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/bean/auth/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.bean.auth; 2 | 3 | public class LoginRequest { 4 | private String username; 5 | private String password; 6 | 7 | public LoginRequest() { 8 | } 9 | 10 | public LoginRequest(String username, String password) { 11 | this.username = username; 12 | this.password = password; 13 | } 14 | 15 | public String getUsername() { 16 | return username; 17 | } 18 | 19 | public void setUsername(String username) { 20 | this.username = username; 21 | } 22 | 23 | public String getPassword() { 24 | return password; 25 | } 26 | 27 | public void setPassword(String password) { 28 | this.password = password; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/bean/auth/MongoUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.bean.auth; 2 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 3 | import org.springframework.security.core.GrantedAuthority; 4 | import org.springframework.security.core.authority.AuthorityUtils; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | 7 | import java.util.Collection; 8 | import java.util.List; 9 | 10 | @JsonDeserialize(as = MongoUserDetails.class) 11 | public class MongoUserDetails implements UserDetails 12 | { 13 | 14 | private String username; 15 | private String password; 16 | private Integer active; 17 | private boolean isLocked; 18 | private boolean isExpired; 19 | private boolean isEnabled; 20 | private List grantedAuthorities; 21 | 22 | public MongoUserDetails(String username, String password,Integer active, boolean isLocked, boolean isExpired, boolean isEnabled, String [] authorities) { 23 | this.username = username; 24 | this.password = password; 25 | this.active = active; 26 | this.isLocked = isLocked; 27 | this.isExpired = isExpired; 28 | this.isEnabled = isEnabled; 29 | this.grantedAuthorities = AuthorityUtils.createAuthorityList(authorities); 30 | } 31 | 32 | public MongoUserDetails(String username, String [] authorities) { 33 | this.username = username; 34 | this.grantedAuthorities = AuthorityUtils.createAuthorityList(authorities); 35 | } 36 | 37 | public MongoUserDetails() { 38 | super(); 39 | } 40 | 41 | @Override 42 | public Collection getAuthorities() { 43 | return grantedAuthorities; 44 | } 45 | 46 | @Override 47 | public String getPassword() { 48 | return password; 49 | } 50 | 51 | @Override 52 | public String getUsername() { 53 | return username; 54 | } 55 | 56 | @Override 57 | public boolean isAccountNonExpired() { 58 | return active==1; 59 | } 60 | 61 | @Override 62 | public boolean isAccountNonLocked() { 63 | return !isLocked; 64 | } 65 | 66 | @Override 67 | public boolean isCredentialsNonExpired() { 68 | return !isExpired; 69 | } 70 | 71 | @Override 72 | public boolean isEnabled() { 73 | return isEnabled; 74 | } 75 | 76 | public void setPassword(String password) { 77 | this.password = password; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/bean/auth/Role.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.bean.auth; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | public class Role { 7 | private Integer id; 8 | private String role; 9 | 10 | public Integer getId() { 11 | return id; 12 | } 13 | 14 | public void setId(Integer id) { 15 | this.id = id; 16 | } 17 | 18 | public String getRole() { 19 | return role; 20 | } 21 | 22 | public void setRole(String role) { 23 | this.role = role; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | return super.hashCode(); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Role{" + 34 | "id=" + id + 35 | ", role='" + role + '\'' + 36 | '}'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/bean/auth/User.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.bean.auth; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | import javax.validation.constraints.Email; 7 | import javax.validation.constraints.NotEmpty; 8 | import java.util.Set; 9 | 10 | @Document 11 | public class User { 12 | @Id 13 | private String id; 14 | @Email(message = "*Please provide a valid email") 15 | @NotEmpty(message = "*Please provide an email") 16 | private String email; 17 | @NotEmpty(message = "*Please provide your name") 18 | private String password; 19 | @NotEmpty(message = "*Please provide your name") 20 | private String name; 21 | @NotEmpty(message = "*Please provide your last name") 22 | private String lastName; 23 | private Integer active=1; 24 | private boolean isLoacked=false; 25 | private boolean isExpired=false; 26 | private boolean isEnabled=true; 27 | private Set role; 28 | 29 | public String getId() { 30 | return id; 31 | } 32 | 33 | public void setId(String id) { 34 | this.id = id; 35 | } 36 | 37 | public String getEmail() { 38 | return email; 39 | } 40 | 41 | public void setEmail(String email) { 42 | this.email = email; 43 | } 44 | 45 | public String getPassword() { 46 | return password; 47 | } 48 | 49 | public void setPassword(String password) { 50 | this.password = password; 51 | } 52 | 53 | public String getName() { 54 | return name; 55 | } 56 | 57 | public void setName(String name) { 58 | this.name = name; 59 | } 60 | 61 | public String getLastName() { 62 | return lastName; 63 | } 64 | 65 | public void setLastName(String lastName) { 66 | this.lastName = lastName; 67 | } 68 | 69 | public Integer getActive() { 70 | return active; 71 | } 72 | 73 | public void setActive(Integer active) { 74 | this.active = active; 75 | } 76 | 77 | public Set getRole() { 78 | return role; 79 | } 80 | 81 | public void setRole(Set role) { 82 | this.role = role; 83 | } 84 | 85 | public boolean isLoacked() { 86 | return isLoacked; 87 | } 88 | 89 | public void setLoacked(boolean loacked) { 90 | isLoacked = loacked; 91 | } 92 | 93 | public boolean isExpired() { 94 | return isExpired; 95 | } 96 | 97 | public void setExpired(boolean expired) { 98 | isExpired = expired; 99 | } 100 | 101 | public boolean isEnabled() { 102 | return isEnabled; 103 | } 104 | 105 | public void setEnabled(boolean enabled) { 106 | isEnabled = enabled; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.controller; 2 | 3 | import com.arjun.gateway.bean.auth.AuthResponse; 4 | import com.arjun.gateway.bean.auth.LoginRequest; 5 | import com.arjun.gateway.service.ILoginService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpHeaders; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | @Controller 17 | @RequestMapping("/api") 18 | public class LoginController { 19 | 20 | @Autowired 21 | private ILoginService iLoginService; 22 | 23 | @CrossOrigin("*") 24 | @PostMapping("/signin") 25 | @ResponseBody 26 | public ResponseEntity login(@RequestBody LoginRequest loginRequest) { 27 | String token = iLoginService.login(loginRequest.getUsername(),loginRequest.getPassword()); 28 | HttpHeaders headers = new HttpHeaders(); 29 | List headerlist = new ArrayList<>(); 30 | List exposeList = new ArrayList<>(); 31 | headerlist.add("Content-Type"); 32 | headerlist.add(" Accept"); 33 | headerlist.add("X-Requested-With"); 34 | headerlist.add("Authorization"); 35 | headers.setAccessControlAllowHeaders(headerlist); 36 | exposeList.add("Authorization"); 37 | headers.setAccessControlExposeHeaders(exposeList); 38 | headers.set("Authorization", token); 39 | return new ResponseEntity(new AuthResponse(token), headers, HttpStatus.CREATED); 40 | } 41 | @CrossOrigin("*") 42 | @PostMapping("/signout") 43 | @ResponseBody 44 | public ResponseEntity logout (@RequestHeader(value="Authorization") String token) { 45 | HttpHeaders headers = new HttpHeaders(); 46 | if (iLoginService.logout(token)) { 47 | headers.remove("Authorization"); 48 | return new ResponseEntity(new AuthResponse("logged out"), headers, HttpStatus.CREATED); 49 | } 50 | return new ResponseEntity(new AuthResponse("Logout Failed"), headers, HttpStatus.NOT_MODIFIED); 51 | } 52 | 53 | /** 54 | * 55 | * @param token 56 | * @return boolean. 57 | * if request reach here it means it is a valid token. 58 | */ 59 | @PostMapping("/valid/token") 60 | @ResponseBody 61 | public Boolean isValidToken (@RequestHeader(value="Authorization") String token) { 62 | return true; 63 | } 64 | 65 | 66 | @PostMapping("/signin/token") 67 | @CrossOrigin("*") 68 | @ResponseBody 69 | public ResponseEntity createNewToken (@RequestHeader(value="Authorization") String token) { 70 | String newToken = iLoginService.createNewToken(token); 71 | HttpHeaders headers = new HttpHeaders(); 72 | List headerList = new ArrayList<>(); 73 | List exposeList = new ArrayList<>(); 74 | headerList.add("Content-Type"); 75 | headerList.add(" Accept"); 76 | headerList.add("X-Requested-With"); 77 | headerList.add("Authorization"); 78 | headers.setAccessControlAllowHeaders(headerList); 79 | exposeList.add("Authorization"); 80 | headers.setAccessControlExposeHeaders(exposeList); 81 | headers.set("Authorization", newToken); 82 | return new ResponseEntity(new AuthResponse(newToken), headers, HttpStatus.CREATED); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/exception/CustomException.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | public class CustomException extends RuntimeException{ 6 | private static final long serialVersionUID = 1L; 7 | 8 | private final String message; 9 | private final HttpStatus httpStatus; 10 | 11 | public CustomException(String message, HttpStatus httpStatus) { 12 | this.message = message; 13 | this.httpStatus = httpStatus; 14 | } 15 | 16 | @Override 17 | public String getMessage() { 18 | return message; 19 | } 20 | 21 | public HttpStatus getHttpStatus() { 22 | return httpStatus; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/exception/GlobalExceptionHandlerController.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.exception; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.security.access.AccessDeniedException; 7 | import org.springframework.web.bind.annotation.ExceptionHandler; 8 | import org.springframework.web.bind.annotation.RestControllerAdvice; 9 | 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | @RestControllerAdvice 14 | public class GlobalExceptionHandlerController { 15 | private final Logger LOG = LoggerFactory.getLogger(getClass()); 16 | 17 | @ExceptionHandler(CustomException.class) 18 | public void handleCustomException(HttpServletResponse res, CustomException e) throws IOException { 19 | LOG.error("ERROR", e); 20 | res.sendError(e.getHttpStatus().value(), e.getMessage()); 21 | } 22 | 23 | @ExceptionHandler(AccessDeniedException.class) 24 | public void handleAccessDeniedException(HttpServletResponse res, AccessDeniedException e) throws IOException { 25 | LOG.error("ERROR", e); 26 | res.sendError(HttpStatus.FORBIDDEN.value(), "Access denied"); 27 | } 28 | 29 | @ExceptionHandler(IllegalArgumentException.class) 30 | public void handleIllegalArgumentException(HttpServletResponse res, IllegalArgumentException e) throws IOException { 31 | LOG.error("ERROR", e); 32 | res.sendError(HttpStatus.BAD_REQUEST.value(), "Something went wrong"); 33 | } 34 | 35 | @ExceptionHandler(Exception.class) 36 | public void handleException(HttpServletResponse res, Exception e) throws IOException { 37 | LOG.error("ERROR", e); 38 | res.sendError(HttpStatus.BAD_REQUEST.value(), "Something went wrong"); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/repository/JwtTokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.repository; 2 | 3 | import com.arjun.gateway.bean.auth.JwtToken; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface JwtTokenRepository extends MongoRepository { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.repository; 2 | 3 | import com.arjun.gateway.bean.auth.User; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | import org.springframework.data.mongodb.repository.Query; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends MongoRepository { 10 | @Query(value="{'email' : ?0}") 11 | User findByEmail(String email); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/security/JwtTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.security; 2 | 3 | import com.arjun.gateway.exception.CustomException; 4 | import io.jsonwebtoken.JwtException; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.web.filter.GenericFilterBean; 9 | 10 | import javax.servlet.FilterChain; 11 | import javax.servlet.ServletException; 12 | import javax.servlet.ServletRequest; 13 | import javax.servlet.ServletResponse; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import java.io.IOException; 17 | public class JwtTokenFilter extends GenericFilterBean { 18 | private JwtTokenProvider jwtTokenProvider; 19 | 20 | public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) { 21 | this.jwtTokenProvider = jwtTokenProvider; 22 | } 23 | 24 | @Override 25 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) 26 | throws IOException, ServletException { 27 | HttpServletRequest request = (HttpServletRequest) req; 28 | HttpServletResponse response = (HttpServletResponse) res; 29 | String token = jwtTokenProvider.resolveToken((HttpServletRequest) req); 30 | if (token != null) { 31 | if (!jwtTokenProvider.isTokenPresentInDB(token)) { 32 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Invalid JWT token"); 33 | throw new CustomException("Invalid JWT token",HttpStatus.UNAUTHORIZED); 34 | } 35 | try { 36 | jwtTokenProvider.validateToken(token) ; 37 | } catch (JwtException | IllegalArgumentException e) { 38 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Invalid JWT token"); 39 | throw new CustomException("Invalid JWT token",HttpStatus.UNAUTHORIZED); 40 | } 41 | Authentication auth = token != null ? jwtTokenProvider.getAuthentication(token) : null; 42 | //setting auth in the context. 43 | SecurityContextHolder.getContext().setAuthentication(auth); 44 | } 45 | filterChain.doFilter(req, res); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/security/JwtTokenFilterConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.security; 2 | 3 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.web.DefaultSecurityFilterChain; 6 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 7 | 8 | public class JwtTokenFilterConfigurer extends SecurityConfigurerAdapter { 9 | private JwtTokenProvider jwtTokenProvider; 10 | 11 | public JwtTokenFilterConfigurer(JwtTokenProvider jwtTokenProvider) { 12 | this.jwtTokenProvider = jwtTokenProvider; 13 | } 14 | 15 | @Override 16 | public void configure(HttpSecurity http) throws Exception { 17 | JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider); 18 | http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/security/JwtTokenProvider.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.security; 2 | 3 | import com.arjun.gateway.bean.auth.JwtToken; 4 | import com.arjun.gateway.bean.auth.MongoUserDetails; 5 | import com.arjun.gateway.repository.JwtTokenRepository; 6 | import io.jsonwebtoken.Claims; 7 | import io.jsonwebtoken.JwtException; 8 | import io.jsonwebtoken.Jwts; 9 | import io.jsonwebtoken.SignatureAlgorithm; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 12 | import org.springframework.security.core.Authentication; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.core.userdetails.UserDetailsService; 15 | import org.springframework.stereotype.Component; 16 | 17 | import javax.annotation.PostConstruct; 18 | import javax.servlet.http.HttpServletRequest; 19 | import java.util.Base64; 20 | import java.util.Date; 21 | import java.util.List; 22 | 23 | @Component 24 | public class JwtTokenProvider { 25 | private static final String AUTH="auth"; 26 | private static final String AUTHORIZATION="Authorization"; 27 | private String secretKey="secret-key"; 28 | private long validityInMilliseconds = 3600000; // 1h 29 | 30 | @Autowired 31 | private JwtTokenRepository jwtTokenRepository; 32 | 33 | @Autowired 34 | private UserDetailsService userDetailsService; 35 | 36 | @PostConstruct 37 | protected void init() { 38 | secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); 39 | } 40 | 41 | public String createToken(String username, List roles) { 42 | 43 | Claims claims = Jwts.claims().setSubject(username); 44 | claims.put(AUTH,roles); 45 | 46 | Date now = new Date(); 47 | Date validity = new Date(now.getTime() + validityInMilliseconds); 48 | 49 | String token = Jwts.builder()// 50 | .setClaims(claims)// 51 | .setIssuedAt(now)// 52 | .setExpiration(validity)// 53 | .signWith(SignatureAlgorithm.HS256, secretKey)// 54 | .compact(); 55 | jwtTokenRepository.save(new JwtToken(token)); 56 | return token; 57 | } 58 | 59 | public String resolveToken(HttpServletRequest req) { 60 | String bearerToken = req.getHeader(AUTHORIZATION); 61 | /*if (bearerToken != null && bearerToken.startsWith("Bearer ")) { 62 | return bearerToken.substring(7, bearerToken.length()); 63 | }*/ 64 | if (bearerToken != null ) { 65 | return bearerToken; 66 | } 67 | return null; 68 | } 69 | 70 | public boolean validateToken(String token) throws JwtException,IllegalArgumentException{ 71 | Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); 72 | return true; 73 | } 74 | public boolean isTokenPresentInDB (String token) { 75 | return jwtTokenRepository.findById(token).isPresent(); 76 | } 77 | //user details with out database hit 78 | public UserDetails getUserDetails(String token) { 79 | String userName = getUsername(token); 80 | List roleList = getRoleList(token); 81 | UserDetails userDetails = new MongoUserDetails(userName,roleList.toArray(new String[roleList.size()])); 82 | return userDetails; 83 | } 84 | public List getRoleList(String token) { 85 | return (List) Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token). 86 | getBody().get(AUTH); 87 | } 88 | 89 | public String getUsername(String token) { 90 | return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); 91 | } 92 | public Authentication getAuthentication(String token) { 93 | //using data base: uncomment when you want to fetch data from data base 94 | //UserDetails userDetails = userDetailsService.loadUserByUsername(getUsername(token)); 95 | //from token take user value. comment below line for changing it taking from data base 96 | UserDetails userDetails = getUserDetails(token); 97 | return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/security/UserService.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.security; 2 | 3 | import com.arjun.gateway.bean.auth.MongoUserDetails; 4 | import com.arjun.gateway.bean.auth.Role; 5 | import com.arjun.gateway.bean.auth.User; 6 | import com.arjun.gateway.exception.CustomException; 7 | import com.arjun.gateway.repository.UserRepository; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpStatus; 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 | @Service 16 | public class UserService implements UserDetailsService{ 17 | @Autowired 18 | private UserRepository userRepository; 19 | 20 | @Override 21 | public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { 22 | User user = userRepository.findByEmail(email); 23 | if (user == null || user.getRole() == null || user.getRole().isEmpty()) { 24 | throw new CustomException("Invalid username or password.", HttpStatus.UNAUTHORIZED); 25 | } 26 | String [] authorities = new String[user.getRole().size()]; 27 | int count=0; 28 | for (Role role : user.getRole()) { 29 | //NOTE: normally we dont need to add "ROLE_" prefix. Spring does automatically for us. 30 | //Since we are using custom token using JWT we should add ROLE_ prefix 31 | authorities[count] = "ROLE_"+role.getRole(); 32 | count++; 33 | } 34 | MongoUserDetails userDetails = new MongoUserDetails(user.getEmail(),user.getPassword(),user.getActive(), 35 | user.isLoacked(), user.isExpired(),user.isEnabled(),authorities); 36 | return userDetails; 37 | } 38 | 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.HttpMethod; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.config.http.SessionCreationPolicy; 13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 | import org.springframework.security.crypto.password.PasswordEncoder; 15 | 16 | @Configuration 17 | @EnableGlobalMethodSecurity(prePostEnabled = true) 18 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 19 | 20 | @Autowired 21 | private JwtTokenProvider jwtTokenProvider; 22 | 23 | @Override 24 | protected void configure(HttpSecurity http) throws Exception { 25 | 26 | // Disable CSRF (cross site request forgery) 27 | http.cors().and().csrf().disable(); 28 | 29 | // No session will be created or used by spring security 30 | http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 31 | 32 | // Entry points 33 | http.authorizeRequests() 34 | .antMatchers("/**/signin/**").permitAll() 35 | // Disallow everything else.. 36 | .anyRequest().authenticated(); 37 | 38 | // If a user try to access a resource without having enough permissions 39 | http.exceptionHandling().accessDeniedPage("/login"); 40 | 41 | // Apply JWT 42 | http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider)); 43 | 44 | // Optional, if you want to test the API from a browser 45 | // http.httpBasic(); 46 | } 47 | 48 | @Override 49 | public void configure(WebSecurity web) throws Exception { 50 | // Allow eureka client to be accessed without authentication 51 | web.ignoring().antMatchers("/*/")// 52 | .antMatchers("/eureka/**")// 53 | .antMatchers(HttpMethod.OPTIONS, "/**"); // Request type options should be allowed. 54 | } 55 | 56 | @Bean 57 | public PasswordEncoder passwordEncoder() { 58 | return new BCryptPasswordEncoder(12); 59 | } 60 | 61 | @Bean 62 | public AuthenticationManager customAuthenticationManager() throws Exception { 63 | return authenticationManager(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/service/ILoginService.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.service; 2 | 3 | import com.arjun.gateway.bean.auth.User; 4 | 5 | public interface ILoginService { 6 | String login(String username, String password); 7 | User saveUser(User user); 8 | 9 | boolean logout(String token); 10 | 11 | Boolean isValidToken(String token); 12 | 13 | String createNewToken(String token); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/arjun/gateway/service/serviceimpl/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway.service.serviceimpl; 2 | 3 | import com.arjun.gateway.bean.auth.JwtToken; 4 | import com.arjun.gateway.bean.auth.Role; 5 | import com.arjun.gateway.bean.auth.User; 6 | import com.arjun.gateway.exception.CustomException; 7 | import com.arjun.gateway.repository.JwtTokenRepository; 8 | import com.arjun.gateway.repository.UserRepository; 9 | import com.arjun.gateway.security.JwtTokenProvider; 10 | import com.arjun.gateway.service.ILoginService; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.security.authentication.AuthenticationManager; 14 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 15 | import org.springframework.security.core.AuthenticationException; 16 | import org.springframework.security.crypto.password.PasswordEncoder; 17 | import org.springframework.stereotype.Service; 18 | 19 | import java.util.List; 20 | import java.util.Objects; 21 | import java.util.stream.Collectors; 22 | 23 | @Service 24 | public class LoginService implements ILoginService 25 | { 26 | @Autowired 27 | private PasswordEncoder passwordEncoder; 28 | @Autowired 29 | private JwtTokenProvider jwtTokenProvider; 30 | @Autowired 31 | private AuthenticationManager authenticationManager; 32 | @Autowired 33 | private UserRepository userRepository; 34 | @Autowired 35 | private JwtTokenRepository jwtTokenRepository; 36 | 37 | @Override 38 | public String login(String username, String password) { 39 | try { 40 | authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, 41 | password)); 42 | User user = userRepository.findByEmail(username); 43 | if (user == null || user.getRole() == null || user.getRole().isEmpty()) { 44 | throw new CustomException("Invalid username or password.", HttpStatus.UNAUTHORIZED); 45 | } 46 | //NOTE: normally we dont need to add "ROLE_" prefix. Spring does automatically for us. 47 | //Since we are using custom token using JWT we should add ROLE_ prefix 48 | String token = jwtTokenProvider.createToken(username, user.getRole().stream() 49 | .map((Role role)-> "ROLE_"+role.getRole()).filter(Objects::nonNull).collect(Collectors.toList())); 50 | return token; 51 | 52 | } catch (AuthenticationException e) { 53 | throw new CustomException("Invalid username or password.", HttpStatus.UNAUTHORIZED); 54 | } 55 | } 56 | 57 | @Override 58 | public User saveUser(User user) { 59 | user.setPassword(passwordEncoder.encode(user.getPassword()) ); 60 | return userRepository.save(user); 61 | } 62 | 63 | @Override 64 | public boolean logout(String token) { 65 | jwtTokenRepository.delete(new JwtToken(token)); 66 | return true; 67 | } 68 | 69 | @Override 70 | public Boolean isValidToken(String token) { 71 | return jwtTokenProvider.validateToken(token); 72 | } 73 | 74 | @Override 75 | public String createNewToken(String token) { 76 | String username = jwtTokenProvider.getUsername(token); 77 | ListroleList = jwtTokenProvider.getRoleList(token); 78 | String newToken = jwtTokenProvider.createToken(username,roleList); 79 | return newToken; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Name of the application 2 | spring.application.name=gateway 3 | #This is a eureka server so no need to register 4 | eureka.client.register-with-eureka=false 5 | #This is a eureka server no need to fetch registry 6 | eureka.client.fetch-registry=false 7 | #Register url for client 8 | eureka.client.service-url.defaultZone=http://localhost:8080/eureka 9 | #timeout 10 | eureka.server.wait-time-in-ms-when-sync-empty=0 11 | #All url come with prefix/api will interpret 12 | zuul.prefix=/api 13 | zuul.routes.middleware.path=/cart/** 14 | zuul.routes.middleware.url=http://localhost:8081/ 15 | 16 | #spring data mongo 17 | spring.data.mongodb.authentication-database=admin 18 | spring.data.mongodb.username=root 19 | spring.data.mongodb.password=root 20 | spring.data.mongodb.database=test 21 | spring.data.mongodb.port=27017 22 | spring.data.mongodb.host=localhost 23 | -------------------------------------------------------------------------------- /src/test/java/com/arjun/gateway/GatewayApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.arjun.gateway; 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 GatewayApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------