diff --git a/pom.xml b/pom.xml
index 0679783..1aa7a26 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
org.springframework.boot
spring-boot-starter-parent
- 2.7.7
+ 3.4.1
@@ -30,12 +30,12 @@
org.springframework.boot
spring-boot-starter-web
-
+
- tomcat-embed-el
- org.apache.tomcat.embed
-
-
+ tomcat-embed-el
+ org.apache.tomcat.embed
+
+
org.springframework.boot
@@ -47,25 +47,27 @@
- txw2
- org.glassfish.jaxb
+ txw2
+ org.glassfish.jaxb
-
+
- org.springframework.mobile
- spring-mobile-device
- 1.1.5.RELEASE
+ io.jsonwebtoken
+ jjwt-api
+ 0.12.6
-
io.jsonwebtoken
- jjwt
- 0.6.0
+ jjwt-impl
+ 0.12.6
+ runtime
- javax.xml.bind
- jaxb-api
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.12.6
+ runtime
@@ -141,5 +143,4 @@
-
diff --git a/src/main/java/com/bfwg/Application.java b/src/main/java/com/bfwg/Application.java
index d90f6a7..4ba8bba 100644
--- a/src/main/java/com/bfwg/Application.java
+++ b/src/main/java/com/bfwg/Application.java
@@ -9,6 +9,4 @@ public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-}
-
-
+}
\ No newline at end of file
diff --git a/src/main/java/com/bfwg/common/DeviceProvider.java b/src/main/java/com/bfwg/common/DeviceProvider.java
deleted file mode 100644
index b0b00b9..0000000
--- a/src/main/java/com/bfwg/common/DeviceProvider.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.bfwg.common;
-
-import org.springframework.mobile.device.Device;
-import org.springframework.mobile.device.DeviceUtils;
-import org.springframework.stereotype.Component;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * Created by fanjin on 2017-10-16.
- */
-@Component
-public class DeviceProvider {
-
- public Device getCurrentDevice(HttpServletRequest request) {
- return DeviceUtils.getCurrentDevice(request);
- }
-}
diff --git a/src/main/java/com/bfwg/common/TimeProvider.java b/src/main/java/com/bfwg/common/TimeProvider.java
index ce735ea..15b412f 100644
--- a/src/main/java/com/bfwg/common/TimeProvider.java
+++ b/src/main/java/com/bfwg/common/TimeProvider.java
@@ -11,9 +11,9 @@
@Component
public class TimeProvider implements Serializable {
- private static final long serialVersionUID = -3301695478208950415L;
+ private static final long serialVersionUID = -3301695478208950415L;
- public Date now() {
- return new Date();
- }
+ public Date now() {
+ return new Date();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/bfwg/config/WebConfig.java b/src/main/java/com/bfwg/config/WebConfig.java
deleted file mode 100644
index 0adb14c..0000000
--- a/src/main/java/com/bfwg/config/WebConfig.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.bfwg.config;
-
-import java.util.List;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver;
-import org.springframework.mobile.device.DeviceResolverHandlerInterceptor;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class WebConfig implements WebMvcConfigurer {
-
- @Bean
- public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
- return new DeviceResolverHandlerInterceptor();
- }
-
- @Bean
- public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
- return new DeviceHandlerMethodArgumentResolver();
- }
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(deviceResolverHandlerInterceptor());
- }
-
- @Override
- public void addArgumentResolvers(List argumentResolvers) {
- argumentResolvers.add(deviceHandlerMethodArgumentResolver());
- }
-
-}
diff --git a/src/main/java/com/bfwg/config/WebSecurityConfig.java b/src/main/java/com/bfwg/config/WebSecurityConfig.java
index 8f7f047..20ffd83 100644
--- a/src/main/java/com/bfwg/config/WebSecurityConfig.java
+++ b/src/main/java/com/bfwg/config/WebSecurityConfig.java
@@ -1,5 +1,7 @@
package com.bfwg.config;
+import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -7,7 +9,7 @@
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
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.WebSecurityCustomizer;
@@ -27,7 +29,7 @@
@Configuration
@EnableWebSecurity
-@EnableGlobalMethodSecurity(prePostEnabled = true)
+@EnableMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
@Autowired
@@ -41,8 +43,7 @@ public class WebSecurityConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
- auth.userDetailsService(jwtUserDetailsService)
- .passwordEncoder(passwordEncoder);
+ auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder);
}
@Autowired
@@ -56,27 +57,20 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration a
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
- .exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint).and()
- .authorizeRequests()
- .antMatchers(
- HttpMethod.GET,
- "/",
- "/auth/**",
- "/webjars/**",
- "/*.html",
- "/favicon.ico",
- "/**/*.html",
- "/**/*.css",
- "/**/*.js")
- .permitAll()
- .antMatchers("/auth/**").permitAll()
- .anyRequest().authenticated().and()
- .addFilterBefore(new TokenAuthenticationFilter(tokenHelper, jwtUserDetailsService),
- BasicAuthenticationFilter.class);
- http.csrf().disable();
+ http.addFilterBefore(new TokenAuthenticationFilter(tokenHelper, jwtUserDetailsService),
+ BasicAuthenticationFilter.class)
+ .authorizeHttpRequests(authorize -> authorize
+ .requestMatchers(antMatcher(HttpMethod.GET, "/"), antMatcher(HttpMethod.GET, "/auth/**"),
+ antMatcher(HttpMethod.GET, "/webjars/**"), antMatcher(HttpMethod.GET, "/*.html"),
+ antMatcher(HttpMethod.GET, "/favicon.ico"), antMatcher(HttpMethod.GET, "/**/*.html"),
+ antMatcher(HttpMethod.GET, "/**/*.css"), antMatcher(HttpMethod.GET, "/**/*.js"))
+ .permitAll().requestMatchers("/auth/**").permitAll().anyRequest().authenticated())
+ .sessionManagement(sec -> sec.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .exceptionHandling(
+ exceptionHandler -> exceptionHandler.authenticationEntryPoint(restAuthenticationEntryPoint))
+ .csrf(csrf -> csrf.disable());
+
return http.build();
}
@@ -84,18 +78,11 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
public WebSecurityCustomizer webSecurityCustomizer() {
// TokenAuthenticationFilter will ignore the below paths
return (web) -> {
- web.ignoring().antMatchers(
- HttpMethod.POST,
- "/auth/login");
- web.ignoring().antMatchers(
- HttpMethod.GET,
- "/",
- "/webjars/**",
- "/*.html",
- "/favicon.ico",
- "/**/*.html",
- "/**/*.css",
- "/**/*.js");
+ web.ignoring().requestMatchers(HttpMethod.POST, "/auth/login").requestMatchers(
+ antMatcher(HttpMethod.GET, "/"), antMatcher(HttpMethod.GET, "/webjars/**"),
+ antMatcher(HttpMethod.GET, "/*.html"), antMatcher(HttpMethod.GET, "/favicon.ico"),
+ antMatcher(HttpMethod.GET, "/**/*.html"), antMatcher(HttpMethod.GET, "/**path/*.css"),
+ antMatcher(HttpMethod.GET, "/**path/*.js"));
};
}
}
diff --git a/src/main/java/com/bfwg/model/Authority.java b/src/main/java/com/bfwg/model/Authority.java
index 4d42424..b8c4d5b 100644
--- a/src/main/java/com/bfwg/model/Authority.java
+++ b/src/main/java/com/bfwg/model/Authority.java
@@ -1,48 +1,56 @@
package com.bfwg.model;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
-import javax.persistence.*;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
/**
* Created by fan.jin on 2016-11-03.
*/
@Entity
-@Table(name="AUTHORITY")
+@Table(name = "AUTHORITY")
public class Authority implements GrantedAuthority {
- @Id
- @Column(name="id")
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- Long id;
-
- @Enumerated( EnumType.STRING)
- @Column(name="name")
- UserRoleName name;
-
- @Override
- public String getAuthority() {
- return name.name();
- }
-
- public void setName(UserRoleName name) {
- this.name = name;
- }
-
- @JsonIgnore
- public UserRoleName getName() {
- return name;
- }
-
- @JsonIgnore
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ Long id;
+
+ @Enumerated(EnumType.STRING)
+ @Column(name = "name")
+ UserRoleName name;
+
+ @Override
+ public String getAuthority() {
+ return name.name();
+ }
+
+ public void setName(UserRoleName name) {
+ this.name = name;
+ }
+
+ @JsonIgnore
+ public UserRoleName getName() {
+ return name;
+ }
+
+ @JsonIgnore
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
}
diff --git a/src/main/java/com/bfwg/model/User.java b/src/main/java/com/bfwg/model/User.java
index 3ae26b7..ea34088 100644
--- a/src/main/java/com/bfwg/model/User.java
+++ b/src/main/java/com/bfwg/model/User.java
@@ -4,23 +4,23 @@
import java.util.Collection;
import java.util.List;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.Table;
-
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
+
/**
* Created by fan.jin on 2016-10-15.
*/
diff --git a/src/main/java/com/bfwg/model/UserRoleName.java b/src/main/java/com/bfwg/model/UserRoleName.java
index 3ddf821..c957e62 100644
--- a/src/main/java/com/bfwg/model/UserRoleName.java
+++ b/src/main/java/com/bfwg/model/UserRoleName.java
@@ -1,6 +1,5 @@
package com.bfwg.model;
public enum UserRoleName {
- ROLE_USER,
- ROLE_ADMIN
+ ROLE_USER, ROLE_ADMIN
}
diff --git a/src/main/java/com/bfwg/model/UserTokenState.java b/src/main/java/com/bfwg/model/UserTokenState.java
index 9fe5d0b..c8c083b 100644
--- a/src/main/java/com/bfwg/model/UserTokenState.java
+++ b/src/main/java/com/bfwg/model/UserTokenState.java
@@ -4,32 +4,32 @@
* Created by fan.jin on 2016-10-17.
*/
public class UserTokenState {
- private String access_token;
- private Long expires_in;
+ private String access_token;
+ private Long expires_in;
- public UserTokenState() {
- this.access_token = null;
- this.expires_in = null;
- }
+ public UserTokenState() {
+ this.access_token = null;
+ this.expires_in = null;
+ }
- public UserTokenState(String access_token, long expires_in) {
- this.access_token = access_token;
- this.expires_in = expires_in;
- }
+ public UserTokenState(String access_token, long expires_in) {
+ this.access_token = access_token;
+ this.expires_in = expires_in;
+ }
- public String getAccess_token() {
- return access_token;
- }
+ public String getAccess_token() {
+ return access_token;
+ }
- public void setAccess_token(String access_token) {
- this.access_token = access_token;
- }
+ public void setAccess_token(String access_token) {
+ this.access_token = access_token;
+ }
- public Long getExpires_in() {
- return expires_in;
- }
+ public Long getExpires_in() {
+ return expires_in;
+ }
- public void setExpires_in(Long expires_in) {
- this.expires_in = expires_in;
- }
+ public void setExpires_in(Long expires_in) {
+ this.expires_in = expires_in;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/bfwg/repository/UserRepository.java b/src/main/java/com/bfwg/repository/UserRepository.java
index 3eb565b..e6fed9a 100644
--- a/src/main/java/com/bfwg/repository/UserRepository.java
+++ b/src/main/java/com/bfwg/repository/UserRepository.java
@@ -7,6 +7,5 @@
* Created by fan.jin on 2016-10-15.
*/
public interface UserRepository extends JpaRepository {
- User findByUsername( String username );
+ User findByUsername(String username);
}
-
diff --git a/src/main/java/com/bfwg/rest/AuthenticationController.java b/src/main/java/com/bfwg/rest/AuthenticationController.java
index 5ac4a37..2fcca32 100644
--- a/src/main/java/com/bfwg/rest/AuthenticationController.java
+++ b/src/main/java/com/bfwg/rest/AuthenticationController.java
@@ -5,14 +5,10 @@
import java.util.HashMap;
import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.mobile.device.Device;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -24,13 +20,15 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.bfwg.common.DeviceProvider;
import com.bfwg.model.User;
import com.bfwg.model.UserTokenState;
import com.bfwg.security.TokenHelper;
import com.bfwg.security.auth.JwtAuthenticationRequest;
import com.bfwg.service.UserService;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
/**
* Created by fan.jin on 2017-05-10.
*/
@@ -49,19 +47,13 @@ public class AuthenticationController {
@Autowired
private UserService userService;
- @Autowired
- private DeviceProvider deviceProvider;
-
@PostMapping("/login")
- public ResponseEntity> createAuthenticationToken(
- @RequestBody JwtAuthenticationRequest authenticationRequest,
- HttpServletResponse response,
- Device device) throws AuthenticationException, IOException {
+ public ResponseEntity> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest,
+ HttpServletResponse response) throws AuthenticationException, IOException {
// Perform the security
- final Authentication authentication = authenticationManager.authenticate(
- new UsernamePasswordAuthenticationToken(
- authenticationRequest.getUsername(),
+ final Authentication authentication = authenticationManager
+ .authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(),
authenticationRequest.getPassword()));
// Inject into security context
@@ -69,27 +61,23 @@ public ResponseEntity> createAuthenticationToken(
// token creation
User user = (User) authentication.getPrincipal();
- String jws = tokenHelper.generateToken(user.getUsername(), device);
- int expiresIn = tokenHelper.getExpiredIn(device);
+ String jws = tokenHelper.generateToken(user.getUsername());
+ int expiresIn = tokenHelper.getExpiredIn();
// Return the token
return ResponseEntity.ok(new UserTokenState(jws, expiresIn));
}
@PostMapping("/refresh")
- public ResponseEntity> refreshAuthenticationToken(
- HttpServletRequest request,
- HttpServletResponse response,
+ public ResponseEntity> refreshAuthenticationToken(HttpServletRequest request, HttpServletResponse response,
Principal principal) {
String authToken = tokenHelper.getToken(request);
- Device device = deviceProvider.getCurrentDevice(request);
-
if (authToken != null && principal != null) {
// TODO check user password last update
- String refreshedToken = tokenHelper.refreshToken(authToken, device);
- int expiresIn = tokenHelper.getExpiredIn(device);
+ String refreshedToken = tokenHelper.refreshToken(authToken);
+ int expiresIn = tokenHelper.getExpiredIn();
return ResponseEntity.ok(new UserTokenState(refreshedToken, expiresIn));
} else {
diff --git a/src/main/java/com/bfwg/security/TokenHelper.java b/src/main/java/com/bfwg/security/TokenHelper.java
index 710a26f..28ec6a2 100644
--- a/src/main/java/com/bfwg/security/TokenHelper.java
+++ b/src/main/java/com/bfwg/security/TokenHelper.java
@@ -1,19 +1,21 @@
package com.bfwg.security;
-import com.bfwg.common.TimeProvider;
-import com.bfwg.model.User;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
+import java.util.Date;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.mobile.device.Device;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
-import javax.servlet.http.HttpServletRequest;
-import java.util.Date;
+import com.bfwg.common.TimeProvider;
+import com.bfwg.model.User;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.security.Keys;
+import io.jsonwebtoken.security.MacAlgorithm;
+import jakarta.servlet.http.HttpServletRequest;
/**
* Created by fan.jin on 2016-10-19.
@@ -22,157 +24,109 @@
@Component
public class TokenHelper {
- @Value("${app.name}")
- private String APP_NAME;
-
- @Value("${jwt.secret}")
- public String SECRET;
-
- @Value("${jwt.expires_in}")
- private int EXPIRES_IN;
-
- @Value("${jwt.mobile_expires_in}")
- private int MOBILE_EXPIRES_IN;
-
- @Value("${jwt.header}")
- private String AUTH_HEADER;
-
- static final String AUDIENCE_UNKNOWN = "unknown";
- static final String AUDIENCE_WEB = "web";
- static final String AUDIENCE_MOBILE = "mobile";
- static final String AUDIENCE_TABLET = "tablet";
-
- @Autowired
- TimeProvider timeProvider;
-
- private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;
-
- public String getUsernameFromToken(String token) {
- String username;
- try {
- final Claims claims = this.getAllClaimsFromToken(token);
- username = claims.getSubject();
- } catch (Exception e) {
- username = null;
- }
- return username;
- }
-
- public Date getIssuedAtDateFromToken(String token) {
- Date issueAt;
- try {
- final Claims claims = this.getAllClaimsFromToken(token);
- issueAt = claims.getIssuedAt();
- } catch (Exception e) {
- issueAt = null;
- }
- return issueAt;
- }
-
- public String getAudienceFromToken(String token) {
- String audience;
- try {
- final Claims claims = this.getAllClaimsFromToken(token);
- audience = claims.getAudience();
- } catch (Exception e) {
- audience = null;
- }
- return audience;
- }
-
- public String refreshToken(String token, Device device) {
- String refreshedToken;
- Date a = timeProvider.now();
- try {
- final Claims claims = this.getAllClaimsFromToken(token);
- claims.setIssuedAt(a);
- refreshedToken = Jwts.builder()
- .setClaims(claims)
- .setExpiration(generateExpirationDate(device))
- .signWith( SIGNATURE_ALGORITHM, SECRET )
- .compact();
- } catch (Exception e) {
- refreshedToken = null;
- }
- return refreshedToken;
- }
-
- public String generateToken(String username, Device device) {
- String audience = generateAudience(device);
- return Jwts.builder()
- .setIssuer( APP_NAME )
- .setSubject(username)
- .setAudience(audience)
- .setIssuedAt(timeProvider.now())
- .setExpiration(generateExpirationDate(device))
- .signWith( SIGNATURE_ALGORITHM, SECRET )
- .compact();
- }
-
- private String generateAudience(Device device) {
- String audience = AUDIENCE_UNKNOWN;
- if (device.isNormal()) {
- audience = AUDIENCE_WEB;
- } else if (device.isTablet()) {
- audience = AUDIENCE_TABLET;
- } else if (device.isMobile()) {
- audience = AUDIENCE_MOBILE;
- }
- return audience;
- }
-
- private Claims getAllClaimsFromToken(String token) {
- Claims claims;
- try {
- claims = Jwts.parser()
- .setSigningKey(SECRET)
- .parseClaimsJws(token)
- .getBody();
- } catch (Exception e) {
- claims = null;
- }
- return claims;
- }
-
- private Date generateExpirationDate(Device device) {
- long expiresIn = device.isTablet() || device.isMobile() ? MOBILE_EXPIRES_IN : EXPIRES_IN;
- return new Date(timeProvider.now().getTime() + expiresIn * 1000);
- }
-
- public int getExpiredIn(Device device) {
- return device.isMobile() || device.isTablet() ? MOBILE_EXPIRES_IN : EXPIRES_IN;
- }
-
- public Boolean validateToken(String token, UserDetails userDetails) {
- User user = (User) userDetails;
- final String username = getUsernameFromToken(token);
- final Date created = getIssuedAtDateFromToken(token);
- return (
- username != null &&
- username.equals(userDetails.getUsername()) &&
- !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())
- );
- }
-
- private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
- return (lastPasswordReset != null && created.before(lastPasswordReset));
- }
-
- public String getToken( HttpServletRequest request ) {
- /**
- * Getting the token from Authentication header
- * e.g Bearer your_token
- */
- String authHeader = getAuthHeaderFromHeader( request );
- if ( authHeader != null && authHeader.startsWith("Bearer ")) {
- return authHeader.substring(7);
- }
-
- return null;
- }
-
- public String getAuthHeaderFromHeader( HttpServletRequest request ) {
- return request.getHeader(AUTH_HEADER);
- }
+ @Value("${app.name}")
+ private String APP_NAME;
+
+ @Value("${jwt.secret}")
+ public String SECRET;
+
+ @Value("${jwt.expires_in}")
+ private int EXPIRES_IN;
+
+ @Value("${jwt.header}")
+ private String AUTH_HEADER;
+
+ @Autowired
+ TimeProvider timeProvider;
+
+ private MacAlgorithm SIGNATURE_ALGORITHM = Jwts.SIG.HS512;
+
+ public String getUsernameFromToken(String token) {
+ String username;
+ try {
+ final Claims claims = this.getAllClaimsFromToken(token);
+ username = claims.getSubject();
+ } catch (Exception e) {
+ username = null;
+ }
+ return username;
+ }
+
+ public Date getIssuedAtDateFromToken(String token) {
+ Date issueAt;
+ try {
+ final Claims claims = this.getAllClaimsFromToken(token);
+ issueAt = claims.getIssuedAt();
+ } catch (Exception e) {
+ issueAt = null;
+ }
+ return issueAt;
+ }
+
+ public String refreshToken(String token) {
+ String refreshedToken;
+ Date a = timeProvider.now();
+ try {
+ final Claims claims = getAllClaimsFromToken(token);
+ refreshedToken = Jwts.builder().claims(claims).issuedAt(a).expiration(generateExpirationDate())
+ .signWith(Keys.hmacShaKeyFor(SECRET.getBytes()), SIGNATURE_ALGORITHM).compact();
+ } catch (Exception e) {
+ refreshedToken = null;
+ }
+ return refreshedToken;
+ }
+
+ public String generateToken(String username) {
+ return Jwts.builder().issuer(APP_NAME).subject(username).issuedAt(timeProvider.now())
+ .expiration(generateExpirationDate())
+ .signWith(Keys.hmacShaKeyFor(SECRET.getBytes()), SIGNATURE_ALGORITHM).compact();
+ }
+
+ private Claims getAllClaimsFromToken(String token) {
+ Jws claims;
+ try {
+ claims = Jwts.parser().verifyWith(Keys.hmacShaKeyFor(SECRET.getBytes())).build().parseSignedClaims(token);
+ } catch (Exception e) {
+ claims = null;
+ }
+ return claims.getPayload();
+ }
+
+ private Date generateExpirationDate() {
+ long expiresIn = EXPIRES_IN;
+ return new Date(timeProvider.now().getTime() + expiresIn * 1000);
+ }
+
+ public int getExpiredIn() {
+ return EXPIRES_IN;
+ }
+
+ public Boolean validateToken(String token, UserDetails userDetails) {
+ User user = (User) userDetails;
+ final String username = getUsernameFromToken(token);
+ final Date created = getIssuedAtDateFromToken(token);
+ return (username != null && username.equals(userDetails.getUsername())
+ && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate()));
+ }
+
+ private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
+ return (lastPasswordReset != null && created.before(lastPasswordReset));
+ }
+
+ public String getToken(HttpServletRequest request) {
+ /**
+ * Getting the token from Authentication header e.g Bearer your_token
+ */
+ String authHeader = getAuthHeaderFromHeader(request);
+ if (authHeader != null && authHeader.startsWith("Bearer ")) {
+ return authHeader.substring(7);
+ }
+
+ return null;
+ }
+
+ public String getAuthHeaderFromHeader(HttpServletRequest request) {
+ return request.getHeader(AUTH_HEADER);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/bfwg/security/auth/JwtAuthenticationRequest.java b/src/main/java/com/bfwg/security/auth/JwtAuthenticationRequest.java
index 3fe4433..a3e3ab5 100644
--- a/src/main/java/com/bfwg/security/auth/JwtAuthenticationRequest.java
+++ b/src/main/java/com/bfwg/security/auth/JwtAuthenticationRequest.java
@@ -4,31 +4,31 @@
* Created by fanjin on 2017-10-09.
*/
public class JwtAuthenticationRequest {
- private String username;
- private String password;
+ private String username;
+ private String password;
- public JwtAuthenticationRequest() {
- super();
- }
+ public JwtAuthenticationRequest() {
+ super();
+ }
- public JwtAuthenticationRequest(String username, String password) {
- this.setUsername(username);
- this.setPassword(password);
- }
+ public JwtAuthenticationRequest(String username, String password) {
+ this.setUsername(username);
+ this.setPassword(password);
+ }
- public String getUsername() {
- return this.username;
- }
+ public String getUsername() {
+ return this.username;
+ }
- public void setUsername(String username) {
- this.username = username;
- }
+ public void setUsername(String username) {
+ this.username = username;
+ }
- public String getPassword() {
- return this.password;
- }
+ public String getPassword() {
+ return this.password;
+ }
- public void setPassword(String password) {
- this.password = password;
- }
+ public void setPassword(String password) {
+ this.password = password;
+ }
}
diff --git a/src/main/java/com/bfwg/security/auth/RestAuthenticationEntryPoint.java b/src/main/java/com/bfwg/security/auth/RestAuthenticationEntryPoint.java
index 2e99c8d..b3fd74f 100644
--- a/src/main/java/com/bfwg/security/auth/RestAuthenticationEntryPoint.java
+++ b/src/main/java/com/bfwg/security/auth/RestAuthenticationEntryPoint.java
@@ -1,5 +1,7 @@
package com.bfwg.security.auth;
+import java.io.IOException;
+
/**
* Created by fan.jin on 2016-11-12.
*/
@@ -8,9 +10,8 @@
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
/**
* Created by fan.jin on 2016-11-07.
@@ -18,13 +19,13 @@
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
- @Override
- public void commence(HttpServletRequest request,
- HttpServletResponse response,
- AuthenticationException authException) throws IOException {
- // This is invoked when user tries to access a secured REST resource without supplying any credentials
- // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
- }
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException authException) throws IOException {
+ // This is invoked when user tries to access a secured REST resource without
+ // supplying any credentials
+ // We should just send a 401 Unauthorized response because there is no 'login
+ // page' to redirect to
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
+ }
}
-
diff --git a/src/main/java/com/bfwg/security/auth/TokenAuthenticationFilter.java b/src/main/java/com/bfwg/security/auth/TokenAuthenticationFilter.java
index 0da6b4f..95be82b 100644
--- a/src/main/java/com/bfwg/security/auth/TokenAuthenticationFilter.java
+++ b/src/main/java/com/bfwg/security/auth/TokenAuthenticationFilter.java
@@ -1,6 +1,7 @@
package com.bfwg.security.auth;
-import com.bfwg.security.TokenHelper;
+import java.io.IOException;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -8,54 +9,51 @@
import org.springframework.security.core.userdetails.UserDetailsService;
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 com.bfwg.security.TokenHelper;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
/**
* Created by fan.jin on 2016-10-19.
*/
public class TokenAuthenticationFilter extends OncePerRequestFilter {
- private final Log logger = LogFactory.getLog(this.getClass());
-
- private TokenHelper tokenHelper;
-
- private UserDetailsService userDetailsService;
-
- public TokenAuthenticationFilter(TokenHelper tokenHelper, UserDetailsService userDetailsService) {
- this.tokenHelper = tokenHelper;
- this.userDetailsService = userDetailsService;
- }
-
-
- @Override
- public void doFilterInternal(
- HttpServletRequest request,
- HttpServletResponse response,
- FilterChain chain
- ) throws IOException, ServletException {
-
- String username;
- String authToken = tokenHelper.getToken(request);
-
- if (authToken != null) {
- // get username from token
- username = tokenHelper.getUsernameFromToken(authToken);
- if (username != null) {
- // get user
- UserDetails userDetails = userDetailsService.loadUserByUsername(username);
- if (tokenHelper.validateToken(authToken, userDetails)) {
- // create authentication
- TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
- authentication.setToken(authToken);
- SecurityContextHolder.getContext().setAuthentication(authentication);
- }
- }
- }
- chain.doFilter(request, response);
- }
+ private final Log logger = LogFactory.getLog(this.getClass());
+
+ private TokenHelper tokenHelper;
+
+ private UserDetailsService userDetailsService;
+
+ public TokenAuthenticationFilter(TokenHelper tokenHelper, UserDetailsService userDetailsService) {
+ this.tokenHelper = tokenHelper;
+ this.userDetailsService = userDetailsService;
+ }
+
+ @Override
+ public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+
+ String username;
+ String authToken = tokenHelper.getToken(request);
+
+ if (authToken != null) {
+ // get username from token
+ username = tokenHelper.getUsernameFromToken(authToken);
+ if (username != null) {
+ // get user
+ UserDetails userDetails = userDetailsService.loadUserByUsername(username);
+ if (tokenHelper.validateToken(authToken, userDetails)) {
+ // create authentication
+ TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
+ authentication.setToken(authToken);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+ }
+ }
+ chain.doFilter(request, response);
+ }
}
\ No newline at end of file
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 5ea37fe..39ad835 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -5,4 +5,4 @@ jwt:
header: Authorization
expires_in: 300 # 5 minutes
mobile_expires_in: 600 # 10 minutes
- secret: queenvictoria
+ secret: p2H(++:$j*xKfKvK6n5k=},@@]CWkbj7d0iQ%6/;0}x6?[wNWR,$=0/HHx*&pJAq
diff --git a/src/test/java/com/bfwg/ApplicationTest.java b/src/test/java/com/bfwg/ApplicationTest.java
index 32a710d..cec6329 100644
--- a/src/test/java/com/bfwg/ApplicationTest.java
+++ b/src/test/java/com/bfwg/ApplicationTest.java
@@ -12,7 +12,7 @@
@SpringBootTest
public class ApplicationTest {
- @Test
- public void contextLoads() {
- }
+ @Test
+ public void contextLoads() {
+ }
}
diff --git a/src/test/java/com/bfwg/rest/AuthenticationControllerTest.java b/src/test/java/com/bfwg/rest/AuthenticationControllerTest.java
index e0a4ed6..de1f9a1 100644
--- a/src/test/java/com/bfwg/rest/AuthenticationControllerTest.java
+++ b/src/test/java/com/bfwg/rest/AuthenticationControllerTest.java
@@ -1,6 +1,5 @@
package com.bfwg.rest;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.when;
@@ -22,7 +21,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.mobile.device.Device;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
@@ -30,12 +28,10 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import com.bfwg.common.DeviceProvider;
import com.bfwg.common.TimeProvider;
import com.bfwg.model.Authority;
import com.bfwg.model.User;
import com.bfwg.model.UserRoleName;
-import com.bfwg.security.DeviceDummy;
import com.bfwg.security.TokenHelper;
import com.bfwg.service.impl.CustomUserDetailsService;
@@ -65,19 +61,10 @@ public class AuthenticationControllerTest {
@Autowired
private WebApplicationContext context;
- @MockBean
- private DeviceProvider deviceProvider;
-
- @Autowired
- private DeviceDummy device;
-
@Before
public void setup() {
- mvc = MockMvcBuilders
- .webAppContextSetup(context)
- .apply(springSecurity())
- .build();
+ mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
User user = new User();
user.setUsername("username");
@@ -88,23 +75,18 @@ public void setup() {
user.setAuthorities(authorities);
user.setLastPasswordResetDate(new Timestamp(DateUtil.yesterday().getTime()));
when(this.userDetailsService.loadUserByUsername(eq("testUser"))).thenReturn(user);
- MockitoAnnotations.initMocks(this);
+ MockitoAnnotations.openMocks(this);
ReflectionTestUtils.setField(tokenHelper, "EXPIRES_IN", 100); // 100 sec
- ReflectionTestUtils.setField(tokenHelper, "MOBILE_EXPIRES_IN", 200); // 200 sec
- ReflectionTestUtils.setField(tokenHelper, "SECRET", "queenvictoria");
+ ReflectionTestUtils.setField(tokenHelper, "SECRET",
+ "wb!.V.G]e&;4Q78&b,n[6F]PQg613!)-Gpy*CN{/[@LN.Z1Mn*aKH!*zg/pXLp/4");
- device.setMobile(false);
- device.setNormal(false);
- device.setTablet(false);
}
@Test
public void shouldGetEmptyTokenStateWhenGivenValidOldToken() throws Exception {
- when(timeProviderMock.now())
- .thenReturn(DateUtil.yesterday());
- this.mvc.perform(post("/auth/refresh")
- .header("Authorization", "Bearer 123"))
+ when(timeProviderMock.now()).thenReturn(DateUtil.yesterday());
+ this.mvc.perform(post("/auth/refresh").header("Authorization", "Bearer 123"))
.andExpect(content().json("{access_token:null,expires_in:null}"));
}
@@ -112,58 +94,24 @@ public void shouldGetEmptyTokenStateWhenGivenValidOldToken() throws Exception {
@WithMockUser(roles = "USER")
public void shouldRefreshNotExpiredWebToken() throws Exception {
- given(timeProviderMock.now())
- .willReturn(new Date(30L));
+ given(timeProviderMock.now()).willReturn(new Date(30L));
- device.setNormal(true);
- String token = createToken(device);
- String refreshedToken = tokenHelper.refreshToken(token, device);
- given(deviceProvider.getCurrentDevice(any()))
- .willReturn(device);
- this.mvc.perform(post("/auth/refresh")
- .header("Authorization", "Bearer " + token))
+ String token = createToken();
+ String refreshedToken = tokenHelper.refreshToken(token);
+ this.mvc.perform(post("/auth/refresh").header("Authorization", "Bearer " + token))
.andExpect(content().json("{access_token:" + refreshedToken + ",expires_in:100}"));
}
- @Test
- @WithMockUser(roles = "USER")
- public void shouldRefreshNotExpiredMobileToken() throws Exception {
- given(timeProviderMock.now())
- .willReturn(new Date(30L));
- device.setMobile(true);
- String token = createToken(device);
- String refreshedToken = tokenHelper.refreshToken(token, device);
- given(deviceProvider.getCurrentDevice(any()))
- .willReturn(device);
- this.mvc.perform(post("/auth/refresh")
- .header("Authorization", "Bearer " + token))
- .andExpect(content().json("{access_token:" + refreshedToken + ",expires_in:200}"));
- }
-
@Test
public void shouldNotRefreshExpiredWebToken() throws Exception {
Date beforeSomeTime = new Date(DateUtil.now().getTime() - 15 * 1000);
- when(timeProviderMock.now())
- .thenReturn(beforeSomeTime);
- device.setNormal(true);
- String token = createToken(device);
- this.mvc.perform(post("/auth/refresh")
- .header("Authorization", "Bearer " + token))
- .andExpect(content().json("{access_token:null,expires_in:null}"));
- }
-
- @Test
- public void shouldRefreshExpiredMobileToken() throws Exception {
- Date beforeSomeTime = new Date(DateUtil.now().getTime() - 15 * 1000);
- when(timeProviderMock.now())
- .thenReturn(beforeSomeTime);
- device.setNormal(true);
- String token = createToken(device);
+ when(timeProviderMock.now()).thenReturn(beforeSomeTime);
+ String token = createToken();
this.mvc.perform(post("/auth/refresh").header("Authorization", "Bearer " + token))
.andExpect(content().json("{access_token:null,expires_in:null}"));
}
- private String createToken(Device device) {
- return tokenHelper.generateToken(TEST_USERNAME, device);
+ private String createToken() {
+ return tokenHelper.generateToken(TEST_USERNAME);
}
}
diff --git a/src/test/java/com/bfwg/rest/UserControllerTest.java b/src/test/java/com/bfwg/rest/UserControllerTest.java
index 58c179d..c07b8df 100644
--- a/src/test/java/com/bfwg/rest/UserControllerTest.java
+++ b/src/test/java/com/bfwg/rest/UserControllerTest.java
@@ -23,53 +23,44 @@
@SpringBootTest
public class UserControllerTest {
- private MockMvc mvc;
+ private MockMvc mvc;
- @Autowired
- private WebApplicationContext context;
+ @Autowired
+ private WebApplicationContext context;
- @Before
- public void setup() {
- mvc = MockMvcBuilders
- .webAppContextSetup(context)
- .apply(springSecurity())
- .build();
- }
+ @Before
+ public void setup() {
+ mvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).build();
+ }
- @Test
- @WithAnonymousUser
- public void shouldGetUnauthorizedWithoutRole() throws Exception {
+ @Test
+ @WithAnonymousUser
+ public void shouldGetUnauthorizedWithoutRole() throws Exception {
- this.mvc.perform(get("/user"))
- .andExpect(status().isUnauthorized());
- }
+ this.mvc.perform(get("/user")).andExpect(status().isUnauthorized());
+ }
- @Test
- @WithMockUser(roles = "USER")
- public void getPersonsSuccessfullyWithUserRole() throws Exception {
- this.mvc.perform(get("/api/whoami"))
- .andExpect(status().is2xxSuccessful());
- }
+ @Test
+ @WithMockUser(roles = "USER")
+ public void getPersonsSuccessfullyWithUserRole() throws Exception {
+ this.mvc.perform(get("/api/whoami")).andExpect(status().is2xxSuccessful());
+ }
- @Test
- @WithAnonymousUser
- public void getPersonsFailWithAnonymousUser() throws Exception {
- this.mvc.perform(get("/api/whoami"))
- .andExpect(status().is4xxClientError());
- }
+ @Test
+ @WithAnonymousUser
+ public void getPersonsFailWithAnonymousUser() throws Exception {
+ this.mvc.perform(get("/api/whoami")).andExpect(status().is4xxClientError());
+ }
- @Test
- @WithMockUser(roles = "ADMIN")
- public void getAllUserSuccessWithAdminRole() throws Exception {
- this.mvc.perform(get("/api/user/all"))
- .andExpect(status().is2xxSuccessful());
- }
+ @Test
+ @WithMockUser(roles = "ADMIN")
+ public void getAllUserSuccessWithAdminRole() throws Exception {
+ this.mvc.perform(get("/api/user/all")).andExpect(status().is2xxSuccessful());
+ }
- @Test
- @WithMockUser(roles = "USER")
- public void getAllUserFailWithUserRole() throws Exception {
- this.mvc.perform(get("/api/user/all"))
- .andExpect(status().is4xxClientError());
- }
+ @Test
+ @WithMockUser(roles = "USER")
+ public void getAllUserFailWithUserRole() throws Exception {
+ this.mvc.perform(get("/api/user/all")).andExpect(status().is4xxClientError());
+ }
}
-
diff --git a/src/test/java/com/bfwg/security/DeviceDummy.java b/src/test/java/com/bfwg/security/DeviceDummy.java
deleted file mode 100644
index 0ec0f28..0000000
--- a/src/test/java/com/bfwg/security/DeviceDummy.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.bfwg.security;
-
-import org.springframework.mobile.device.Device;
-import org.springframework.mobile.device.DevicePlatform;
-import org.springframework.stereotype.Component;
-
-/**
- * Created by fanjin on 2017-10-07.
- */
-@Component
-public class DeviceDummy implements Device {
- private boolean normal;
- private boolean mobile;
- private boolean tablet;
-
- @Override
- public boolean isNormal() {
- return normal;
- }
-
- @Override
- public boolean isMobile() {
- return mobile;
- }
-
- @Override
- public boolean isTablet() {
- return tablet;
- }
-
- @Override
- public DevicePlatform getDevicePlatform() {
- return null;
- }
-
- public void setNormal(boolean normal) {
- this.normal = normal;
- }
-
- public void setMobile(boolean mobile) {
- this.mobile = mobile;
- }
-
- public void setTablet(boolean tablet) {
- this.tablet = tablet;
- }
-}
diff --git a/src/test/java/com/bfwg/security/TokenHelperTest.java b/src/test/java/com/bfwg/security/TokenHelperTest.java
index d22ee90..d423442 100644
--- a/src/test/java/com/bfwg/security/TokenHelperTest.java
+++ b/src/test/java/com/bfwg/security/TokenHelperTest.java
@@ -1,161 +1,118 @@
package com.bfwg.security;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.sql.Timestamp;
+import java.util.Date;
-import com.bfwg.common.TimeProvider;
-import com.bfwg.model.User;
import org.assertj.core.util.DateUtil;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.springframework.mobile.device.Device;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.util.ReflectionTestUtils;
-import java.sql.Timestamp;
-import java.util.Date;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import com.bfwg.common.TimeProvider;
+import com.bfwg.model.User;
/**
* Created by fan.jin on 2017-01-08.
*/
public class TokenHelperTest {
- private static final String TEST_USERNAME = "testUser";
+ private static final String TEST_USERNAME = "testUser";
+
+ @InjectMocks
+ private TokenHelper tokenHelper;
+
+ @Mock
+ private TimeProvider timeProviderMock;
+
+ @Before
+ public void init() {
+ MockitoAnnotations.openMocks(this);
+
+ ReflectionTestUtils.setField(tokenHelper, "EXPIRES_IN", 10); // 10 sec
+ ReflectionTestUtils.setField(tokenHelper, "SECRET",
+ "Y0[yCzX7Ym;${,[+hj*(E*erX:-%-JU=K!}Sp/m:$gZ.D[EW,fQec3Ha1.rwy)TX");
+ }
+
+ @Test
+ public void testGenerateTokenGeneratesDifferentTokensForDifferentCreationDates() throws Exception {
+ when(timeProviderMock.now()).thenReturn(DateUtil.yesterday()).thenReturn(DateUtil.now());
+
+ final String token = createToken();
+ final String laterToken = createToken();
+
+ assertThat(token).isNotEqualTo(laterToken);
+ }
+
+ @Test
+ public void tokenShouldExpire() {
+ Date beforeSomeTime = new Date(DateUtil.now().getTime() - 20 * 1000);
+
+ when(timeProviderMock.now()).thenReturn(beforeSomeTime);
+
+ UserDetails userDetails = mock(User.class);
+ when(userDetails.getUsername()).thenReturn(TEST_USERNAME);
+
+ final String mobileToken = createToken();
+ assertThat(tokenHelper.validateToken(mobileToken, userDetails)).isFalse();
+ }
+
+ @Test
+ public void getUsernameFromToken() throws Exception {
+ when(timeProviderMock.now()).thenReturn(DateUtil.now());
+
+ final String token = createToken();
+
+ assertThat(tokenHelper.getUsernameFromToken(token)).isEqualTo(TEST_USERNAME);
+ }
+
+ @Test
+ public void getCreatedDateFromToken() {
+ final Date now = DateUtil.now();
+ when(timeProviderMock.now()).thenReturn(now);
+
+ final String token = createToken();
+
+ assertThat(tokenHelper.getIssuedAtDateFromToken(token)).isInSameMinuteWindowAs(now);
+ }
- @InjectMocks
- private TokenHelper tokenHelper;
+ @Test
+ public void expiredTokenCannotBeRefreshed() {
+ when(timeProviderMock.now()).thenReturn(DateUtil.yesterday());
- @Mock
- private TimeProvider timeProviderMock;
+ String token = createToken();
+ tokenHelper.refreshToken(token);
+ }
- @InjectMocks
- DeviceDummy device;
+ @Test
+ public void changedPasswordCannotBeRefreshed() throws Exception {
+ when(timeProviderMock.now()).thenReturn(DateUtil.now());
- @Before
- public void init() {
- MockitoAnnotations.initMocks(this);
+ User user = mock(User.class);
+ when(user.getLastPasswordResetDate()).thenReturn(new Timestamp(DateUtil.tomorrow().getTime()));
+ String token = createToken();
+ assertThat(tokenHelper.validateToken(token, user)).isFalse();
+ }
- ReflectionTestUtils.setField(tokenHelper, "EXPIRES_IN", 10); // 10 sec
- ReflectionTestUtils.setField(tokenHelper, "MOBILE_EXPIRES_IN", 20); // 20 sec
- ReflectionTestUtils.setField(tokenHelper, "SECRET", "mySecret");
- }
+ @Test
+ public void canRefreshToken() throws Exception {
+ when(timeProviderMock.now()).thenReturn(DateUtil.now()).thenReturn(DateUtil.tomorrow());
+ String firstToken = createToken();
+ String refreshedToken = tokenHelper.refreshToken(firstToken);
+ Date firstTokenDate = tokenHelper.getIssuedAtDateFromToken(firstToken);
+ Date refreshedTokenDate = tokenHelper.getIssuedAtDateFromToken(refreshedToken);
+ assertThat(firstTokenDate).isBefore(refreshedTokenDate);
+ }
- @Test
- public void testGenerateTokenGeneratesDifferentTokensForDifferentCreationDates() throws Exception {
- when(timeProviderMock.now())
- .thenReturn(DateUtil.yesterday())
- .thenReturn(DateUtil.now());
-
- final String token = createToken(device);
- final String laterToken = createToken(device);
-
- assertThat(token).isNotEqualTo(laterToken);
- }
-
- @Test
- public void mobileTokenShouldLiveLonger() {
- Date beforeSomeTime = new Date(DateUtil.now().getTime() - 15 * 1000);
-
- UserDetails userDetails = mock(User.class);
- when(userDetails.getUsername()).thenReturn(TEST_USERNAME);
-
- when(timeProviderMock.now())
- .thenReturn(beforeSomeTime);
- device.setMobile(true);
- final String mobileToken = createToken(device);
- assertThat(tokenHelper.validateToken(mobileToken, userDetails)).isTrue();
- }
-
- @Test
- public void mobileTokenShouldExpire() {
- Date beforeSomeTime = new Date(DateUtil.now().getTime() - 20 * 1000);
-
- when(timeProviderMock.now())
- .thenReturn(beforeSomeTime);
-
- UserDetails userDetails = mock(User.class);
- when(userDetails.getUsername()).thenReturn(TEST_USERNAME);
-
- device.setMobile(true);
- final String mobileToken = createToken(device);
- assertThat(tokenHelper.validateToken(mobileToken, userDetails)).isFalse();
- }
-
- @Test
- public void getUsernameFromToken() throws Exception {
- when(timeProviderMock.now()).thenReturn(DateUtil.now());
-
- final String token = createToken(device);
-
- assertThat(tokenHelper.getUsernameFromToken(token)).isEqualTo(TEST_USERNAME);
- }
-
- @Test
- public void getCreatedDateFromToken() {
- final Date now = DateUtil.now();
- when(timeProviderMock.now()).thenReturn(now);
-
- final String token = createToken(device);
-
- assertThat(tokenHelper.getIssuedAtDateFromToken(token)).isInSameMinuteWindowAs(now);
- }
-
- @Test
- public void expiredTokenCannotBeRefreshed() {
- when(timeProviderMock.now())
- .thenReturn(DateUtil.yesterday());
-
- String token = createToken(device);
- tokenHelper.refreshToken(token, device);
- }
-
- @Test
- public void getAudienceFromToken() throws Exception {
- when(timeProviderMock.now()).thenReturn(DateUtil.now());
- device.setNormal(true);
- final String token = createToken(this.device);
-
- assertThat(tokenHelper.getAudienceFromToken(token)).isEqualTo(tokenHelper.AUDIENCE_WEB);
- }
-
- @Test
- public void getAudienceFromMobileToken() throws Exception {
- when(timeProviderMock.now()).thenReturn(DateUtil.now());
- device.setMobile(true);
- final String token = createToken(this.device);
- assertThat(tokenHelper.getAudienceFromToken(token)).isEqualTo(tokenHelper.AUDIENCE_MOBILE);
- }
-
- @Test
- public void changedPasswordCannotBeRefreshed() throws Exception {
- when(timeProviderMock.now())
- .thenReturn(DateUtil.now());
-
- User user = mock(User.class);
- when(user.getLastPasswordResetDate()).thenReturn(new Timestamp(DateUtil.tomorrow().getTime()));
- String token = createToken(device);
- assertThat(tokenHelper.validateToken(token, user)).isFalse();
- }
-
- @Test
- public void canRefreshToken() throws Exception {
- when(timeProviderMock.now())
- .thenReturn(DateUtil.now())
- .thenReturn(DateUtil.tomorrow());
- String firstToken = createToken(device);
- String refreshedToken = tokenHelper.refreshToken(firstToken, device);
- Date firstTokenDate = tokenHelper.getIssuedAtDateFromToken(firstToken);
- Date refreshedTokenDate = tokenHelper.getIssuedAtDateFromToken(refreshedToken);
- assertThat(firstTokenDate).isBefore(refreshedTokenDate);
- }
-
- private String createToken(Device device) {
- return tokenHelper.generateToken(TEST_USERNAME, device);
- }
+ private String createToken() {
+ return tokenHelper.generateToken(TEST_USERNAME);
+ }
}
diff --git a/src/test/java/com/bfwg/security/UserDetailsDummy.java b/src/test/java/com/bfwg/security/UserDetailsDummy.java
index 612be45..a4fda0d 100644
--- a/src/test/java/com/bfwg/security/UserDetailsDummy.java
+++ b/src/test/java/com/bfwg/security/UserDetailsDummy.java
@@ -10,44 +10,44 @@
*/
public class UserDetailsDummy implements UserDetails {
- private final String username;
-
- public UserDetailsDummy(String username) {
- this.username = username;
- }
-
- @Override
- public Collection extends GrantedAuthority> getAuthorities() {
- return null;
- }
-
- @Override
- public String getPassword() {
- return null;
- }
-
- @Override
- public String getUsername() {
- return username;
- }
-
- @Override
- public boolean isAccountNonExpired() {
- return false;
- }
-
- @Override
- public boolean isAccountNonLocked() {
- return false;
- }
-
- @Override
- public boolean isCredentialsNonExpired() {
- return false;
- }
-
- @Override
- public boolean isEnabled() {
- return false;
- }
+ private final String username;
+
+ public UserDetailsDummy(String username) {
+ this.username = username;
+ }
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return null;
+ }
+
+ @Override
+ public String getPassword() {
+ return null;
+ }
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return false;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return false;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
}