우당탕탕 개발일지
AWS Cognito를 활용한 회원가입 본문
< 사용자 풀 생성 >
1단계. 로그인 환경 구성
유저 아이디로 로그인을 구현할 것이기 때문에 사용자 이름을 선택해 주었다.
2단계. 보안 요구 사항 구성
MFA 방법으로 SMS메시지 혹은 인증 앱을 이용하는 방법이 있는데, SMS 메시지 방식은 Amazon SMS에서 비용이 별도 부과되어 사용하지 않기로 결정했다.
3단계. 가입 환경 구성
cognito는 인증/인가 기능만 대체해주고, 실제 사용자 정보는 cognito_id로 다른 DB에 저장할 예정이기 때문에 default 값으로 설정한다.
4단계. 메시지 전송 구성
5단계. 앱 통합
백엔드 서버에서 인증을 처리하기 때문에 기밀 클라이언트를 설정해주었고, access-token은 1시간, refresh-token은 1일로 설정해주었다.
클라이언트 보안키 표시를 활성화한 후, 클라이언트 ID와 보안키를 확인한다. 이 두 값들을 가지고 있어야 cognito의 사용자풀에 접근이 가능하다. 따라서 ID와 보안키가 공개되지 않도록 주의해야 한다.
< Spring Security 연동 >
1. build.gradle 설정
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// MariaDB
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
// security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'software.amazon.awssdk:cognitoidentityprovider:2.20.66'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
2. application.yml 설정
spring:
security:
oauth2:
client:
registration:
cognito:
client-id: ${application.spring.security.oauth2.registration.client-id}
client-secret: ${application.spring.security.oauth2.registration.client-secret}
scope:
- openid
redirect-uri: ${application.spring.security.oauth2.registration.redirect-uri}
client-name: ${application.spring.security.oauth2.registration.client-name}
provider:
conito:
issuer-uri: ${application.spring.security.oauth2.provider.issuer-uri}
user-name-attribute: cognito:email
jpa:
database: mariadb
hibernate:
ddl-auto: update # (1) 스키마 자동 생성
show-sql: true # (2) SQL 쿼리 출력
generate-ddl: true
properties:
hibernate:
format_sql: true # (3) SQL pretty print
defer-datasource-initialization: true
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: ${application.spring.datasource.url}
username: ${application.spring.datasource.username}
password: ${application.spring.datasource.password}
clientId, clientSecret, clientName은 사용자 풀을 생성하며 만든 앱클라이언트 정보이다.
issuerUri는 Cognito Identity Pool의 발행자 URI로, 사용자 풀 ID를 적으면 된다.
region은 arn을 참고하여 적으면 된다.
3. DTO 작성
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MemberRequest {
private String userId;
private String userName;
private String userPassword;
private String userEmail;
private String userPhoneNumber;
}
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserResponse {
private String userSub;
private String userId;
private String email;
private String accessToken;
private String refreshToken;
private Boolean status;
}
4. controller 작성
import com.example.MyPage.dto.user.UserRequest;
import com.example.MyPage.dto.user.UserResponse;
import com.example.MyPage.repository.UserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient;
import software.amazon.awssdk.services.cognitoidentityprovider.model.AttributeType;
import software.amazon.awssdk.services.cognitoidentityprovider.model.SignUpRequest;
import software.amazon.awssdk.services.cognitoidentityprovider.model.SignUpResponse;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
@Slf4j
public class UserController {
private final UserRepository userRepository;
@Value("${spring.security.oauth2.client.registration.cognito.aws-region}")
private String awsRegion;
@Value("${spring.security.oauth2.client.registration.cognito.client-id}")
private String clientId;
@PostMapping("/user/join")
public ResponseEntity<UserResponse> join(@RequestBody UserRequest userRequest) {
// AWS Cognito 클라이언트 생성
try (CognitoIdentityProviderClient cognitoClient = CognitoIdentityProviderClient.builder()
.region(Region.of(awsRegion))
.credentialsProvider(DefaultCredentialsProvider.create())
.build()) {
// 회원가입 요청 생성
SignUpRequest signUpRequest = SignUpRequest.builder()
.clientId(clientId)
.username(userRequest.getUserEmail()) // Cognito에서는 이메일을 username으로 사용
.password(userRequest.getUserPassword())
.userAttributes(AttributeType.builder()
.name("email")
.value(userRequest.getUserEmail())
.build())
.build();
// 회원가입 요청 보내기
SignUpResponse signUpResponse = cognitoClient.signUp(signUpRequest);
// 회원가입 성공 시, 사용자의 Cognito ID 반환
UserResponse userResponse = UserResponse.builder()
.userSub(signUpResponse.userSub())
.status(true)
.build();
return ResponseEntity.ok(userResponse);
} catch (Exception e) {
log.error("회원가입 요청 중 오류 발생: ", e);
return ResponseEntity.status(500).build();
}
}
'Spring' 카테고리의 다른 글
[Spring] API 공통 응답 (0) | 2024.09.20 |
---|---|
[Spring] Swagger - API 명세서 작성 (1) | 2024.09.15 |
[Spring] JWT 서비스 (0) | 2024.07.11 |
JPA - 데이터 모델링 (0) | 2024.05.20 |
SpringBoot - MVC (0) | 2023.06.16 |