Skip to content

Commit d339a47

Browse files
committed
oauth token with jwt more security less brain
1 parent eed8feb commit d339a47

File tree

11 files changed

+225
-56
lines changed

11 files changed

+225
-56
lines changed

BankApplicationBackend/pom.xml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,20 @@
3535
<!-- <groupId>org.springframework.boot</groupId> -->
3636
<!-- <artifactId>spring-boot-starter-thymeleaf</artifactId> -->
3737
<!-- </dependency> -->
38-
<!-- <dependency> -->
39-
<!-- <groupId>org.springframework.boot</groupId> -->
40-
<!-- <artifactId>spring-boot-starter-security</artifactId> -->
41-
<!-- </dependency> -->
38+
<dependency>
39+
<groupId>org.springframework.boot</groupId>
40+
<artifactId>spring-boot-starter-security</artifactId>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.springframework.security</groupId>
44+
<artifactId>spring-security-jwt</artifactId>
45+
<version>1.0.7.RELEASE</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>com.auth0</groupId>
49+
<artifactId>java-jwt</artifactId>
50+
<version>3.4.0</version>
51+
</dependency>
4252

4353
<dependency>
4454
<groupId>mysql</groupId>

BankApplicationBackend/src/main/java/com/demo/bankapp/BankApplication.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
7+
import org.springframework.security.crypto.password.PasswordEncoder;
58

69
@SpringBootApplication
710
public class BankApplication {

BankApplicationBackend/src/main/java/com/demo/bankapp/assembler/UserResourceAssembler.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ public class UserResourceAssembler implements ResourceAssembler<User, Resource<U
1717
public Resource<User> toResource(User user) {
1818
return new Resource<>(user,
1919
linkTo(methodOn(UserController.class).createNewUser(null)).withSelfRel(),
20-
linkTo(methodOn(UserController.class).findAll()).withRel("users"),
21-
linkTo(methodOn(UserController.class).login(null)).withRel("login"));
20+
linkTo(methodOn(UserController.class).findAll()).withRel("users"));
2221
}
2322
}

BankApplicationBackend/src/main/java/com/demo/bankapp/configuration/SecurityConfig.java

