아장아장 개발 일기

Spring + AWS Cognito 세팅 및 로그인, 회원가입, 로그아웃 구현 본문

개발/AWS

Spring + AWS Cognito 세팅 및 로그인, 회원가입, 로그아웃 구현

빨간머리 마녀 🍒 2022. 6. 15. 15:35

Java Spring과 AWS Cognito를 연동하는 방법을 알아봅니다.
로그인, 회원가입, 로그아웃까지 가장 기본적인 회원인증 기능을 구현합니다.

1. Amazon Cognito 세팅하기

먼저 아래 두가지를 유의하여 aws cognito console에 userpool을 생성합니다.

(1) CallbackURL 스프링 환경설정 파일의 redirect-uri와 일치하도록 설정(로그인후 랜딩 페이지)

(2) logoutURL 스프링 환경설정 파일의 logoutUrl과 일치하도록 설정(로그아웃후 랜딩페이지)

2. Spring 세팅하기


build.gradle

implementation 'org.springframework.security:spring-security-oauth2-client'
implementation 'org.springframework.security:spring-security-oauth2-jose'
implementation 'org.springframework.security:spring-security-config'
implementation 'org.springframework.security:spring-security-web'


application.properties

spring.security.oauth2.client.registration.cognito.clientId=(clientId 입력)
spring.security.oauth2.client.registration.cognito.clientSecret=(clientSecret 입력)
spring.security.oauth2.client.registration.cognito.scope=openid
spring.security.oauth2.client.registration.cognito.redirectUri=http://localhost:8080/login/oauth2/code/cognito
spring.security.oauth2.client.registration.cognito.clientName=(clientName 입력)
spring.security.oauth2.client.provider.cognito.issuerUri=https://cognito-idp.{region}.amazonaws.com/{poolId}
spring.security.oauth2.client.provider.cognito.user-name-attribute=cognito:username

cognito.logoutUrl=http://localhost:8080/

 

client id, client secret, client name, pool id는 cognito console에서 확인하실 수 있습니다.(아래 이미지 참고)

 

AWS Cognito Console에서 User pool ID 확인
AWS Cognito console에서 client name, client id, client secret 확인

3. Spring Security 설정

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${spring.security.oauth2.client.registration.cognito.clientId}")
    private String clientId;
    @Value("${cognito.logoutUrl}")
    private String logoutUrl;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
                .and()
                .authorizeRequests(authz -> authz.mvcMatchers("/")
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .oauth2Login()
                .and()
                .logout()
                .logoutSuccessUrl("/");
    }
}


위의 Security 설정으로도 기본적인 로그아웃이 잘 작동하나, 필요에 따라 커스터마이즈된 logoutSuccessHandler를 따로 추가할 수도 있습니다.

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    @Value("${spring.security.oauth2.client.registration.cognito.clientId}")
    private String clientId;
    @Value("${cognito.logoutUrl}")
    private String logoutUrl;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
                .and()
                .authorizeRequests(authz -> authz.mvcMatchers("/")
                        .permitAll()
                        .anyRequest()
                        .authenticated())
                .oauth2Login()
                .and()
                .logout()
                .logoutSuccessHandler(new CognitoOidcLogoutSuccessHandler(logoutUrl, clientId));
    }
}

 

CognitoOidLogoutSuccessHandler.java

@RequiredArgsConstructor
public class CognitoOidcLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {

    private final String logoutUrl;
    private final String clientId;

    @Override
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        UriComponents baseUrl = UriComponentsBuilder
                .fromHttpUrl(UrlUtils.buildFullRequestUrl(request))
                .replacePath(request.getContextPath())
                .replaceQuery(null)
                .fragment(null)
                .build();

        return UriComponentsBuilder
                .fromUri(URI.create(logoutUrl))
                .queryParam("client_id", clientId)
                .queryParam("logout_uri", baseUrl)
                .encode(StandardCharsets.UTF_8)
                .build()
                .toUriString();
    }
}

4. 랜딩페이지 설정

home.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8">
        <title>환영합니다.</title>
    </head>
    <body>
        <div>
            <h1 class="title">OAuth 2.0 Spring Security Cognito Demo</h1>
            <div sec:authorize="isAuthenticated()">
                <div class="box">
                    안녕하세요, <strong th:text="${#authentication.name}"></strong>님!
                </div>
                <div class="box">
                    <a th:href="@{/logout}">로그아웃</a>
                </div>
            </div>
            <div sec:authorize="isAnonymous()">
                <div class="box">
                    <a class="button login is-primary" th:href="@{/oauth2/authorization/cognito}">
                        아마존 Cognito로 로그인하기</a>
                </div>
            </div>
        </div>
    </body>
</html>
 
@Configuration
public class CognitoWebConfiguration implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}

 

* 참고한 페이지

https://rieckpil.de/oidc-logout-with-aws-cognito-and-spring-security/

 

OIDC Logout With AWS Cognito and Spring Security - rieckpil

Configure Spring Security for a full user logout using AWS Cognito as an OIDC Identity Provider (no RP-Initiated Logout support yet).

rieckpil.de

https://www.baeldung.com/spring-security-oauth-cognito

 

Spring Security with Amazon Cognito | Baeldung

Learn how Spring Security makes it easy to integrate a client application with Amazon Cognito.

www.baeldung.com

 

Comments