Skip to content

Commit eb8cd87

Browse files
committed
JWT Authentication
* Sample JWT Authentication Service is implemented * Code refactoring
1 parent 9945af5 commit eb8cd87

File tree

58 files changed

+1229
-222
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1229
-222
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>stateless-auth</artifactId>
7+
<groupId>com.fd</groupId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>authentication-commons-jwt</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-web</artifactId>
18+
</dependency>
19+
20+
<dependency>
21+
<groupId>org.springframework.boot</groupId>
22+
<artifactId>spring-boot-starter-security</artifactId>
23+
</dependency>
24+
25+
<dependency>
26+
<groupId>io.jsonwebtoken</groupId>
27+
<artifactId>jjwt</artifactId>
28+
</dependency>
29+
</dependencies>
30+
</project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.fd.tryout.security.jwt;
2+
3+
import lombok.Getter;
4+
import org.springframework.beans.factory.annotation.Value;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.context.annotation.PropertySource;
7+
8+
/**
9+
* @author fdanismaz
10+
* date: 10/20/18 3:52 PM
11+
*/
12+
@Getter
13+
@Configuration
14+
@PropertySource("jwt.properties")
15+
public class JwtAuthenticationConfig {
16+
17+
@Value("${com.fd.security.jwt.url:/login}")
18+
private String url;
19+
20+
@Value("${com.fd.security.jwt.header:Authorization}")
21+
private String header;
22+
23+
@Value("${com.fd.security.jwt.prefix:Bearer}")
24+
private String prefix;
25+
26+
@Value("${com.fd.security.jwt.expiration:#{24*60*60}}")
27+
private int expiration; // default 24 hours
28+
29+
@Value("${com.fd.security.jwt.secret}")
30+
private String secret;
31+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.fd.tryout.security.jwt;
2+
3+
import io.jsonwebtoken.Claims;
4+
import io.jsonwebtoken.Jwts;
5+
import lombok.extern.slf4j.Slf4j;
6+
import lombok.var;
7+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8+
import org.springframework.security.core.authority.SimpleGrantedAuthority;
9+
import org.springframework.security.core.context.SecurityContextHolder;
10+
import org.springframework.web.filter.OncePerRequestFilter;
11+
12+
import javax.servlet.FilterChain;
13+
import javax.servlet.ServletException;
14+
import javax.servlet.http.HttpServletRequest;
15+
import javax.servlet.http.HttpServletResponse;
16+
import java.io.IOException;
17+
import java.util.List;
18+
import java.util.stream.Collectors;
19+
20+
/**
21+
* @author fdanismaz
22+
* date: 10/20/18 4:00 PM
23+
*/
24+
@Slf4j
25+
public class JwtTokenAuthenticationFilter extends OncePerRequestFilter {
26+
27+
private JwtAuthenticationConfig config;
28+
29+
public JwtTokenAuthenticationFilter(JwtAuthenticationConfig config) {
30+
this.config = config;
31+
}
32+
33+
@Override
34+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
35+
String token = request.getHeader(config.getHeader());
36+
if (token != null && token.startsWith(config.getPrefix() + " ")) {
37+
token = token.replace(config.getPrefix() + " ", "");
38+
try {
39+
Claims claims = Jwts.parser().setSigningKey(config.getSecret().getBytes()).parseClaimsJws(token).getBody();
40+
String username = claims.getSubject();
41+
List<String> authorities = claims.get("authorities", List.class);
42+
if (username != null) {
43+
var grantedAuthorities = authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
44+
var auth = new UsernamePasswordAuthenticationToken(username, null, grantedAuthorities);
45+
SecurityContextHolder.getContext().setAuthentication(auth);
46+
}
47+
} catch (Exception e) {
48+
log.error(e.getMessage());
49+
SecurityContextHolder.clearContext();
50+
}
51+
}
52+
filterChain.doFilter(request, response);
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.fd.tryout.security.jwt;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import io.jsonwebtoken.Jwts;
5+
import io.jsonwebtoken.SignatureAlgorithm;
6+
import lombok.var;
7+
import org.springframework.security.authentication.AuthenticationManager;
8+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
9+
import org.springframework.security.core.Authentication;
10+
import org.springframework.security.core.AuthenticationException;
11+
import org.springframework.security.core.GrantedAuthority;
12+
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
13+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
14+
15+
import javax.servlet.FilterChain;
16+
import javax.servlet.http.HttpServletRequest;
17+
import javax.servlet.http.HttpServletResponse;
18+
import java.io.IOException;
19+
import java.time.Instant;
20+
import java.util.Collections;
21+
import java.util.Date;
22+
import java.util.List;
23+
import java.util.stream.Collectors;
24+
25+
/**
26+
* @author fdanismaz
27+
* date: 10/20/18 4:33 PM
28+
*/
29+
public class JwtUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
30+
31+
private final JwtAuthenticationConfig config;
32+
private final ObjectMapper mapper;
33+
34+
public JwtUsernamePasswordAuthenticationFilter(JwtAuthenticationConfig config,
35+
AuthenticationManager authenticationManager) {
36+
super(new AntPathRequestMatcher(config.getUrl(), "POST"));
37+
this.setAuthenticationManager(authenticationManager);
38+
this.config = config;
39+
this.mapper = new ObjectMapper();
40+
}
41+
42+
@Override
43+
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
44+
throws AuthenticationException, IOException {
45+
46+
User user = this.mapper.readValue(request.getInputStream(), User.class);
47+
var authenticationToken =
48+
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), Collections.emptyList());
49+
return this.getAuthenticationManager().authenticate(authenticationToken);
50+
}
51+
52+
@Override
53+
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
54+
FilterChain chain, Authentication auth) {
55+
Instant now = Instant.now();
56+
List<String> authorities = auth.getAuthorities().stream().map(GrantedAuthority::getAuthority)
57+
.collect(Collectors.toList());
58+
String token = Jwts.builder()
59+
.setSubject(auth.getName())
60+
.claim("authorities", authorities)
61+
.setIssuedAt(Date.from(now))
62+
.setExpiration(Date.from(now.plusSeconds(config.getExpiration())))
63+
.signWith(SignatureAlgorithm.HS256, config.getSecret().getBytes())
64+
.compact();
65+
response.addHeader(config.getHeader(), config.getPrefix() + " " + token);
66+
}
67+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.fd.tryout.security.jwt;
2+
3+
import lombok.Data;
4+
5+
/**
6+
* @author fdanismaz
7+
* date: 10/21/18 9:56 AM
8+
*/
9+
@Data
10+
public class User {
11+
private String username;
12+
private String password;
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
com.fd.security.jwt.url= /login
2+
com.fd.security.jwt.header= Authorization
3+
com.fd.security.jwt.prefix= Bearer
4+
com.fd.security.jwt.expiration= #{24*60*60}
5+
com.fd.security.jwt.secret= 123

stateless-auth/stateless-auth-dto/pom.xml renamed to authentication/authentication-commons/pom.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,19 @@
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111

12-
<artifactId>stateless-auth-dto</artifactId>
12+
<artifactId>authentication-commons</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-security</artifactId>
18+
</dependency>
19+
20+
<dependency>
21+
<groupId>com.fd</groupId>
22+
<artifactId>authentication-db</artifactId>
23+
</dependency>
24+
</dependencies>
1325

1426

1527
</project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.fd.tryout.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
import java.time.LocalDate;
9+
10+
/**
11+
* @author fdanismaz
12+
* date: 10/7/18 12:42 PM
13+
*/
14+
@Data
15+
@Builder
16+
@NoArgsConstructor
17+
@AllArgsConstructor
18+
public class Customer {
19+
20+
private String id;
21+
private String name;
22+
private String company;
23+
private LocalDate birthdate;
24+
}

stateless-auth/spring-session-auth/src/main/java/com/fd/tryout/security/springsession/security/DbAuthenticationProvider.java renamed to authentication/authentication-commons/src/main/java/com/fd/tryout/security/DbAuthenticationProvider.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package com.fd.tryout.security.springsession.security;
1+
package com.fd.tryout.security;
22

3-
import com.fd.tryout.security.springsession.entity.UserEntity;
4-
import com.fd.tryout.security.springsession.repository.user.UserRepository;
5-
import com.fd.tryout.security.springsession.repository.user.UserSpecifications;
3+
import com.fd.tryout.security.entity.UserEntity;
4+
import com.fd.tryout.security.repository.user.UserRepository;
5+
import com.fd.tryout.security.repository.user.UserSpecifications;
66
import lombok.extern.slf4j.Slf4j;
77
import org.springframework.security.authentication.AuthenticationProvider;
88
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>stateless-auth</artifactId>
7+
<groupId>com.fd</groupId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>authentication-db</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-data-jpa</artifactId>
18+
</dependency>
19+
20+
<dependency>
21+
<groupId>org.hibernate</groupId>
22+
<artifactId>hibernate-c3p0</artifactId>
23+
</dependency>
24+
25+
<dependency>
26+
<groupId>javax.xml.bind</groupId>
27+
<artifactId>jaxb-api</artifactId>
28+
<version>${jaxb.version}</version>
29+
</dependency>
30+
</dependencies>
31+
32+
<build>
33+
<plugins>
34+
<!-- Hibernate Type Safe metamodel -->
35+
<plugin>
36+
<groupId>org.bsc.maven</groupId>
37+
<artifactId>maven-processor-plugin</artifactId>
38+
<version>${maven.plugin.processor.version}</version>
39+
<executions>
40+
<execution>
41+
<id>process</id>
42+
<goals>
43+
<goal>process</goal>
44+
</goals>
45+
<phase>generate-sources</phase>
46+
<configuration>
47+
<processors>
48+
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
49+
</processors>
50+
<outputDirectory>target/generated-sources/annotations</outputDirectory>
51+
</configuration>
52+
</execution>
53+
</executions>
54+
<dependencies>
55+
<dependency>
56+
<groupId>org.hibernate</groupId>
57+
<artifactId>hibernate-jpamodelgen</artifactId>
58+
<version>${hibernate.jpamodelgen-version}</version>
59+
</dependency>
60+
</dependencies>
61+
</plugin>
62+
</plugins>
63+
</build>
64+
65+
</project>

0 commit comments

Comments
 (0)