Lines changed: 0 additions & 17 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.demo.bankapp.configuration.security;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.Date;
6+
7+
import com.fasterxml.jackson.databind.ObjectMapper;
8+
9+
import javax.servlet.FilterChain;
10+
import javax.servlet.ServletException;
11+
import javax.servlet.http.HttpServletRequest;
12+
import javax.servlet.http.HttpServletResponse;
13+
14+
import org.springframework.security.authentication.AuthenticationManager;
15+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
16+
import org.springframework.security.core.Authentication;
17+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
18+
19+
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
20+
import static com.demo.bankapp.configuration.security.SecurityConstants.EXPIRATION_TIME;
21+
import static com.demo.bankapp.configuration.security.SecurityConstants.HEADER_STRING;
22+
import static com.demo.bankapp.configuration.security.SecurityConstants.SECRET;
23+
import static com.demo.bankapp.configuration.security.SecurityConstants.TOKEN_PREFIX;
24+
25+
import com.auth0.jwt.JWT;
26+
import com.demo.bankapp.model.User;
27+
28+
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
29+
30+
private AuthenticationManager authenticationManager;
31+
32+
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
33+
this.authenticationManager = authenticationManager;
34+
}
35+
36+
@Override
37+
public Authentication attemptAuthentication(HttpServletRequest req,
38+
HttpServletResponse res) {
39+
40+
try {
41+
User creds = new ObjectMapper().readValue(req.getInputStream(), User.class);
42+
43+
return authenticationManager.authenticate(
44+
new UsernamePasswordAuthenticationToken(
45+
creds.getUsername(),
46+
creds.getPassword(),
47+
new ArrayList<>())
48+
);
49+
} catch (IOException e) {
50+
throw new RuntimeException(e);
51+
}
52+
}
53+
54+
@Override
55+
protected void successfulAuthentication(HttpServletRequest req,
56+
HttpServletResponse res,
57+
FilterChain chain,
58+
Authentication auth) throws IOException, ServletException {
59+
60+
String token = JWT.create()
61+
.withSubject(((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername())
62+
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
63+
.sign(HMAC512(SECRET.getBytes()));
64+
res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.demo.bankapp.configuration.security;
2+
3+
import com.auth0.jwt.JWT;
4+
import com.auth0.jwt.algorithms.Algorithm;
5+
import org.springframework.security.authentication.AuthenticationManager;
6+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
7+
import org.springframework.security.core.context.SecurityContextHolder;
8+
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
9+
10+
import javax.servlet.FilterChain;
11+
import javax.servlet.ServletException;
12+
import javax.servlet.http.HttpServletRequest;
13+
import javax.servlet.http.HttpServletResponse;
14+
15+
import static com.demo.bankapp.configuration.security.SecurityConstants.HEADER_STRING;
16+
import static com.demo.bankapp.configuration.security.SecurityConstants.SECRET;
17+
import static com.demo.bankapp.configuration.security.SecurityConstants.TOKEN_PREFIX;
18+
19+
import java.io.IOException;
20+
import java.util.ArrayList;
21+
22+
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
23+
24+
public JWTAuthorizationFilter(AuthenticationManager authManager) {
25+
super(authManager);
26+
}
27+
28+
@Override
29+
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
30+
String header = req.getHeader(HEADER_STRING);
31+
32+
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
33+
chain.doFilter(req, res);
34+
return;
35+
}
36+
37+
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
38+
39+
SecurityContextHolder.getContext().setAuthentication(authentication);
40+
chain.doFilter(req, res);
41+
}
42+
43+
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
44+
String token = request.getHeader(HEADER_STRING);
45+
if (token != null) {
46+
// parse the token.
47+
String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes())).build().verify(token.replace(TOKEN_PREFIX, "")).getSubject();
48+
49+
if (user != null) {
50+
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
51+
}
52+
return null;
53+
}
54+
return null;
55+
}
56+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.demo.bankapp.configuration.security;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.http.HttpMethod;
6+
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
7+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
9+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
10+
import org.springframework.security.config.http.SessionCreationPolicy;
11+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
12+
import org.springframework.security.crypto.password.PasswordEncoder;
13+
import org.springframework.web.cors.CorsConfiguration;
14+
import org.springframework.web.cors.CorsConfigurationSource;
15+
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
16+
17+
import com.demo.bankapp.service.concretions.UserService;
18+
19+
@EnableWebSecurity
20+
public class SecurityConfig extends WebSecurityConfigurerAdapter {
21+
22+
@Autowired
23+
private UserService userService;
24+
25+
@Autowired
26+
private PasswordEncoder passwordEncoder;
27+
28+
@Override
29+
protected void configure(HttpSecurity http) throws Exception {
30+
http.cors().and().csrf().disable().anonymous().and().authorizeRequests()
31+
.antMatchers("/wealth/**").authenticated()
32+
.antMatchers("/transfer/**").authenticated()
33+
.antMatchers("/transaction/**").authenticated()
34+
.antMatchers("/user/find/all").authenticated()
35+
.antMatchers("/user/login").authenticated()
36+
.antMatchers(HttpMethod.POST, "/user/create").permitAll()
37+
.and()
38+
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
39+
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
40+
// this disables session creation on Spring Security
41+
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
42+
}
43+
44+
@Override
45+
public void configure(AuthenticationManagerBuilder auth) throws Exception {
46+
auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
47+
}
48+
49+
@Bean
50+
CorsConfigurationSource corsConfigurationSource() {
51+
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
52+
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
53+
return source;
54+
}
55+
56+
@Bean
57+
public PasswordEncoder passwordEncoder() {
58+
return new BCryptPasswordEncoder();
59+
}
60+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.demo.bankapp.configuration.security;
2+
3+
public class SecurityConstants {
4+
public static final String SECRET = "SecretKeyToGenJWTs";
5+
public static final long EXPIRATION_TIME = 864_000_000; // 10 days
6+
public static final String TOKEN_PREFIX = "Bearer ";
7+
public static final String HEADER_STRING = "Authorization";
8+
}

BankApplicationBackend/src/main/java/com/demo/bankapp/controller/UserController.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,6 @@ public Resource<User> createNewUser(@RequestBody CreateNewUserRequest request) {
6262
return assembler.toResource(user);
6363
}
6464

65-
@PostMapping("/login")
66-
public Resource<User> login(@RequestBody LoginRequest request) {
67-
68-
if (request == null) {
69-
throw new BadRequestException();
70-
}
71-
72-
if (request.getUsername() == null || request.getUsername().equals("") || request.getPassword() == null || request.getPassword().equals("")) {
73-
throw new BadRequestException("Invalid credentials.");
74-
}
75-
76-
User user = userService.login(request.getUsername(), request.getPassword());
77-
return assembler.toResource(user);
78-
}
79-
8065
private boolean isNumeric(String str) {
8166
return Pattern.matches("[0-9]+", str);
8267
}

BankApplicationBackend/src/main/java/com/demo/bankapp/service/abstractions/IUserService.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.util.List;
44

55
import com.demo.bankapp.model.User;
6-
import com.demo.bankapp.request.LoginRequest;
76

87
public interface IUserService {
98

@@ -15,6 +14,4 @@ public interface IUserService {
1514

1615
User createNewUser(User user);
1716

18-
User login(String username, String password);
19-
2017
}

BankApplicationBackend/src/main/java/com/demo/bankapp/service/concretions/UserService.java

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
package com.demo.bankapp.service.concretions;
22

3+
import static java.util.Collections.emptyList;
4+
35
import java.util.List;
46

57
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.security.core.userdetails.UserDetails;
9+
import org.springframework.security.core.userdetails.UserDetailsService;
10+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
611
import org.springframework.security.crypto.password.PasswordEncoder;
712
import org.springframework.stereotype.Service;
813

9-
import com.demo.bankapp.exception.BadCredentialsException;
1014
import com.demo.bankapp.exception.UserNotFoundException;
1115
import com.demo.bankapp.model.User;
1216
import com.demo.bankapp.repository.UserRepository;
1317
import com.demo.bankapp.service.abstractions.IUserService;
1418

1519
@Service
16-
public class UserService implements IUserService {
20+
public class UserService implements IUserService, UserDetailsService {
1721

1822
@Autowired
1923
private UserRepository repository;
@@ -32,19 +36,6 @@ public User createNewUser(User user) {
3236
return repository.save(user);
3337
}
3438

35-
@Override
36-
public User login(String username, String password) {
37-
38-
User user = findByUserName(username);
39-
String encodedPassword = passwordEncoder.encode(password);
40-
41-
if (!encodedPassword.equals(user.getPassword())) {
42-
throw new BadCredentialsException();
43-
}
44-
45-
return user;
46-
}
47-
4839
@Override
4940
public User findByUserName(String username) {
5041
User user = repository.findByUsername(username);
@@ -64,6 +55,17 @@ public User findByTcno(String tcno) {
6455
else
6556
return user;
6657
}
58+
59+
@Override
60+
public UserDetails loadUserByUsername(String username) {
61+
User user = repository.findByUsername(username);
62+
63+
if (user == null) {
64+
throw new UsernameNotFoundException(username);
65+
}
66+
67+
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), emptyList());
68+
}
6769

6870
// Avoid timing attacks?
6971
// private boolean isEqual(byte[] a, byte[] b) {

0 commit comments

Comments
 (0)