Skip to content

Commit 2f951f1

Browse files
committed
Update app api
1 parent 15ed18e commit 2f951f1

File tree

14 files changed

+717
-29
lines changed

14 files changed

+717
-29
lines changed

backend/webandtech/pom.xml

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,22 @@
33
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
6-
7-
<groupId>webapp8</groupId>
8-
<artifactId>webandtech</artifactId>
9-
<version>0.0.1-SNAPSHOT</version>
10-
<name>webandtech</name>
11-
12-
<parent>
6+
<parent>
137
<groupId>org.springframework.boot</groupId>
148
<artifactId>spring-boot-starter-parent</artifactId>
159
<version>2.6.3</version>
1610
</parent>
11+
<groupId>webapp8</groupId>
12+
<artifactId>webandtech</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<name>webandtech</name>
1715

1816
<properties>
1917
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2018
<java.version>17</java.version>
2119
</properties>
2220

2321
<dependencies>
24-
<dependency>
25-
<groupId>junit</groupId>
26-
<artifactId>junit</artifactId>
27-
<scope>test</scope>
28-
</dependency>
2922
<dependency>
3023
<groupId>org.springframework.boot</groupId>
3124
<artifactId>spring-boot-starter-thymeleaf</artifactId>
@@ -113,5 +106,39 @@
113106
<artifactId>openpdf</artifactId>
114107
<version>1.3.8</version>
115108
</dependency>
109+
110+
111+
112+
<dependency>
113+
<groupId>org.springdoc</groupId>
114+
<artifactId>springdoc-openapi-ui</artifactId>
115+
<version>1.6.6</version>
116+
</dependency>
117+
<dependency>
118+
<groupId>io.jsonwebtoken</groupId>
119+
<artifactId>jjwt</artifactId>
120+
<version>0.7.0</version>
121+
</dependency>
116122
</dependencies>
123+
124+
<build>
125+
<plugins>
126+
127+
<plugin>
128+
<groupId>org.springframework.boot</groupId>
129+
<artifactId>spring-boot-maven-plugin</artifactId>
130+
</plugin>
131+
132+
133+
<plugin>
134+
<groupId>org.apache.maven.plugins</groupId>
135+
<artifactId>maven-surefire-plugin</artifactId>
136+
<configuration>
137+
<testFailureIgnore>true</testFailureIgnore>
138+
</configuration>
139+
</plugin>
140+
141+
</plugins>
142+
</build>
143+
117144
</project>
Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,42 @@
11
package webapp8.webandtech.controller.api.auth;
22

3+
import javax.servlet.http.HttpServletRequest;
4+
import javax.servlet.http.HttpServletResponse;
5+
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.CookieValue;
9+
import org.springframework.web.bind.annotation.PostMapping;
10+
import org.springframework.web.bind.annotation.RequestBody;
11+
import org.springframework.web.bind.annotation.RequestMapping;
12+
import org.springframework.web.bind.annotation.RestController;
13+
14+
import webapp8.webandtech.security.jwt.AuthResponse;
15+
import webapp8.webandtech.security.jwt.LoginRequest;
16+
import webapp8.webandtech.security.jwt.UserLoginService;
17+
import webapp8.webandtech.security.jwt.AuthResponse.Status;
18+
19+
@RestController
20+
@RequestMapping("/api/auth")
321
public class LoginApiController {
22+
@Autowired
23+
private UserLoginService userService;
24+
@PostMapping("/login")
425

5-
}
26+
public ResponseEntity<AuthResponse> login(
27+
@CookieValue(name = "accessToken", required = false) String accessToken,
28+
@CookieValue(name = "refreshToken", required = false) String refreshToken,
29+
@RequestBody LoginRequest loginRequest) {
30+
return userService.login(loginRequest, accessToken, refreshToken);
31+
}
32+
33+
@PostMapping("/refresh")
34+
public ResponseEntity<AuthResponse> refreshToken(
35+
@CookieValue(name = "refreshToken", required = false) String refreshToken) {
36+
return userService.refresh(refreshToken);
37+
}
38+
@PostMapping("/logout")
39+
public ResponseEntity<AuthResponse> logOut(HttpServletRequest request, HttpServletResponse response) {
40+
return ResponseEntity.ok(new AuthResponse(Status.SUCCESS, userService.logout(request, response)));
41+
}
42+
}

