Skip to content

Commit

Permalink
1. eureka server 8070 -> 8761.
Browse files Browse the repository at this point in the history
2. gateway oauth2login + oauth2ResourceServer + MapReactiveUserDetailService implemented.

from spring 3.2.x, need to implement MapReactiveUserDetailService by my own. ref: spring-projects/spring-boot#37504 (comment)
  • Loading branch information
plum7ree committed Jul 8, 2024
1 parent 7909a5d commit a97dd31
Show file tree
Hide file tree
Showing 15 changed files with 209 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ eureka:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: "http://localhost:8070/eureka/"
defaultZone: "http://localhost:8761/eureka/"
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ eureka:
fetchRegistry: true
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8070/eureka/
defaultZone: http://localhost:8761/eureka/


---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ retry-config:
# fetchRegistry: true
# registerWithEureka: true
# serviceUrl:
# defaultZone: http://localhost:8070/eureka/
# defaultZone: http://localhost:8761/eureka/

topic-names:
payment-request-topic-name: payment-request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ retry-config:
# fetchRegistry: true
# registerWithEureka: true
# serviceUrl:
# defaultZone: http://localhost:8070/eureka/
# defaultZone: http://localhost:8761/eureka/

topic-names:
payment-request-topic-name: payment-request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ eureka:
fetchRegistry: true
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8070/eureka/
defaultZone: http://localhost:8761/eureka/

19 changes: 18 additions & 1 deletion backend/java/backend/gateway/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,29 @@
<artifactId>spring-boot-starter-security</artifactId>
</dependency>


<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency> <!-- solve mac DNS error -->
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>

<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.32.1</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId>
<version>1.29.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
package com.example.gateway.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

@Configuration
@EnableWebFluxSecurity
@Slf4j
public class SecurityConfig {

@Bean
Expand All @@ -38,18 +49,22 @@ public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
).permitAll()
.anyExchange().authenticated())
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults())
.oauth2Login(Customizer.withDefaults());
// .formLogin(formLogin -> formLogin
// .loginPage("/login")
// .usernameParameter("email")
// .passwordParameter("password")
// .failureUrl("/login?error")
// .successHandler(new RedirectServerAuthenticationSuccessHandler("/home"))
// )
.oauth2Login(Customizer.withDefaults())
.oauth2ResourceServer(oAuth2ResourceServerSpec -> oAuth2ResourceServerSpec
.jwt(jwtSpec -> jwtSpec.jwtAuthenticationConverter(grantedAuthoritiesExtractor())));


return http.build();
}

// from spring 3.2.2, need to implement MapReactiveUserDetailsService by my own.
// https://github.com/spring-projects/spring-boot/issues/38713#issuecomment-1852289101
// https://github.com/spring-projects/spring-boot/issues/39096
@Bean
MapReactiveUserDetailsService userDetailsService() {
UserDetails userDetails = User.withUsername("admin").password("admin").roles("ADMIN").build();
return new MapReactiveUserDetailsService(List.of(userDetails));
}

