Spring Boot + OAuth2로 로그인 기능 구현하기

Programmingzi·2023년 11월 15일

OAuth2란?

OAuth는 인증을 위한 개방형 표준 프로토콜이다.
쉽게 말해, 사용자 개인정보와 인증 서비스를 신뢰할 만한 타사 플랫폼에 위임하는 것이다.
따라서, 사용자는 소셜 계정으로 간편하게 로그인할 수 있고 개발자는 인증 서비스 구현에 대한 부담을 줄일 수 있다.

OAuth1과 OAuth2의 차이점?

  • 토큰 갱신: OAuth1에서는 토큰을 갱신하는 것이 어려웠지만, OAuth2에서는 새로운 토큰을 쉽게 발급하고 갱신할 수 있다.(2에서 Refresh Toekn 개념이 등장함)
  • 범용성: OAuth2은 모바일 기기와 같은 다양한 플랫폼에서 사용할 수 있지만, OAuth1은 덜 유연하며 웹 기반 애플리케이션에서 주로 사용된다.



전체 flow

  1. 안드로이드에서 Authorization Server에 요청해서 Athorization Code를 받는다. 받은 코드를 요청 파라미터에 담아 /oauth/kakao?code={code} url을 호출한다.

  2. /oauth/kakao?code={code}로 요청을 받은 Spring 서버는 Authorization Code로 Authorization Server에 Access Token을 요청한다.

  3. Authorization Server는 서버에게 Access Token을 발급한다.

  4. 서버는 Access Toekn을 바탕으로 Resource Server에게 사용자 정보를 요청한다.

  5. Resource Server는 해당 사용자를 반환한다.

  6. 서버는 사용자를 받아서 처음 로그인한 경우 DB에 사용자 정보를 저장한다.

  7. 클라이언트에게 사용자 정보를 반환한다.



OAuth2 구현

1. SNS Developer 페이지에 애플리케이션 등록

카카오, 네이버, 구글 등의 developer 페이지에 접속하여 애플리케이션을 등록하고, Redirect URI를 등록한다.

2. application-oauth.properties 생성

#Kakao
spring.security.oauth2.client.registration.kakao.client-id = {}
spring.security.oauth2.client.registration.kakao.scope = profile_nickname, account_email
spring.security.oauth2.client.registration.kakao.client-name = Kakao
spring.security.oauth2.client.registration.kakao.authorization-grant-type = authorization_code
spring.security.oauth2.client.registration.kakao.redirect-uri = {http://localhost:XXXX/XX}
spring.security.oauth2.client.registration.kakao.client-authentication-method = POST

spring.security.oauth2.client.provider.kakao.authorization-uri = https://kauth.kakao.com/oauth/authorize
spring.security.oauth2.client.provider.kakao.token-uri = https://kauth.kakao.com/oauth/token
spring.security.oauth2.client.provider.kakao.user-info-uri = https://kapi.kakao.com/v2/user/me
spring.security.oauth2.client.provider.kakao.user-name-attribute = id

yml 파일에 인증 정보를 추가한다.
여기서 client-id는 developer 페이지에서 발급받은 값을 넣어준다.
oauth와 관련된 설정은 따로 관리하고 싶어 application-oauth.properties로 생성하여 기존의 설정 파일과 분리했다.

3. MemberController.java

@GetMapping("/oauth/kakao")
    public ResponseEntity kakaoLoin(@RequestParam("code") String code)
                                        throws JsonProcessingException {
        Member member = oauthMemberService.oauthLogin(code, "kakao");


        MemberResponseDto memberResponseDto = new MemberResponseDto(member.getEmail(), member.getNickname());
        return ResponseEntity.status(HttpStatus.OK).body(memberResponseDto);
    }

해당 URL은 이전에 developer 페이지에서 등록한 Redirect URI와 동일하다. Authorization Server에서 Access Code를 파라미터로 넘기며 URL을 호출한다.

4. OauthMemberServiceImpl.java

public Member oauthLogin(String code, String type) throws JsonProcessingException {
        TYPE = type;

        if (TYPE.equals("kakao")) {
            CLIENT_ID = KAKAO_CLIENT_ID;
            REDIRECT_URI = KAKAO_REDIRECT_URI;
        } else {
            CLIENT_ID = NAVER_CLIENT_ID;
            REDIRECT_URI = NAVER_REDIRECT_URI;
        }

        // 1. request access token from access code
        String accessToken = getAccessToken(code);

        // 2. call kakao/naver api from access token -> get member info
        SocialMemberDto oauthMemberInfo = getOauthMemberInfo(accessToken);

        // 3. register to kakao/naver id
        Member member = registerOauthMemberIfNeed(oauthMemberInfo);

        return member;

    }

해당 서비스 로직은 다음과 같다.
1. Authorization Server에 Access Code를 이용해 Access Token 발급받기
2. Resource Server에 Access Toekn을 이용해 사용자 정보 받기
3. 처음 로그인한 사용자의 경우 DB에 저장
4. 사용자 반환

4-1. getAccessToken

  1. 요청 바디에 Access Code, Client Id, Redirect uri 등의 필요한 정보를 담아 Authorization Server에 Http 요청 날림.
  2. Access Token JSON 형태로 발급받음

4-2. getOauthMemberInfo

  1. 요청 바디에 Access Token 등의 필요한 정보를 담아 Resource Server에 Http 요청 날림.
  2. 사용자 정보 JSON 형태로 받음.

4-3. registerOauthMemberIfNeed

MemberRepository에 사용자가 없다면, 사용자 정보 DB에 저장한 후 사용자 정보를 반환한다.

** 해당 글은 기록용으로 작성된 글입니다. 개발 레퍼런스 용으로 부족할 수 있으니 궁금한 점이 있다면, 댓글로 작성해주세요!

참고

https://bcp0109.tistory.com/379
https://canada-coder.tistory.com/entry/%EC%9E%A1-%EC%9D%B8%ED%84%B0%EB%B7%B0-2-OAuth-10-%EA%B3%BC-OAuth-20%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90

0개의 댓글