묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
소셜 로그인 설계
안녕하세요 강사님 혹시 oauth2 를 이용한 로그인을 한 다음에 사용자 프로필을 받는 것이 서비스 플로우인데 이럴경우 웹이 아닌 앱을 사용할경우 (로직은 다른 거 알고 있습니다.) (PCKE 방식 사용 예정입니다.)oauth2 를 해서 사용자 db에 저장이 되고 이렇게 처음에 저장이 되고 그 다음에 프로필을 받으면 저 값이 수정이 되게 만들어 주는 게 맞을지 질문드립니다. 사용자엔티티에 Provider 나 socialId 로 값을 받습니다. (구글과 애플을 사용할 예정입니다.) @Entity @Table(name = "users") @Getter @NoArgsConstructor @Setter public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id") private Long id; @Column(name = "name", nullable = false) private String name; @Enumerated(EnumType.STRING) @Column(name = "SEX", nullable = false) private Sex sex; @Column(name = "age", nullable = false) private Integer age; @Column(name = "nationality", nullable = false) private String nationality; @Column(name = "introduction", length = 40, nullable = false) private String introduction; @Column(name = "visit_purpose", length = 40, nullable = false) private String visitPurpose; @Column(name = "languages", nullable = false) private String languages; @Column(name = "hobby", nullable = false) private String hobby; @Column(name = "created_at", nullable = false) private Instant createdAt; @Column(name = "updated_at", nullable = false) private Instant updatedAt; @Column(name = "Provider", nullable = false) private String provider; @Column(name = "social_id", nullable = false) private String socialId; @Column(name = "email", nullable = false) private String email; @Builder public User(String name, Sex sex, Integer age, String nationality, String introduction, String visitPurpose, String languages, String hobby, String provider, String socialId, String email) { this.name = name; this.sex = sex; this.age = age; this.nationality = nationality; this.introduction = introduction; this.visitPurpose = visitPurpose; this.languages = languages; this.hobby = hobby; this.provider = provider; this.socialId = socialId; this.email = email; this.createdAt = Instant.now(); this.updatedAt = Instant.now(); } public void updateProfile(UserUpdateDTO dto) { if (dto.getName() != null && !dto.getName().trim().isEmpty()) { this.name = dto.getName().trim(); } if (dto.getSex() != null) { this.sex = dto.getSex(); } if (dto.getAge() != null) { this.age = dto.getAge(); } if (dto.getNationality() != null && !dto.getNationality().trim().isEmpty()) { this.nationality = dto.getNationality().trim(); } if (dto.getIntroduction() != null && !dto.getIntroduction().trim().isEmpty()) { this.introduction = dto.getIntroduction().trim(); } if (dto.getVisitPurpose() != null && !dto.getVisitPurpose().trim().isEmpty()) { this.visitPurpose = dto.getVisitPurpose().trim(); } if (dto.getLanguages() != null && !dto.getLanguages().trim().isEmpty()) { this.languages = dto.getLanguages().trim(); } if (dto.getHobby() != null && !dto.getHobby().trim().isEmpty()) { this.hobby = dto.getHobby().trim(); } this.updatedAt = Instant.now(); // 수정 시각 갱신 } }
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
카카오 인가코드 요청
카카오 인가 코드 요청 url이 변경 된 것 같습니다!
-
해결됨카카오,구글 SNS 로그인(springboot3, vue3)
구글 로그인 프론트 화면
안녕하세요 구글 로그인 구현 중 질문있어서 질문드립니다! googleUrl, googleClientId, googleRedirectUrl, googleScope, googleResponseType 을 const auth_url = `${this.googleUrl}?client_id=${this.googleClientId}&redirect_url=${this.googleRedirectUrl}&response_type=code&scope=${this.googlescope}`; window.location.href = auth_url; 구글로그인 화면을 누르면 리다이렉트 url에 오류가 있다고 하는데 동일한 리다이렉트 url로 해도 잘 안됩니다 이럴 경우 또 어떤 것을 확인해보는게 좋을까요??
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
github 주소 어디서 확인가능한가요?
소스코드 올라온 github 주소 어디서 확인이 가능할까요?
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
안녕하세요 선생님
혹시 다음 강의도 준비 중이신가요 ? 준비 중이시라면 어떤 강의 인지 알 수 있을까요
-
해결됨카카오,구글 SNS 로그인(springboot3, vue3)
application.yml에 동일 OAuth2 제공업체의 redirect-uri를 여러 개 등록할 수 있을지 궁금합니다.
안녕하세요.application.yml에 동일 OAuth2 제공업체의 redirect-uri를 여러 개 등록할 수 있을지 궁금합니다. 현재 OAuth 제공업체에 개발 및 테스트용과 배포용으로 redirect-uri를 여러 개 등록하였습니다.해당 redirect-uri를 application.yml에 복수로 등록하여 사용할 수 있을까에 대한 의견이 궁금합니다.
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
안녕하세요 섹션2. 인가코드(프론트에서 발급) 부분에서 질문 있습니다.
안녕하세요 먼저 좋은 강의 정말 감사드립니다.섹션2 인가코드(프론트에서 발급) 강의와 강의 자료에서 get 요청을 통해 인가코드 전달을 한다고 설명하셨는데, 프론트엔드 코드에서는 post로 요청하고 있고, http body로 jwt 토큰을 받으려면 post로 요청해야하는게 맞는 것 같은데, 제가 잘못 이해하고 있는건지 잘못 설명하신건지 헷갈려서 질문글 남깁니다. const response = await axios.post("http://localhost:8080/member/google/doLogin", {code});
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
filterchain 구성에서 포스트맨으로 테스트시
안녕하세요 레디스 강의에 이어 잘 수강하고 있습니다!filterchain 구성에서 포스트맨으로 테스트 시에 raw password가 그대로 컨트롤러에 전달되는데, 실무에서는 (Q.1) 이렇게 하는 방식이 허용되는지 궁금합니다. (Q.2) 안된다면 어떤식으로 해결하는지 궁금하네요!
-
해결됨카카오,구글 SNS 로그인(springboot3, vue3)
프론트엔드에서 Auth.js를 사용했을 때, 질문 있습니다.
안녕하세요. 좋은 품질의 강의를 제작해주셔서 감사합니다. 프론트엔드 부분을 vue.js에서 Next.js로 변경하여 프로젝트를 진행하고 있습니다. 해당 과정에서 막힘이 있어 질문을 드립니다. Next.js를 기반으로 Auth.js 라이브러리를 사용하여 프론트엔드 소셜 로그인을 구현하고 있습니다.소셜 로그인 흐름을 다음과 같이 생각하고 있습니다.1. 유저가 소셜 로그인 버튼을 누른다. 2. 프론트엔드에서 해당 소셜 로그인 화면을 리다이렉트 시킨다. 3. 유저는 소셜 로그인을 진행한다. 4. 소셜 로그인 성공 시, 프론트엔드 서버는 인증 코드를 소셜 서버로부터 받은 후, 백엔드로 소셜 로그인 API를 인증 코드 첨부하여 요청한다. 5. 백엔드 서버에서 인증 코드를 가지고 액세스 토큰 발급, 엑세스 토큰으로 유저 정보를 받아서 JWT를 만들어 프론트엔드로 반환해준다. 하지만 다음 피드백을 받았습니다. "Auth.js를 사용하면 소셜 서버로부터 인가코드를 직접 받아올 수 없어 백엔드 서버로 인가코드 요청을 할 수 없다."위 의견이 맞다면, 백엔드 서버에서 소셜 로그인 전 과정을 진행하고 JWT 값만 프론트엔드로 반환하는 방법 밖에 없는걸까요? 강의에서 사용되지 않은 기술에 대해서 질문하여 죄송합니다.감사합니다.
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
[질문] 소셜 로그인한 적이 없다면 회원가입 시키기
안녕하세요. 강의 감사히 잘 듣고 있습니다.강의를 듣다가 궁금한 점이 생겨 질문 드리고 싶습니다. 강의 16분쯤에 회원가입이 되어있지 않다면 회원가입한다고 말씀하셨습니다.이때 socialId 로 회원가입 여부를 판단하신다고 하셨는데, 왜 email 로는 하지 않으셨는지 궁금합니다. email 도 unique 제약조건을 걸었기 때문에 email 도 가능하다고 생각이 들었는데 강사님의 의견은 어떠한지 여쭤보고 싶습니다. 질문 읽어주셔서 감사합니다.
-
미해결스프링 시큐리티 OAuth2
Jdbc 관련 강의 및 깃헙 문의
안녕하세요. 아래는 강의 자료 캡처입니다.1, 2, 3, 4 번에 대한 각각의 강의가 없어서 문의 드립니다. 특히, 4번은..OAuth 2.0 강좌 전체에서Authorization server 에 직접 DB 나 Nosql 에 연동하는 강의가 없는 것 같아서꼭 보고 싶은데.. 깃헙에 브랜치마저도 없는 것 같아 문의 드립니다.. 감사합니다.
-
미해결스프링 시큐리티 OAuth2
OAuth2AuthorizedClient 이해 및 활용 강의 내용 질문
1 의문 ................................................강의 내용중에서oauth2Login(Customizer.withDefaults())없이oauth2Client(Customizer.withDefaults())만 사용한 경우에는 인가 처리만 하기 때문에 따로 인증 처리를 해주는 과정을 보여주셨는데 2 배경지식 ................................................oauth2Client 와 oauth2Login 의 차이는 1단계 처리 필터 : OAuth2AuthorizationRequestRedirectFilter 로 동일2단계 를 처리필터: OAuth2LoginAuthenticationFilter 대신 여기선 OAuth2AuthorizationCodeGrantFilter 사용 즉OAuth2LoginAuthenticationFilter 를 거치지않아OAuth2LoginAuthenticationFilter에서 사용하는OidcAuthorizationCodeAuthenticationProvider에서IdToken 을 추출해OidcIdToken를 만들고 OidcUser 를 로드하는 부분의 유무가 핵심적인 차이라고 생각이드는데요 그리고 OAuth2User는 인가 개념만 있지 인증 개념은 없다고 들었습니다 3 질문 ....................................................... 단순히 OAuth2User를 만들어 OAuth2AuthenticationToken을 SecurityContextHolder에 수동 저장한다고 해서 "인증된 사용자"로 간주되는 않아서로그아웃도 제대로 동작하지 않습니다 .물론 스프링 시큐리티 자체에서 세션,쿠키,SecurityContextHolder에 강제로 저장한 Authentication 없애기를 통해 일부는 처리는 되지만질문1 : keycloak 에서의 실제 세션은 로그아웃을 못하지않나요 ?@GetMapping("/logout") public String logout( HttpServletRequest request, HttpServletResponse response){ Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 로그아웃 처리 SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler(); logoutHandler.logout(request, response, authentication); // 로그아웃 요청을 위한 Keycloak 로그아웃 URL String logoutUrl = "http://localhost:8080/realms/oauth2/protocol/openid-connect/logout"; // 로그아웃 후 리디렉션할 URI String redirectUri = "http://localhost:8081/login"; // 로그아웃 후 돌아올 URL // 실제 ID Token을 가져오는 코드 // 로그아웃 URL에 필요한 파라미터들을 추가 String logoutRequestUrl = logoutUrl + "?id_token_hint=" + idTokenHint + "&post_logout_redirect_uri=" + redirectUri; // 로그아웃 요청을 Keycloak으로 리디렉션 return "redirect:" + logoutRequestUrl; }이런식으로 강제로 형식 만들려고 해도 mvc 에서 id_token을 참조할 수 있는 방법이없습니다 .디버깅으로 확인해보니scope 에 openId 를 추가해서 id_token이 있을거라고 생각했는데OAuth2AuthorizationCodeGrantFilter의 OAuth2AuthorizationCodeGrantFilter에서 authenticationResult 에 additionalParameters = {HashMap@7785} size = 4 "id_token" -> "ㅁㄴㅇㄹㄴㅇㅁㄻㄴㅇㅁㄴㅇㄹ" "session_state" -> "7a3b7dbb-ec62-4a07-8ef8-f67b17b2f3ac" "refresh_expires_in" -> {Integer@7818} 1800 "not-before-policy" -> {Integer@7820} 1746349855이런식으로 있긴하지만 사용하지않고 authenticationResult로부터 authenticationResult.getClientRegistration() 추출해서 OAuth2AuthorizedClient 만들어서 저장하고 끝내내요 private void processAuthorizationResponse(HttpServletRequest request, HttpServletResponse response) throws IOException { OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestRepository.removeAuthorizationRequest(request, response); String registrationId = (String)authorizationRequest.getAttribute("registration_id"); ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId); MultiValueMap<String, String> params = OAuth2AuthorizationResponseUtils.toMultiMap(request.getParameterMap()); String redirectUri = UrlUtils.buildFullRequestUrl(request); OAuth2AuthorizationResponse authorizationResponse = OAuth2AuthorizationResponseUtils.convert(params, redirectUri); OAuth2AuthorizationCodeAuthenticationToken authenticationRequest = new OAuth2AuthorizationCodeAuthenticationToken(clientRegistration, new OAuth2AuthorizationExchange(authorizationRequest, authorizationResponse)); authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); OAuth2AuthorizationCodeAuthenticationToken authenticationResult; try { authenticationResult = (OAuth2AuthorizationCodeAuthenticationToken)this.authenticationManager.authenticate(authenticationRequest); } catch (OAuth2AuthorizationException var16) { OAuth2AuthorizationException ex = var16; OAuth2Error error = ex.getError(); UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(authorizationRequest.getRedirectUri()).queryParam("error", new Object[]{error.getErrorCode()}); if (StringUtils.hasLength(error.getDescription())) { uriBuilder.queryParam("error_description", new Object[]{error.getDescription()}); } if (StringUtils.hasLength(error.getUri())) { uriBuilder.queryParam("error_uri", new Object[]{error.getUri()}); } this.redirectStrategy.sendRedirect(request, response, uriBuilder.build().encode().toString()); return; } Authentication currentAuthentication = this.securityContextHolderStrategy.getContext().getAuthentication(); String principalName = currentAuthentication != null ? currentAuthentication.getName() : "anonymousUser"; OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(authenticationResult.getClientRegistration(), principalName, authenticationResult.getAccessToken(), authenticationResult.getRefreshToken()); this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, currentAuthentication, request, response); String redirectUrl = authorizationRequest.getRedirectUri(); SavedRequest savedRequest = this.requestCache.getRequest(request, response); if (savedRequest != null) { redirectUrl = savedRequest.getRedirectUrl(); this.requestCache.removeRequest(request, response); } this.redirectStrategy.sendRedirect(request, response, redirectUrl); }질문 2 : 강의(OAuth2AuthorizedClient 이해 및 활용)에서는OAuth2User를 만들어 OAuth2AuthenticationToken 을 저장하는 식으로 처리하셨는데 수업을 듣다 보니 이렇게 처리한 이유가 궁금해 질문 드립니다 .
-
미해결실습으로 마스터하는 OAuth 2.0: 기본부터 보안 위험까지
수강 기간 연장 문의
안녕하세요. nextjs 몰라서 안듣고 공부하고 들어야지 하다가.. 수강기간 오늘이 마지막이라 허겁지겁 들었습니다. 가능하다면 1~2달 정도만 수강기간을 연장할수 있을까요?? 부탁드립니다..
-
미해결스프링 시큐리티 OAuth2
UserInfo 엔드포인트 요청 실습
scope 을 openId 하나만 설정하더라도 OidcUserService의 loadUser() 함수 안의 분기문에서 DefaultOAuth2UserService 를 계속 호출하길래 확인해보니 keycloak 에서 "scope": "openid profile email"형태로 리턴이 와서 항상 if 문에 걸리네요 keycloak 정책이 바뀐건지는 몰라도 내부적으로 저절로 추가하는 거 같습니다 버전도 강의와 동일한 19.0.1 버전입니다
-
해결됨카카오,구글 SNS 로그인(springboot3, vue3)
토큰 생성강의 코드 실행 문의
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/oauthdb?useSSL=false username: root password: jinwook219 jpa: database: mysql # InnoDB?? database-platform: org.hibernate.dialect.MySQL8Dialect generate-ddl: true hibernate: ddl-auto: create show_sql: true jwt: # 32글자 이상 인코딩된 문자열 : oauthserversecretaccesstokenoauthserversecretaccesstokenoauthserversecretaccesstoken secret: b2F1dGhzZXJ2ZXJzZWNyZXRhY2Nlc3N0b2tlbm9hdXRoc2VydmVyc2VjcmV0YWNjZXNzdG9rZW5vYXV0aHNlcnZlcnNlY3JldGFjY2Vzc3Rva2Vu expiration: 3000 #분단위 package com.example.oauth.auth; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.crypto.spec.SecretKeySpec; import java.security.Key; import java.util.Date; @Component public class JwtTokenProvider { private final String secretKey; private final int expiration; private Key SECRET_KEY; public JwtTokenProvider(@Value("${jwt.secret}") String secretKey, @Value("${jwt.expiration}") int expiration) { this.secretKey = secretKey; this.expiration = expiration; this.SECRET_KEY = new SecretKeySpec(java.util.Base64.getDecoder().decode(secretKey), SignatureAlgorithm.HS512.getJcaName()); } public String createToken(String email, String role){ // claims는 jwt토큰의 payload부분을 의미 Claims claims = Jwts.claims().setSubject(email); claims.put("role", role); Date now = new Date(); String token = Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(new Date(now.getTime()+ expiration*60*1000L)) .signWith(SECRET_KEY) .compact(); return token; } } Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2025-04-29T00:35:55.742+09:00 ERROR 3891 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtTokenProvider' defined in file [/Users/macforjinwook/Desktop/oauth/build/classes/java/main/com/example/oauth/auth/JwtTokenProvider.class]: Unexpected exception during bean creation at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:536) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:347) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1155) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1121) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1056) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:987) ~[spring-context-6.2.5.jar:6.2.5] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) ~[spring-context-6.2.5.jar:6.2.5] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.4.4.jar:3.4.4] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.4.jar:3.4.4] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.4.jar:3.4.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.4.jar:3.4.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.4.jar:3.4.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.4.jar:3.4.4] at com.example.oauth.OauthApplication.main(OauthApplication.java:10) ~[main/:na] Caused by: org.springframework.util.PlaceholderResolutionException: Could not resolve placeholder 'jwt.secret' in value "${jwt.secret}" at org.springframework.util.PlaceholderResolutionException.withValue(PlaceholderResolutionException.java:81) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.util.PlaceholderParser$ParsedValue.resolve(PlaceholderParser.java:423) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.util.PlaceholderParser.replacePlaceholders(PlaceholderParser.java:128) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:118) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:114) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:255) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:226) ~[spring-core-6.2.5.jar:6.2.5] at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:201) ~[spring-context-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:971) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1577) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1555) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:913) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:240) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1381) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1218) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563) ~[spring-beans-6.2.5.jar:6.2.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.2.5.jar:6.2.5] ... 16 common frames omitted 종료 코드 1(으)로 완료된 프로세스 Caused by: org.springframework.util.PlaceholderResolutionException: Could not resolve placeholder 'jwt.secret' in value "${jwt.secret}"이 부분을 보면 yml에 있는 jwt.secret을 인식 못하는 것 같은데 원인을 못 찾겠습니다 강사님 깃허브 코드를 붙혀넣어봐도 왜 이런지 잘 모르겠습니다. 혹시 이런 경우에는 어떤 것을 찾아봐야하나요??
-
해결됨카카오,구글 SNS 로그인(springboot3, vue3)
refresh 와 naver login 도 두번째 강의도 만들어주시면 어떨까요
이 수업 듣고 완전 이해 했습니다.refresh와 로그인도 해주시면 진짜 감사합니당ㅎㅎㅎ kotlin하고 nextjs 로 뚝딱뚝딱 만들었는데 이 정도만 하고 aws 에 올리면 이직 시 포트폴리오로 제출해도 문제 없을 것 같아요.
-
해결됨카카오,구글 SNS 로그인(springboot3, vue3)
백엔드 서버에서 소셜 로그인을 전부 처리하는 것에서 질문 있습니다.
"인가코드(백엔드에서 발급)" 강의에서 백엔드에서 소셜 로그인을 처리 부분에 질문이 있습니다.해당 방식의 단점이 JWT 반환 시, redirect 방식을 사용하므로 JWT 토큰 값이 노출될 수 있어 보안상 문제가 될 수 있다고 이해했습니다.하지만 JWT 토큰 값 자체는 브라우저 로컬 스토리지에 저장하면 어떻게든 유저에게 노출되는 것 아닌가 라는 생각이 듭니다.이에 대한 강사님의 생각이 궁금합니다.
-
미해결카카오,구글 SNS 로그인(springboot3, vue3)
강의 내용 문의 입니당
안녕하세요수업 들으면서 동시에 코틀린으로 코딩하다보니 중간중간 놓치는 부분이 있어서 코드 제공이 가능할까요?코드 제공 주신 다는 내용은 들었는데 자료에 안보여서 동영상을 여기저기 반복 재생하니 진도가 느려지네요
-
미해결스프링 시큐리티 OAuth2
RFC 문서에서의 AccessToken 발급 방식 궁금한점
강사님 안녕하세요. 진짜 오랜만에 질문드립니다. 다름이 아니라 제가 Authorization Code Grant 방식에서의 OAuth2 인증 인가 프로세스를 RFC 문서에서 읽고 있었습니다. https://datatracker.ietf.org/doc/html/rfc6749#section-4.1에 따르면, (E) The authorization server authenticates the client, validates the authorization code, and ensures that the redirection URI received matches the URI used to redirect the client in step (C). If valid, the authorization server responds back with an access token and, optionally, a refresh token. (E) 인증 서버는 클라이언트를 인증하고, 인가 코드(authorization code)의 유효성을 검사하며, (C) 단계에서 클라이언트를 리다이렉션할 때 사용된 리디렉션 URI가 받은 URI와 일치하는지 확인합니다. 만약 유효하다면, 인증 서버는 액세스 토큰(access token)과 선택적으로 리프레시 토큰(refresh token)을 응답으로 반환합니다. 라고 나와있습니다. 즉, AccessToken 을 요청할때 Http Body 에 명시하는 redirect_uri 주소가, Authorization Code 를 발급할 때 사용한 redirect_uri 와 같으면 이를 유효한 요청이라 판단하고, AccessToken 을 내려준다고 나와있는데요. 근데 우리의 Application. 즉, Client 가 React 와 Spring 으로 나누어진 환경이며, 인가코드 발급은 Front, 나머지는 Back 이 담당한다고 한다면. Frontend 가 Authroization Code 를 발급받고(redirect uri 는 Front 주소) 인가코드를 가지고 Backend 의 특정 Endpoint 에 요청을 찌른다. Backend 가 그 Authroization Code 를 받고, RestTemplate 로 token uri 주소로 code&redierct_uri(백엔드 redirect uri) 등등을 body 에 명시하여 넘길텐데.. 인가서버는 어떻게 엑세스토큰을 내려주는건가요?분명 Frontend 가 Authorization Code 를 발급받을때는 redirecturi 가 Frontend 주소였을테고, Backend 가 AccessToken 을 요청할때 사용된 redirecturi 는 Backend 주소일텐데.. 좀 궁금합니다. OAuth2 Provider 마다 다른걸까요? 많은 블로그에서는 제가 적은 프로세스대로 구현한다고 나와있어 의문점이 들었습니다. 우선 현재는 Spring OAuth2 모듈을 사용하지 않고, 프로젝트 경량화를 위해 OAuth2 Client 모듈이 수행하는 과정을 백엔드에서 직접 모두 구현하여 처리하는 흐름으로 구현해놓긴 했습니다.
-
미해결스프링 시큐리티 OAuth2
강의자료.zip 를 다운로드 받았는데 압축이 풀리지 않습니다. 확인 부탁드려요
강의자료.zip 를 다운로드 받았는데 압축이 풀리지 않습니다. 확인 부탁 드려요- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.