@Bean
CorsConfigurationSource corsConfigurationSource() {
Expand All @@ -64,5 +79,42 @@ CorsConfigurationSource corsConfigurationSource() {
return source;
}

private Converter<Jwt, Mono<AbstractAuthenticationToken>> grantedAuthoritiesExtractor() {
JwtAuthenticationConverter jwtAuthenticationConverter =
new JwtAuthenticationConverter();
return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
}


// @Bean
// public GrantedAuthoritiesMapper userAuthoritiesMapper() {
// return (authorities) -> {
// Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
//
// authorities.forEach(authority -> {
// if (OidcUserAuthority.class.isInstance(authority)) {
// OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
//
// OidcIdToken idToken = oidcUserAuthority.getIdToken();
// OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
// log.info("idToken: {}", idToken);
// log.info("userInfo: {}", userInfo);
// // Map the claims found in idToken and/or userInfo
// // to one or more GrantedAuthority's and add it to mappedAuthorities
//
// } else if (OAuth2UserAuthority.class.isInstance(authority)) {
// OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority) authority;
//
// Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
//
// // Map the attributes found in userAttributes
// // to one or more GrantedAuthority's and add it to mappedAuthorities
//
// }
// });
//
// return mappedAuthorities;
// };
// }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//package com.example.gateway.controller;
//
//import com.example.gateway.dto.AuthResponse;
//import com.google.api.client.auth.oauth2.TokenRequest;
//import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
//import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
//import com.google.api.client.http.javanet.NetHttpTransport;
//import com.google.api.client.json.jackson.JacksonFactory;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.PostMapping;
//import org.springframework.web.bind.annotation.RequestBody;
//import org.springframework.web.bind.annotation.RestController;
//
//import java.util.Collections;
//
//@RestController
//@Slf4j
//public class AuthController {
// @Value("${spring.security.oauth2.client.registration.google.client-id}")
// private String clientId;
//
// @PostMapping("/api/auth/google")
// public ResponseEntity<?> authenticateGoogle(@RequestBody TokenRequest tokenRequest) {
// try {
// log.info("authenticate Google tokenRequest: {}", tokenRequest);
// GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new JacksonFactory())
// .setAudience(Collections.singletonList(clientId))
// .build();
//
// GoogleIdToken idToken = verifier.verify(tokenRequest.toString());
// if (idToken != null) {
// GoogleIdToken.Payload payload = idToken.getPayload();
//
// String userId = payload.getSubject();
// String email = payload.getEmail();
// boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
// String name = (String) payload.get("name");
// String pictureUrl = (String) payload.get("picture");
//
// // 여기서 사용자 정보를 데이터베이스에 저장하거나 업데이트할 수 있습니다.
// // 그리고 자체 JWT 토큰을 생성하여 반환할 수 있습니다.
// return ResponseEntity.ok(new AuthResponse(userId, email, name));
// } else {
// return ResponseEntity.badRequest().body("Invalid ID token.");
// }
// } catch (Exception e) {
// return ResponseEntity.badRequest().body("Token verification failed: " + e.getMessage());
// }
// }
//
//
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.gateway.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;

@Builder
@AllArgsConstructor
public class AuthResponse {
private String userId;
private String email;
private String name;

// constructor, getters and setters
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//package com.example.gateway.service;
//
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
//import org.springframework.stereotype.Service;
//
//@Slf4j
//@Service
//@RequiredArgsConstructor
//public class CustomOAuthUserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
// private final SocialMemberRepository socialMemberRepository;
//
// @Override
// public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
// OAuth2UserService delegate = new DefaultOAuth2UserService();
// OAuth2User oAuth2User = delegate.loadUser(userRequest);
// log.info("oauth2user = {}",oAuth2User);
// String email = oAuth2User.getAttribute("email");
// String nickname = UUID.randomUUID().toString().substring(0,15);
// String password = "default";
//// Role role = Role.ROLE_USER;
//
//
// Optional<SocialMember> socialMember = socialMemberRepository.findByEmail(email);
//
// List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//
// if(socialMember.isEmpty()){
// SocialMember savedSocialMember = SocialMember.createSocialMember(email, nickname);
// SaveMemberResponseDto savedResponse = socialMemberRepository.save(savedSocialMember);
// authorities.add(new SimpleGrantedAuthority("ROLE_FIRST_JOIN"));
// User savedUser = new User (String.valueOf(savedResponse.getId()),password,authorities);
// return new CustomUserDetails(String.valueOf(savedResponse.getId()),authorities,savedUser,oAuth2User.getAttributes());
// }
// else{
// authorities.add(new SimpleGrantedAuthority("ROLE_EXIST_USER"));
// User savedUser = new User (String.valueOf(socialMember.get().getUserId()),password,authorities);
// return new CustomUserDetails(savedUser.getUsername(),authorities,savedUser,oAuth2User.getAttributes());
// }
// }
//
//}
12 changes: 10 additions & 2 deletions backend/java/backend/gateway/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,16 @@ spring:
oauth2:
client:
registration:
github.client-id: ${GITHUB_CLIENT_ID}
github.client-secret: ${GITHUB_CLIENT_SECRET}
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope:
- email
- profile
resourceserver:
jwt:
jwk-set-uri: "https://www.googleapis.com/oauth2/v3/cert"
issuer-uri: "https://accounts.google.com"

# kubernetes:
# discovery:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ eureka:
fetchRegistry: true
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8070/eureka/
defaultZone: http://localhost:8761/eureka/


#broker:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ eureka:
fetchRegistry: true
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8070/eureka/
defaultZone: http://localhost:8761/eureka/


Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ eureka:
fetchRegistry: true
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8070/eureka/
defaultZone: http://localhost:8761/eureka/

Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ eureka:
fetchRegistry: true
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8070/eureka/
defaultZone: http://localhost:8761/eureka/

#logging:
# level:
Expand Down

0 comments on commit a97dd31

Please sign in to comment.