Secure REST API calls - mumayank/Rest-Api-Documentation GitHub Wiki
Add in dependencies
tag:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
tokenSecret=QWEDSaskdf842#$%
class Constants {
companion object {
private val oneSecond = 1000.toLong()
private val oneMinute = 60 * oneSecond
private val oneHour = 60 * oneMinute
private val oneDay = 24 * oneHour
private val oneWeek = 7 * oneDay
private val oneMonth = 30 * oneDay
val expiryTime = oneWeek
val tokenPrefix = "Bearer "
val headerString = "Authorization"
val signUpUrl = "/users"
fun getTokenSecret(applicationContext: ApplicationContext): String {
return applicationContext.environment.getProperty("tokenSecret") ?: ""
}
}
}
public class UserSignIn {
private String email;
private String password;
// getters/ setters
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
UserRepository userRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurity(BCryptPasswordEncoder bCryptPasswordEncoder) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, Constants.Companion.getSignUpUrl()).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(getAuthenticationFilter())
.addFilter(new BasicAuthenticationFilter(authenticationManager()) {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader(Constants.Companion.getHeaderString());
if (header == null || header.startsWith(Constants.Companion.getTokenPrefix()) == false) {
SecurityContextHolder.getContext().setAuthentication(null);
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
chain.doFilter(request, response);
}
})
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(email -> {
UserEntity userEntity = userRepository.findByEmail(email);
if (userEntity == null) {
throw new UsernameNotFoundException(email);
} else {
return new User(userEntity.getEmail(), userEntity.getPassword(), new ArrayList<>());
}
}).passwordEncoder(bCryptPasswordEncoder);
}
private UsernamePasswordAuthenticationFilter getAuthenticationFilter() {
UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilter() {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserSignIn userSignIn = new ObjectMapper().readValue(request.getInputStream(), UserSignIn.class);
return authenticationManager().authenticate(new UsernamePasswordAuthenticationToken(
userSignIn.getEmail(),
userSignIn.getPassword(),
new ArrayList<>()
));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String username = ((User) authResult.getPrincipal()).getUsername();
String token = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + Constants.Companion.getExpiryTime()))
.signWith(SignatureAlgorithm.HS512, Constants.Companion.getTokenSecret(getApplicationContext()))
.compact();
response.addHeader(Constants.Companion.getHeaderString(), Constants.Companion.getTokenPrefix() + token);
}
};
usernamePasswordAuthenticationFilter.setFilterProcessesUrl("/users/login");
return usernamePasswordAuthenticationFilter;
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest httpServletRequest) {
String token = httpServletRequest.getHeader(Constants.Companion.getHeaderString());
if (token != null) {
token = token.replace(Constants.Companion.getTokenPrefix(), "");
String user = Jwts.parser()
.setSigningKey(Constants.Companion.getTokenSecret(getApplicationContext()))
.parseClaimsJws(token)
.getBody()
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
Always store encrypted passwords in DB:
userEntity.password = bCryptPasswordEncoder.encode(userEntity.password)