I want to test protected endpoints in my application and I would like login before each test, get token and use this token in next tests.
@ContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Stepwise
class IntegrationSpec extends Specification {
@Autowired
private TestRestTemplate rest
@Autowired
private String token
@Shared
private HttpEntity request
def setup() {
UserData userData = new UserData("Username", "Password");
def response = rest.postForEntity('/login', userData, Object)
String tempToken = response.getHeaders().get('Authorization')
// remove prefix of token
this.token = tempToken.substring(tempToken.lastIndexOf(" ") + 1)
String loginToken = token.substring(token.lastIndexOf(" ") + 1)
final MultiValueMap<String, String> headers = new LinkedMultiValueMap<>()
headers.add('Authorization', loginToken)
this.request = new HttpEntity(headers)
}
def 'protected resource test'() {
when:
def response = rest.exchange('/protected/resource', HttpMethod.GET, request, new ParameterizedTypeReference<String>() {})
then:
response.getStatusCode() == HttpStatus.OK
}
}
but I get an error :
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:354) ~[jjwt-0.7.0.jar:0.7.0]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481) ~[jjwt-0.7.0.jar:0.7.0]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541) ~[jjwt-0.7.0.jar:0.7.0]
at mypackages.TokenAuthenticationService.getAuthentication(TokenAuthenticationService.java:39) ~[classes/:na]
at mypackages.filters.JWTAuthenticationFilter.doFilter(JWTAuthenticationFilter.java:23) ~[classes/:na]
my TokenService looks following:
public class TokenAuthenticationService {
static final long EXPIRATION_TIME = 10000000;
static final String SECRET = "secret_word";
static final String TOKEN_PREFIX = "Bearer";
static final String HEADER_STRING = "Authorization";
public static void addAuthentication(HttpServletResponse res, String username) {
String JWT = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
}
public static Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
String user = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
return user != null ?
new UsernamePasswordAuthenticationToken(user, null, new ArrayList<GrantedAuthority>()) :
null;
}
return null;
}
}
JWTAuthenticationFilter:
public class JWTAuthenticationFilter extends GenericFilterBean {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) servletRequest);
SecurityContextHolder.getContext()
.setAuthentication(authentication);
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserDetailsService customUserDetailsService() {
return new CustomUserDetailsService();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.POST, "/register").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService());
}
}
username
contains invalid characters or the JWT has been altered between server and client. You can check it in jwt.io. The site shows the payload as empty – Everetteeverglade