Skip to content

Commit 1ecae51

Browse files
committed
feat(jpa-userdetails): change in-memory user details to jpa based user details"
- Implements UserDetails to AuthenticatedUser class - Extend UserDetailService to JpaUserDetailsService - Load Username from User entity (mapped to unique email)
1 parent 94850cc commit 1ecae51

File tree

5 files changed

+99
-12
lines changed

5 files changed

+99
-12
lines changed

app.http

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
@base_url = http://localhost:8089
22
@api = {{base_url}}/api/v1
3-
@username = admin
3+
@username = alice.johnson@example.com
44
@passowrd = password
5-
@token = eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhcHBzIiwic3ViIjoiYWRtaW4iLCJleHAiOjE3NDkyNjkwNjUsInVzZXJfaWQiOiIxIiwiaWF0IjoxNzQ5MjY5MDQ1LCJzY29wZSI6IiJ9.H_p96Hy7zH_bQ8K10vlZd6apQWEuIkgzIBXks5JYX5-B9pn8zPEzBpXSadpnzFl-8g7zfd_a9PEtjncLSV5opAX_QhHUXOiR18WeX8qxGFoXA5qpX5IuzL8dNvSIvhcQfaiqMwiFz7_4F2QGFGHZyPGJd_gZ0SUg_YA91dth0PkOobbH05gSknLEM9lGMqhiqCcFGsgVckiW8GdCbkGxqfgc6qixbpuaoRo92mm0h8Xajz3Q1wEXhsTgXkA_2Y4ejuhd-uFBaO4-mLccE9pnLPZ7OfmcP0tsHTX8A_8g9LC4G78HomaPCdphMIpG9oE70ZnOkCe2T6wOke8pY-udJg
5+
@token = eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhcHBzIiwic3ViIjoiYm9iLnNtaXRoQGV4YW1wbGUuY29tIiwiZXhwIjoxNzQ5MzY2MjU0LCJ1c2VyX2lkIjoyLCJpYXQiOjE3NDkzNjYyMzQsInNjb3BlIjoiIn0.FBStVWnq6h45QVXN7oJA6wxLRDW0OoRCWkxUBstP4PfzKJ81UVJzFt8s5N5dEu1dKc5vd66lOIvDw9d6QfGs2DMNf3LYH53X9r1zhNi0fIsShYSWnrCNahYi7zaRmaGys4cUMBehNj4VQGF-fbxW3UdCgbGxsDlPvJviz76Nfo7TyVZlV9ccVJd1mKJHm0E06H_FK8qab_Rq40jLMMt8B5OM3qdNLN_j6fGds-xXclIsT_W-EaNecfhCcDJ_lkqxsJ-sEIrtpiEp4MD1SqMzbXsyoXKKu6gHzwEeGpI6_giQrdCLf2wFEKBhzPeH-9hKGj8afjw8UWTVXXE4zV8HnA
66
@refresh = eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhcHBzIiwic3ViIjoiYW5kcmlhd2FuIiwiZXhwIjoxNzQ5MjY1MTgyLCJpYXQiOjE3NDkyNjUwNjIsInNjb3BlIjoiIn0.SVX9hYqVBs4b-7yPUZkBOXSRyGN7n7AW2A5XsMdJws40UBJvpBzztl2ir7L7C8A1FvjOQ59Mz5rAGgXH9xytPwXhRF8KHIXZF_aUO--cYhbjleFPjA1J_Y0QtI5ncEoLz6wMHDuz04_xjvbHaejSVo1dgbcZsq3iYc3UrL_Rgz-CQiwARk8CsOeevAGukxz_px-IMYPA2BIypWHcdbsqkgzcjTMAY0xBjGTEND97p1omvPPIDkT-pln8k3zyUEjY9qeEUT1AJwDB_HgoXePTSeW08oVZvrcWeOSdiEP3q9iuIVo93LjVOApcHJyGWzjEqYe_h1mrm2ciQ541BbzsTQ
77
GET {{api}}/users
88
Accept: application/json
99
Authorization: Bearer {{token}}
1010

11+
###
12+
GET {{api}}/me
13+
Accept: application/json
14+
Authorization: Bearer {{token}}
15+
1116
###
1217

1318
POST {{api}}/auth/login

src/main/java/com/andriawan/andresource/config/Security.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.andriawan.andresource.config;
22

