From 3db194ea2194fe5fe31821b0799d936c05e6f8bb Mon Sep 17 00:00:00 2001 From: AbdellahASKI Date: Mon, 14 Jan 2019 02:40:48 +0100 Subject: [PATCH] Added JWTAuthorizationFilter --- pom.xml | 14 +++++ .../sec/JWTAuthorizationFilter.java | 19 ------- .../security/JWTAuthorizationFilter.java | 57 +++++++++++++++++++ .../{sec => security}/SecurityConfig.java | 10 ++-- .../security/SecurityParams.java | 8 +++ src/main/resources/application.properties | 1 + 6 files changed, 86 insertions(+), 23 deletions(-) delete mode 100644 src/main/java/me/aski/catalogueservice/sec/JWTAuthorizationFilter.java create mode 100644 src/main/java/me/aski/catalogueservice/security/JWTAuthorizationFilter.java rename src/main/java/me/aski/catalogueservice/{sec => security}/SecurityConfig.java (85%) create mode 100644 src/main/java/me/aski/catalogueservice/security/SecurityParams.java diff --git a/pom.xml b/pom.xml index 37be821..a21c660 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,20 @@ spring-boot-starter-web + + + com.auth0 + java-jwt + 3.5.0 + + + + commons-codec + commons-codec + 1.11 + + + org.projectlombok lombok diff --git a/src/main/java/me/aski/catalogueservice/sec/JWTAuthorizationFilter.java b/src/main/java/me/aski/catalogueservice/sec/JWTAuthorizationFilter.java deleted file mode 100644 index c258e56..0000000 --- a/src/main/java/me/aski/catalogueservice/sec/JWTAuthorizationFilter.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.aski.catalogueservice.sec; - -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public class JWTAuthorizationFilter extends OncePerRequestFilter { - @Override - protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { - System.out.println("**********"); - String jwt = httpServletRequest.getHeader("Authorization"); - if (jwt == null) throw new RuntimeException("Not Authorized"); - filterChain.doFilter(httpServletRequest, httpServletResponse); - } -} diff --git a/src/main/java/me/aski/catalogueservice/security/JWTAuthorizationFilter.java b/src/main/java/me/aski/catalogueservice/security/JWTAuthorizationFilter.java new file mode 100644 index 0000000..236b917 --- /dev/null +++ b/src/main/java/me/aski/catalogueservice/security/JWTAuthorizationFilter.java @@ -0,0 +1,57 @@ +package me.aski.catalogueservice.security; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public class JWTAuthorizationFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, PATCH"); + String allHeaders = "No-Auth, Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With"; + response.setHeader("Access-Control-Allow-Headers", allHeaders); + response.setHeader("Access-Control-Allow-Credentials", "true"); + + if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { + response.setStatus(HttpServletResponse.SC_OK); + } else { + String jwtToken = request.getHeader(SecurityParams.HEADER_NAME); + if (jwtToken == null || !jwtToken.startsWith(SecurityParams.PREFIX)) { + //throw new RuntimeException("Not Authorized"); + filterChain.doFilter(request, response); + return; + } + + String jwt = jwtToken.substring(SecurityParams.PREFIX.length()); + + JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SecurityParams.SECRET)) + .build(); + DecodedJWT decodedJWT = verifier.verify(jwt); + String username = decodedJWT.getSubject(); + List roles = decodedJWT.getClaims().get("roles").asList(String.class); + + Collection authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); + + UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken(username, null, authorities); + SecurityContextHolder.getContext().setAuthentication(user); + + filterChain.doFilter(request, response); + } + } +} diff --git a/src/main/java/me/aski/catalogueservice/sec/SecurityConfig.java b/src/main/java/me/aski/catalogueservice/security/SecurityConfig.java similarity index 85% rename from src/main/java/me/aski/catalogueservice/sec/SecurityConfig.java rename to src/main/java/me/aski/catalogueservice/security/SecurityConfig.java index a9c1b66..8d3dfb5 100644 --- a/src/main/java/me/aski/catalogueservice/sec/SecurityConfig.java +++ b/src/main/java/me/aski/catalogueservice/security/SecurityConfig.java @@ -1,8 +1,8 @@ -package me.aski.catalogueservice.sec; +package me.aski.catalogueservice.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @@ -14,19 +14,21 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Override + /*@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication(). withUser("admin").password(passwordEncoder().encode("1234")).roles("ADMIN", "USER") .and(). withUser("user").password(passwordEncoder().encode("1234")).roles("USER"); - } + }*/ @Override protected void configure(HttpSecurity http) throws Exception { //super.configure(http); http.csrf().disable(); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + http.authorizeRequests().antMatchers(HttpMethod.GET, "/categories/**").permitAll(); + http.authorizeRequests().antMatchers(HttpMethod.GET, "/products/**").permitAll(); http.authorizeRequests().antMatchers("/categories/**").hasAuthority("ADMIN"); http.authorizeRequests().antMatchers("/products/**").hasAuthority("USER"); http.authorizeRequests().anyRequest().authenticated(); diff --git a/src/main/java/me/aski/catalogueservice/security/SecurityParams.java b/src/main/java/me/aski/catalogueservice/security/SecurityParams.java new file mode 100644 index 0000000..23a0db6 --- /dev/null +++ b/src/main/java/me/aski/catalogueservice/security/SecurityParams.java @@ -0,0 +1,8 @@ +package me.aski.catalogueservice.security; + +public interface SecurityParams { + String HEADER_NAME = "Authorization"; + String SECRET = "abdellah@aski.me"; + long EXPIRATION = 10 * 24 * 3600; + String PREFIX = "Bearer "; +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 56198c3..c0226b9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ +server.port=8081 spring.data.mongodb.uri=mongodb://localhost:27017/CatalogueService \ No newline at end of file