Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OIDC 소셜 로그인 구현 #119

Merged
merged 92 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
0853ed5
chore: 시큐리티 form 로그인 및 세션 등 비활성화 처리
uwoobeat Dec 14, 2023
7a25515
Merge branch 'develop' into feature/62-social-login
uwoobeat Dec 22, 2023
e635180
Merge branch 'develop' into feature/62-social-login
uwoobeat Dec 23, 2023
77081d2
Merge branch 'develop' into feature/62-social-login
uwoobeat Dec 28, 2023
ba5966f
Merge branch 'develop' into feature/62-social-login
uwoobeat Dec 30, 2023
856e18c
chore: oauth 의존성 추가
uwoobeat Jan 2, 2024
b4c12e7
chore: 시큐리티 yml 파일 작성
uwoobeat Jan 2, 2024
0e00ec5
feat: OAuth 정보로 조회하는 메서드 추가
uwoobeat Jan 3, 2024
9e8b639
feat: OAuth 정보 필드를 멤버 엔티티에 추가
uwoobeat Jan 3, 2024
13a4d22
feat: 게스트 멤버 유저 생성 메서드 구현
uwoobeat Jan 3, 2024
efb998e
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 3, 2024
5ee57f3
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 4, 2024
3163c0f
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 4, 2024
670938a
chore: 공통 프로파일 분리
uwoobeat Jan 4, 2024
7c9596b
chore: jwt 의존성 추가
uwoobeat Jan 4, 2024
cc95255
chore: 시큐리티 전용 설정 파일 분리
uwoobeat Jan 4, 2024
d6e9b57
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 5, 2024
6e4872a
feat: 시큐리티 yml에 만료시간 및 발급자 추가
uwoobeat Jan 6, 2024
42c94d0
feat: JwtProperties 추가
uwoobeat Jan 6, 2024
cec999e
feat: JwtTokenProvider 구현
uwoobeat Jan 6, 2024
dbc2b80
feat: 에러코드 추가
uwoobeat Jan 6, 2024
2f9d77f
feat: 리프레시 토큰 및 레포지터리 임시 구현
uwoobeat Jan 6, 2024
196a616
feat: OIDC 유저 서비스 구현
uwoobeat Jan 6, 2024
99b4304
feat: 성공 핸들러 임시 추가
uwoobeat Jan 6, 2024
7caea69
feat: 엑세스 토큰 DTO 추가
uwoobeat Jan 6, 2024
cb1f2c5
feat: 시큐리티 OAuth 설정 반영
uwoobeat Jan 6, 2024
1c41a12
fix: MemberRole이 게스트 상태를 가지도록 수정
uwoobeat Jan 9, 2024
97ef666
feat: 게스트 역할 여부 확인을 위한 커스텀 OIDC 유저 구현
uwoobeat Jan 9, 2024
2626b34
feat: 표준 스코프 스펙과 관계없이 userinfo를 가져오도록 빈 스코프로 설정
uwoobeat Jan 9, 2024
d67f593
refactor: OIDC 유저 서비스가 OidcUser 인터페이스에 의존하도록 변경
uwoobeat Jan 9, 2024
aadb6d9
feat: 시큐리티 관련 상수 클래스 추가
uwoobeat Jan 9, 2024
342f0e9
feat: OIDC 로그인 성공 핸들러 구현
uwoobeat Jan 9, 2024
3b21529
refactor: 상수 클래스로 대체
uwoobeat Jan 9, 2024
8626bf6
docs: 주석 변경
uwoobeat Jan 9, 2024
f1e6284
fix: 토큰 키가 필요한 시점에 초기화되도록 수정
uwoobeat Jan 9, 2024
09ad200
fix: 오타 및 포매팅 수정
uwoobeat Jan 9, 2024
1262542
refactor: 테스트 시 JPA 관련 빈 로딩 제외를 위해 설정 클래스 분리
uwoobeat Jan 9, 2024
2ac039b
refactor: 리프레시 토큰의 ttl을 인자로 받도록 수정
uwoobeat Jan 9, 2024
71ca490
test: 리프레시 토큰 레포지터리 테스트 작성
uwoobeat Jan 9, 2024
7f4716d
refactor: token 패키지를 auth 패키지로 변경
uwoobeat Jan 9, 2024
a037b39
feat: 마지막 로그인 시간 업데이트 기능 구현
uwoobeat Jan 9, 2024
ffc20f9
feat: 게스트 멤버 회원가입 구현
uwoobeat Jan 9, 2024
a16eed1
test: 멤버 도메인 유닛 테스트 변경 및 회원가입 테스트 작성
uwoobeat Jan 9, 2024
7b9428c
feat: 회원가입 서비스 및 컨트롤러 구현
uwoobeat Jan 9, 2024
1abbe32
refactor: 필터와 토큰 간 결합도 낮추기 위해 프로바이더와 서비스 분리
uwoobeat Jan 9, 2024
57d9e2b
refactor: 리다이렉트 경로 및 상수 수정
uwoobeat Jan 9, 2024
ce2f65e
feat: JWT 인증 필터 구현
uwoobeat Jan 9, 2024
94c56e8
feat: 토큰 재발급 로직 구현
uwoobeat Jan 10, 2024
b6485ee
feat: 멤버 가입 DTO 추가
uwoobeat Jan 10, 2024
cee92ff
feat: 토큰 만료 여부 확인 메서드 구현
uwoobeat Jan 10, 2024
598f6c8
style: spotlessApply
uwoobeat Jan 10, 2024
9941bce
fix: 토큰이 있는 경우에만 체크하도록 수정
uwoobeat Jan 10, 2024
eca1391
refactor: 로컬 환경에서는 디비 스키마 항상 새로 생성
uwoobeat Jan 10, 2024
a372f5e
refactor: 프론트 회원가입 페이지 url 반영
uwoobeat Jan 10, 2024
8b879d4
feat: 허용된 URL 외에는 인증 수행하도록 변경
uwoobeat Jan 10, 2024
8a22330
feat: JWT 인증 필터 추가
uwoobeat Jan 10, 2024
5af53b9
refactor: 회원가입 필요 여부는 헤더에 담아서 응답하도록 변경
uwoobeat Jan 10, 2024
31392da
feat: atk, rtk 둘 다 만료 아닌 경우 rtk 재발급하는 로직 추가
uwoobeat Jan 10, 2024
ad83cab
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 10, 2024
a4d525c
refactor: 커스텀 헤더 이름 변경
uwoobeat Jan 11, 2024
062b912
refactor: 상수 클래스의 인스턴스화 막기
uwoobeat Jan 11, 2024
6eb9673
refactor: 에러코드 위치 변경
uwoobeat Jan 11, 2024
3a7a197
style: 포매팅 수정
uwoobeat Jan 11, 2024
240a020
docs: 인증 API 스웨거 태그 추가
uwoobeat Jan 11, 2024
f731aa3
chore: 환경변수 디폴트값 지정
uwoobeat Jan 12, 2024
3a215d9
fix: 누락된 쉼표 추가
uwoobeat Jan 12, 2024
e4d657f
style: 개행 추가
uwoobeat Jan 12, 2024
6f7952b
fix: 컨트롤러 테스트에서 시큐리티 설정 제외
uwoobeat Jan 12, 2024
19206ab
feat: 애플 키파일로 시크릿 만드는 로직 임시 구현
uwoobeat Jan 12, 2024
9cc1563
chore: 애플 프로바이더 및 클라이언트 정보 추가
uwoobeat Jan 12, 2024
c93bda6
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 12, 2024
05b5b6d
Merge branch 'feature/62-social-login' of https://github.com/depromee…
uwoobeat Jan 12, 2024
fa04350
feat: 애플 요청 엔티티 컨버터 구현
uwoobeat Jan 12, 2024
0c0bd40
feat: 애플 요청 엔티티 컨버터 V2 구현
uwoobeat Jan 12, 2024
7593644
feat: 애플 프로퍼티 로드하는 로직 구현
uwoobeat Jan 12, 2024
50b84d7
docs: TODO 추가
uwoobeat Jan 12, 2024
257a560
feat: 에러코드 추가
uwoobeat Jan 12, 2024
cb8403f
feat: OIDC 로그인 실패 핸들러 추가
uwoobeat Jan 12, 2024
c750a19
feat: 커스텀 OAuth 엑세스 토큰 클라이언트 구현
uwoobeat Jan 14, 2024
80c1b84
refactor: 한 라인에 한번의 작업만 수행하도록 개선
uwoobeat Jan 14, 2024
a4e35e4
fix: 오타 수정
uwoobeat Jan 14, 2024
d65c2ff
feat: 컨트롤러 테스트 임시 비활성화 처리
uwoobeat Jan 14, 2024
fdf3327
refactor: 컴포넌트 추가
uwoobeat Jan 14, 2024
d86a75a
feat: 시큐리티 설정 추가
uwoobeat Jan 14, 2024
5fe494c
Merge branch 'develop' into feature/62-social-login
uwoobeat Jan 14, 2024
42a0515
style: spotless 적용
uwoobeat Jan 14, 2024
2f3e26d
chore: 엑세스 토큰 시간 변경
uwoobeat Jan 14, 2024
aae6caa
fix: OAuth 관련 설정 비활성화
uwoobeat Jan 14, 2024
a175a27
fix: OAuth 관련 환경변수 디폴트값 설정
uwoobeat Jan 14, 2024
1195e51
fix: 필터 모킹 추가
uwoobeat Jan 14, 2024
b282147
docs: 주석 수정
uwoobeat Jan 14, 2024
3fe9905
style: spotless 적용
uwoobeat Jan 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ dependencies {
// Spring Security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.security:spring-security-oauth2-client'
implementation 'org.springframework.security:spring-security-oauth2-jose'

// JWT
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'

// Apple Login
implementation 'org.bouncycastle:bcpkix-jdk18on:1.72'

// Querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
Expand All @@ -57,9 +67,8 @@ dependencies {
// AWS
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'

// test lombok
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/com/depromeet/TenminuteApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class TenminuteApplication {
public static void main(String[] args) {
SpringApplication.run(TenminuteApplication.class, args);
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/com/depromeet/domain/auth/api/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.depromeet.domain.auth.api;

import com.depromeet.domain.auth.application.AuthService;
import com.depromeet.domain.auth.application.JwtTokenService;
import com.depromeet.domain.auth.dto.MemberRegisterRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "1. [인증]", description = "인증 관련 API")
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {

private final JwtTokenService jwtTokenService;
private final AuthService authService;

@Operation(summary = "회원가입", description = "회원가입을 진행합니다.")
@PostMapping("/register")
public ResponseEntity<Void> memberRegister(@Valid @RequestBody MemberRegisterRequest request) {
authService.registerMember(request);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.depromeet.domain.auth.application;

import com.depromeet.domain.auth.dto.MemberRegisterRequest;
import com.depromeet.domain.member.dao.MemberRepository;
import com.depromeet.domain.member.domain.Member;
import com.depromeet.global.util.MemberUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService {

private final MemberRepository memberRepository;
private final MemberUtil memberUtil;

public void registerMember(MemberRegisterRequest request) {
final Member member = memberUtil.getCurrentMember();
member.register(request.nickname());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.depromeet.domain.auth.application;

import com.depromeet.domain.auth.dao.RefreshTokenRepository;
import com.depromeet.domain.auth.domain.RefreshToken;
import com.depromeet.domain.auth.dto.AccessToken;
import com.depromeet.domain.member.dao.MemberRepository;
import com.depromeet.domain.member.domain.Member;
import com.depromeet.domain.member.domain.MemberRole;
import com.depromeet.global.config.security.PrincipalDetails;
import com.depromeet.global.security.JwtTokenProvider;
import java.util.NoSuchElementException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class JwtTokenService {

private final JwtTokenProvider jwtTokenProvider;
private final MemberRepository memberRepository;
private final RefreshTokenRepository refreshTokenRepository;

public String createAccessToken(Long memberId, MemberRole memberRole) {
return jwtTokenProvider.generateAccessToken(memberId, memberRole);
}

public String createRefreshToken(Long memberId) {
String token = jwtTokenProvider.generateRefreshToken(memberId);
RefreshToken refreshToken =
RefreshToken.builder()
.memberId(memberId)
.token(token)
.ttl(jwtTokenProvider.getRefreshTokenExpirationTime())
.build();
refreshTokenRepository.save(refreshToken);
return token;
}

public String reissueAccessToken(String refreshToken) {
Member member = getMemberFrom(refreshToken);
return createAccessToken(member.getId(), member.getRole());
}

public String reissueAccessToken(AccessToken accessToken) {
return createAccessToken(accessToken.memberId(), accessToken.memberRole());
}

public String reissueRefreshToken(String refreshToken) {
Member member = getMemberFrom(refreshToken);
return createRefreshToken(member.getId());
}

public String reissueRefreshToken(AccessToken accessToken) {
return createRefreshToken(accessToken.memberId());
}

private Member getMemberFrom(String refreshToken) throws NoSuchElementException {
Long memberId = jwtTokenProvider.parseRefreshToken(refreshToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseRefreshToken 메서드는 customException을 내보내고있는데 throws에 NoSuchElementException은 어디서 나온건가용??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 이 부분 TODO로 해놓고 수정하려고 했는데 빼먹었네요.

orElseThrow()에서 CustomException(ErrorCode.MEMBER_NOT_FOUND으로 던지는 대신 디폴트 예외엔 NoSuchElementException으로 던지도록 했습니다.

이유는 CustomException은 클라이언트한테 어떤 status code를 내려줄 것인지도 결정하고 있는데, getMemberFrom 에서 발생한 예외는 JwtAuthenticationFilter 로 가는데, 여기서 어떤 예외가 발생하든 간에 인증 실패이므로 401을 내려줘야 합니다. 근데 MEMBER_NOT_FOUND 를 던지면 404가 나가니까 NoSuchElementException으로 던지고 CustomAuthenticationEntryPoint 에서 이걸 잡아서 401로 매핑해줄 계획이었어요.

근데 인증 과정에서 발생하는 예외를 잡는 CustomAuthenticationEntryPoint를 아직 구현을 안해서 이 부분은 추가로 작업하도록 할게요.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NoSuchElementException는 어디서 던지나용 ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

orElseThrow()가 디폴트로 던지는 예외가 NoSuchElementException 이에용

return memberRepository.findById(memberId).orElseThrow();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요기 에러처리 안된건가용?

Copy link
Member Author

@uwoobeat uwoobeat Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AuthenticationEntryPoint에서 잡아줘야 하는데 구현을 안해놨네요~
서비스 레이어에서는 그냥 던져도 될 것 같아요

}

public Authentication getAuthentication(String accessToken) {
AccessToken parsedAccessToken = jwtTokenProvider.parseAccessToken(accessToken);

UserDetails userDetails =
new PrincipalDetails(
parsedAccessToken.memberId(), parsedAccessToken.memberRole().name());

return new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
}

public boolean isAccessTokenExpired(String accessToken) {
return jwtTokenProvider.isAccessTokenExpired(accessToken);
}

public boolean isRefreshTokenExpired(String refreshToken) {
return jwtTokenProvider.isRefreshTokenExpired(refreshToken);
}

public AccessToken parseAccessToken(String accessToken) {
return jwtTokenProvider.parseAccessToken(accessToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.depromeet.domain.auth.dao;

import com.depromeet.domain.auth.domain.RefreshToken;
import org.springframework.data.repository.CrudRepository;

public interface RefreshTokenRepository extends CrudRepository<RefreshToken, Long> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.depromeet.domain.auth.domain;

import lombok.Builder;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.TimeToLive;

@Getter
@RedisHash(value = "refreshToken")
public class RefreshToken {

@Id private Long memberId;
private String token;
@TimeToLive private long ttl;

@Builder
public RefreshToken(Long memberId, String token, long ttl) {
this.memberId = memberId;
this.token = token;
this.ttl = ttl;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.depromeet.domain.auth.dto;

import com.depromeet.domain.member.domain.MemberRole;

public record AccessToken(Long memberId, MemberRole memberRole) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.depromeet.domain.auth.dto;

public record MemberRegisterRequest(String nickname) {
// TODO: Add validation
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package com.depromeet.domain.member.dao;

import com.depromeet.domain.member.domain.Member;
import com.depromeet.domain.member.domain.OauthInfo;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {}
public interface MemberRepository extends JpaRepository<Member, Long> {

Optional<Member> findByOauthInfo(OauthInfo oauthInfo);
}
33 changes: 33 additions & 0 deletions src/main/java/com/depromeet/domain/member/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.depromeet.domain.common.model.BaseTimeEntity;
import com.depromeet.domain.mission.domain.Mission;
import com.depromeet.global.error.exception.CustomException;
import com.depromeet.global.error.exception.ErrorCode;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
Expand Down Expand Up @@ -32,6 +34,8 @@ public class Member extends BaseTimeEntity {

@Embedded private Profile profile;

@Embedded private OauthInfo oauthInfo;

@Enumerated(EnumType.STRING)
private MemberStatus status;

Expand All @@ -49,17 +53,28 @@ public class Member extends BaseTimeEntity {
@Builder(access = AccessLevel.PRIVATE)
private Member(
Profile profile,
OauthInfo oauthInfo,
MemberStatus status,
MemberRole role,
MemberVisibility visibility,
LocalDateTime lastLoginAt) {
this.profile = profile;
this.oauthInfo = oauthInfo;
this.status = status;
this.role = role;
this.visibility = visibility;
this.lastLoginAt = lastLoginAt;
}

public static Member createGuestMember(OauthInfo oauthInfo) {
return Member.builder()
.oauthInfo(oauthInfo)
.status(MemberStatus.NORMAL)
.role(MemberRole.GUEST)
.visibility(MemberVisibility.PUBLIC)
.build();
}

public static Member createNormalMember(Profile profile) {
return Member.builder()
.profile(profile)
Expand All @@ -69,4 +84,22 @@ public static Member createNormalMember(Profile profile) {
.lastLoginAt(LocalDateTime.now())
.build();
}

public void updateLastLoginAt(LocalDateTime lastLoginAt) {
this.lastLoginAt = lastLoginAt;
}

public void register(String nickname) {
validateRegisterAvailable();
// TODO: Profile 클래스를 제거하고 Member 클래스 필드로 변경
// TODO: profileImageUrl이 항상 null이 되는 문제 해결
this.profile = new Profile(nickname, null);
Comment on lines +94 to +96
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

object storage에 user default이미지 넣어두고 해당 값 상수로 넣으면 좋을 것 같습니다👍🏻👍🏻

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 이거는 나중에 프로바이더에서 제공하는 프로필 이미지 복사해서 object storage에 넣는 로직도 추가 작업할 예정인데, 이렇게 하면 register 호출했을 때 url이 다시 null로 덮여씌워지는 문제가 있거든요. 그래서 TODO 작성해둔 거였어요

그리고 default 이미지의 경우 프론트에서 가지고 있고 서버에서는 null로 두는게 좋을 것 같습니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

말씀하신대로 디폴트 이미지는 프론트에서 가지고있는게 좋겠네용
추 후에 회원가입 단계에서 프로필 이미지도 설정 가능하도록 기획하고 있어서 그때 추가하면 좋을 것 같네용

this.role = MemberRole.USER;
}

private void validateRegisterAvailable() {
if (role != MemberRole.GUEST) {
throw new CustomException(ErrorCode.MEMBER_ALREADY_REGISTERED);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
@Getter
@AllArgsConstructor
public enum MemberRole {
USER("USER"),
ADMIN("ADMIN");
GUEST("ROLE_GUEST"),
USER("ROLE_USER"),
ADMIN("ROLE_ADMIN");

private final String value;
}
18 changes: 18 additions & 0 deletions src/main/java/com/depromeet/domain/member/domain/OauthInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.depromeet.domain.member.domain;

import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Embeddable
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OauthInfo {

private String oauthId;
private String oauthProvider;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.depromeet.global.common.constants;

public final class SecurityConstants {

private SecurityConstants() {}

public static final String TOKEN_ROLE_NAME = "role";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String ACCESS_TOKEN_HEADER = "Authorization";
public static final String REFRESH_TOKEN_HEADER = "Refresh-Token";
public static final String REGISTER_REQUIRED_HEADER = "Registration-Required";
}
Loading