3+
import com.andriawan.andresource.service.JpaUserDetailsService;
34
import com.nimbusds.jose.jwk.JWK;
45
import com.nimbusds.jose.jwk.JWKSet;
56
import com.nimbusds.jose.jwk.RSAKey;
@@ -17,15 +18,12 @@
1718
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
1819
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
1920
import org.springframework.security.config.http.SessionCreationPolicy;
20-
import org.springframework.security.core.userdetails.User;
21-
import org.springframework.security.core.userdetails.UserDetails;
2221
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
2322
import org.springframework.security.crypto.password.PasswordEncoder;
2423
import org.springframework.security.oauth2.jwt.JwtDecoder;
2524
import org.springframework.security.oauth2.jwt.JwtEncoder;
2625
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
2726
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
28-
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
2927
import org.springframework.security.web.SecurityFilterChain;
3028

3129
@Configuration
@@ -50,12 +48,7 @@ public class Security {
5048

5149
@Autowired private CustomAuthenticationEntryPoint entryPoint;
5250

53-
@Bean
54-
public InMemoryUserDetailsManager sampleUser() {
55-
UserDetails user =
56-
User.withUsername(sampeUsername).password("{noop}".concat(samplePassword)).build();
57-
return new InMemoryUserDetailsManager(user);
58-
}
51+
@Autowired private JpaUserDetailsService jpaUserDetailsService;
5952

6053
@Bean
6154
@Order(1)
@@ -64,6 +57,7 @@ public SecurityFilterChain loginFilterChain(HttpSecurity http) throws Exception
6457
.securityMatcher(loginRoute)
6558
.csrf(crsf -> crsf.disable())
6659
.exceptionHandling(exception -> exception.authenticationEntryPoint(entryPoint))
60+
.userDetailsService(jpaUserDetailsService)
6761
.sessionManagement(
6862
session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
6963
.build();
@@ -76,6 +70,7 @@ public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
7670
request ->
7771
request.requestMatchers(publicRoute).permitAll().anyRequest().authenticated())
7872
.csrf(crsf -> crsf.disable())
73+
.userDetailsService(jpaUserDetailsService)
7974
.oauth2ResourceServer(
8075
oauth2 -> oauth2.jwt(Customizer.withDefaults()).authenticationEntryPoint(entryPoint))
8176
.sessionManagement(
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.andriawan.andresource.entity;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
6+
import org.springframework.security.core.GrantedAuthority;
7+
import org.springframework.security.core.userdetails.UserDetails;
8+
9+
public class AuthenticatedUser implements UserDetails {
10+
11+
private User user;
12+
13+
public AuthenticatedUser(User user) {
14+
this.user = user;
15+
}
16+
17+
@Override
18+
public Collection<? extends GrantedAuthority> getAuthorities() {
19+
final ArrayList<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
20+
return roles;
21+
}
22+
23+
@Override
24+
public String getPassword() {
25+
return user.getPassword();
26+
}
27+
28+
@Override
29+
public String getUsername() {
30+
return user.getEmail();
31+
}
32+
33+
public User getUser() {
34+
return user;
35+
}
36+
37+
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package com.andriawan.andresource.repository;
22

33
import com.andriawan.andresource.entity.User;
4+
5+
import java.util.Optional;
6+
47
import org.springframework.data.jpa.repository.JpaRepository;
58

6-
public interface UserRepository extends JpaRepository<User, Long> {}
9+
public interface UserRepository extends JpaRepository<User, Long> {
10+
Optional<User> findByEmail(String email);
11+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.andriawan.andresource.service;
2+
3+
import java.io.UnsupportedEncodingException;
4+
import java.net.URLDecoder;
5+
import java.nio.charset.StandardCharsets;
6+
import java.util.Optional;
7+
8+
import org.springframework.security.core.userdetails.UserDetails;
9+
import org.springframework.security.core.userdetails.UserDetailsService;
10+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
11+
import org.springframework.stereotype.Service;
12+
13+
import com.andriawan.andresource.entity.AuthenticatedUser;
14+
import com.andriawan.andresource.entity.User;
15+
import com.andriawan.andresource.repository.UserRepository;
16+
17+
@Service
18+
public class JpaUserDetailsService implements UserDetailsService {
19+
20+
private final UserRepository userRepository;
21+
22+
private AuthenticatedUser authenticatedUser;
23+
24+
public JpaUserDetailsService(UserRepository userRepository) {
25+
this.userRepository = userRepository;
26+
}
27+
28+
public AuthenticatedUser getAuthenticatedUser() {
29+
return authenticatedUser;
30+
}
31+
32+
@Override
33+
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
34+
try {
35+
String filteredUsername = URLDecoder.decode(username, StandardCharsets.UTF_8.name());
36+
Optional<User> user = userRepository.findByEmail(filteredUsername);
37+
authenticatedUser = user.map(AuthenticatedUser::new)
38+
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
39+
return authenticatedUser;
40+
} catch (UnsupportedEncodingException e) {
41+
return null;
42+
}
43+
}
44+
45+
}

0 commit comments

Comments
 (0)