backend/webandtech/src/main/java/webapp8/webandtech/security/SecurityConfiguration.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,21 @@ protected void configure(HttpSecurity http) throws Exception {
5757
http.authorizeRequests().antMatchers("/forgotPassword").permitAll();
5858
http.authorizeRequests().antMatchers("/getMoreProductsPage").permitAll();
5959
http.authorizeRequests().antMatchers("/moreProducts").permitAll();
60+
http.authorizeRequests().antMatchers("/api/**").permitAll();
6061
http.authorizeRequests().antMatchers("/error").permitAll();
6162
http.authorizeRequests().antMatchers("httpss://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.4.0/sockjs.js").permitAll();
63+
http.authorizeRequests().antMatchers("/swagger-ui.html").permitAll();
64+
http.authorizeRequests().antMatchers("/v3/**").permitAll();
65+
http.authorizeRequests().antMatchers("/swagger-ui/**").permitAll();
66+
http.csrf().ignoringAntMatchers("/swagger-ui/**");
67+
http.csrf().ignoringAntMatchers("/v3/**");
6268
http.authorizeRequests().antMatchers("/carShop").permitAll();
6369
http.authorizeRequests().antMatchers("/checkout/**").hasAnyRole("USER");
6470
http.authorizeRequests().antMatchers("/users/**").hasAnyRole("USER");
6571
http.authorizeRequests().antMatchers("/admin/**").hasAnyRole("ADMIN");
6672

6773

68-
http.authorizeRequests().anyRequest().authenticated();
74+
http.authorizeRequests().anyRequest().authenticated();
6975

7076
http.formLogin().loginPage("/login");
7177
http.formLogin().usernameParameter("username");
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package webapp8.webandtech.security.jwt;
2+
3+
public class AuthResponse {
4+
5+
private Status status;
6+
private String message;
7+
private String error;
8+
9+
public enum Status {
10+
SUCCESS, FAILURE
11+
}
12+
13+
public AuthResponse() {
14+
}
15+
16+
public AuthResponse(Status status, String message) {
17+
this.status = status;
18+
this.message = message;
19+
}
20+
21+
public AuthResponse(Status status, String message, String error) {
22+
this.status = status;
23+
this.message = message;
24+
this.error = error;
25+
}
26+
27+
public Status getStatus() {
28+
return status;
29+
}
30+
31+
public void setStatus(Status status) {
32+
this.status = status;
33+
}
34+
35+
public String getMessage() {
36+
return message;
37+
}
38+
39+
public void setMessage(String message) {
40+
this.message = message;
41+
}
42+
43+
public String getError() {
44+
return error;
45+
}
46+
47+
public void setError(String error) {
48+
this.error = error;
49+
}
50+
51+
@Override
52+
public String toString() {
53+
return "LoginResponse [status=" + status + ", message=" + message + ", error=" + error + "]";
54+
}
55+
56+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package webapp8.webandtech.security.jwt;
2+
3+
import org.springframework.http.HttpCookie;
4+
import org.springframework.http.ResponseCookie;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
public class JwtCookieManager {
9+
10+
public static final String ACCESS_TOKEN_COOKIE_NAME = "AuthToken";
11+
public static final String REFRESH_TOKEN_COOKIE_NAME = "RefreshToken";
12+
13+
public HttpCookie createAccessTokenCookie(String token, Long duration) {
14+
String encryptedToken = SecurityCipher.encrypt(token);
15+
return ResponseCookie.from(ACCESS_TOKEN_COOKIE_NAME, encryptedToken).maxAge(-1).httpOnly(true).path("/").build();
16+
}
17+
18+
public HttpCookie createRefreshTokenCookie(String token, Long duration) {
19+
String encryptedToken = SecurityCipher.encrypt(token);
20+
return ResponseCookie.from(REFRESH_TOKEN_COOKIE_NAME, encryptedToken).maxAge(-1).httpOnly(true).path("/").build();
21+
}
22+
23+
public HttpCookie deleteAccessTokenCookie() {
24+
return ResponseCookie.from(ACCESS_TOKEN_COOKIE_NAME, "").maxAge(0).httpOnly(true).path("/").build();
25+
}
26+
27+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package webapp8.webandtech.security.jwt;
2+
3+
import java.io.IOException;
4+
5+
import javax.servlet.FilterChain;
6+
import javax.servlet.ServletException;
7+
import javax.servlet.http.Cookie;
8+
import javax.servlet.http.HttpServletRequest;
9+
import javax.servlet.http.HttpServletResponse;
10+
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
import org.springframework.beans.factory.annotation.Autowired;
14+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
15+
import org.springframework.security.core.context.SecurityContextHolder;
16+
import org.springframework.security.core.userdetails.UserDetails;
17+
import org.springframework.security.core.userdetails.UserDetailsService;
18+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
19+
import org.springframework.stereotype.Component;
20+
import org.springframework.util.StringUtils;
21+
import org.springframework.web.filter.OncePerRequestFilter;
22+
23+
@Component
24+
public class JwtRequestFilter extends OncePerRequestFilter {
25+
26+
private static final Logger LOG = LoggerFactory.getLogger(JwtRequestFilter.class);
27+
28+
@Autowired
29+
private UserDetailsService userDetailsService;
30+
31+
@Autowired
32+
private JwtTokenProvider jwtTokenProvider;
33+
34+
@Override
35+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
36+
FilterChain filterChain) throws ServletException, IOException {
37+
38+
try {
39+
String token = getJwtToken(request, true);
40+
41+
if (StringUtils.hasText(token) && jwtTokenProvider.validateToken(token)) {
42+
43+
String username = jwtTokenProvider.getUsername(token);
44+
45+
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
46+
47+
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
48+
userDetails, null, userDetails.getAuthorities());
49+
50+
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
51+
52+
SecurityContextHolder.getContext().setAuthentication(authentication);
53+
}
54+
} catch (Exception ex) {
55+
LOG.error("Exception processing JWT Token",ex);
56+
}
57+
58+
filterChain.doFilter(request, response);
59+
}
60+
61+
private String getJwtToken(HttpServletRequest request, boolean fromCookie) {
62+
63+
if (fromCookie) {
64+
return getJwtFromCookie(request);
65+
} else {
66+
return getJwtFromRequest(request);
67+
}
68+
}
69+
70+
private String getJwtFromRequest(HttpServletRequest request) {
71+
72+
String bearerToken = request.getHeader("Authorization");
73+
74+
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
75+
76+
String accessToken = bearerToken.substring(7);
77+
if (accessToken == null) {
78+
return null;
79+
}
80+
81+
return SecurityCipher.decrypt(accessToken);
82+
}
83+
return null;
84+
}
85+
86+
private String getJwtFromCookie(HttpServletRequest request) {
87+
88+
Cookie[] cookies = request.getCookies();
89+
90+
if (cookies == null) {
91+
return "";
92+
}
93+
94+
for (Cookie cookie : cookies) {
95+
if (JwtCookieManager.ACCESS_TOKEN_COOKIE_NAME.equals(cookie.getName())) {
96+
String accessToken = cookie.getValue();
97+
if (accessToken == null) {
98+
return null;
99+
}
100+
101+
return SecurityCipher.decrypt(accessToken);
102+
}
103+
}
104+
return null;
105+
}
106+
}

0 commit comments

Comments
 (0)