OAuth 인증인가 흐름

김대은·2026년 9월 7일
post-thumbnail

저희가 사이트들 회원가입을 하다보면
이름을 입력하고 전화번호로 인증하고 그런 경우도 있지만
그냥 '구글로 로그인'처럼 다른 서비스의 계정을 이용해 로그인하는 경우도 있습니다. 오늘은 이 과정에서 사용되는 OAuth 인증·인가와 OIDC에 대해 알아보겠습니다.

OAuth란?

OAuth(오픈 인증) : 오픈 인증은 사용자 계정의 로그인이나 비밀번호 없이도
애플리케이션이나 사진, 캘린더 또는 소셜 미디어 게시물과 같은 최종 사용자의 보호된 리소스에 액세스 할 수 있는 권한을 부여하는 개방형 표준 프레임워크입니다.

OAuth 프로토콜을 사용하면 사용자는 사용자 자격 증명을 공유하지 않고 이러한 애플리케이션에 계정 데이터에 대한 액세스 권한을 쉽게 부여할 수 있습니다.

그냥 이름 입력하고 비밀번호 입력해서 로그인하면 되는거 아닌가?
왜 그렇게 해야하지?

OAuth가 중요한 이유

OAuth가 중요한 이유는 크게 두 개로 나눌 수 있습니다

  • 편함
  • 보안

1. 편함

  • 회원가입 폼 다 채울 필요 없이 버튼 하나로 끝납니다.
  • 비밀번호를 또 하나 만들고 기억해야 하는 부담이 없습니다.
  • 여러 사이트마다 새 계정을 만들 필요가 없습니다.

2. 보안
이 부분은 OAuth가 "반드시 보안이 더 좋다"기 보다는, 정확히 왜 더 안전한지를 짚어보겠습니다.

  • 비밀번호를 여러 곳에 뿌리지 않음 : 각 사이트마다 회원가입을 다 일일이 하면
    보안이 약한 한 사이트만 해킹당해도 다 비밀번호 유출(비밀번호를 재사용하는 사람들은 특히 더 위험)

    OAuth를 쓰면?
    구글, 카카오톡 등 한 곳에만 두니까 위험이 줄어듭니다.

  • 전문업체가 보안을 담당 : 구글, 카카오톡처럼 2단계 인증, 로그인 이상 감지 등 보안에 많은 투자를 한 사이트를 쓰면
    내가 직접 만든 작은 사이트보다 더 안전할 것입니다.

이게 모든 사이트들보다 구글이나 카카오가 보안이 무조건 뛰어나다는 뜻이 아닌
상대적으로 내가 만든 작은 사이트보다 보안이 뛰어나다는 뜻입니다.

  • 작은 사이트는 비번을 모름 : 작은 사이트들이 해킹을 당해도 OAuth를 사용해 구글 등으로 로그인하니 구글이 털리지 않는 이상 비밀번호는 털리지 않습니다.(로그인하는 사이트는 토큰만 받지 비밀번호 같은 정보는 안 받습니다.)

  • 권한 세분화 / 취소 가능 : "이 앱에게 이메일만 보여주고, 게시글 작성 권한은 주지 마" 같은 식으로 접근 범위(scope)를 제한할 수 있고, 언제든 권한을 취소(revoke)할 수 있습니다.

OAuth의 작동 방식

사용자의 이름과 비밀번호에 의존하는 다른 프레임워크와 달리 OAuth는 액세스 토큰을 기반으로 하는 인증 프로토콜입니다.
액세스 토큰은 애플리케이션이 액세스할 수 있는 특정 리소스를 결정하는 정보입니다.
OAuth 프로토콜은 권한 부여 요청 프로세스의 각 구성 요소가 액세스 토큰을 승인, 정의 및 관리하는 방법을 정의합니다.

  • OAuth는 Access Token의 형식을 특정하지 않으며, JWT 형태로 사용할 수도 있고 opaque token 형태로 사용할 수도 있습니다.

OAuth 프레임워크 기본 구성 요소

  • 리소스 소유자 : 계정을 소유한 사용자, 해당 계정이 특정 보호된 리소스에 액세스할 수 있도록 동의합니다.

  • 리소스 서버 : 사용자를 대신해 보호된 리소스를 저장하는 서버, OAuth 토큰을 수락하고 유효성 검사를 하고 사용자에게 데이터를 제공합니다.

  • 고객(클라이언트) : 클라이언트는 액세스를 요청하는 애플리케이션, 웹사이트, API 또는 디바이스, 권한 부여 서버에 요청을 합니다. 클라이언트는 리소스에 액세스하는 데 사용할 수 있는 액세스 토큰을 받습니다.

  • 권한 부여 서버 : OAuth 프로토콜을 구동하는 기본 서버입니다. 두 개의 엔드포인트를 운영하여 리소스 서버에 대한 액세스 권한을 부여합니다.

    권한 부여 엔드포인트는 리소스 소유자에게 보호된 특정 리소스에 대한 동의를 제공하라는 메시지를 표시합니다. 그런 다음 토큰 엔드포인트는 OAuth 클라이언트로부터 토큰 요청을 수신하고 리소스에 대한 액세스 권한을 부여하는 새 액세스 토큰을 생성합니다.

  • 범위 : 리소스 서버의 보호된 리소스에 대한 액세스 매개변수

    예를 들어 리소스 소유자에게 이메일, 파일 또는 사진과 같은 데이터 액세스에 대한 동의를 요청할 수 있습니다. 범위는 클라이언트의 접근을 해당 항목으로만 제한합니다.

OAuth 흐름 예시

  1. Jim이 소셜 미디어(클라이언트)에게 이메일 연락처 접근을 허용하려 함
  2. 인증 서버가 Jim에게 동의 요청
  3. Jim이 동의 → 서버가 클라이언트에게 액세스 토큰 발급
  4. 클라이언트가 리소스 서버에 토큰 제시
  5. 서버가 토큰을 확인 → 이메일 연락처만 제공 (토큰에 범위가 포함돼 있어서 다른 데이터는 접근 불가)

OAuth 권한 부여 유형

애플리케이션에 액세스 토큰을 제공하는 절차를 권한 부여(권한 부여 흐름)라고 합니다.

권한 부여 코드 (Authorization Code)

  • 웹 애플리케이션, 모바일 앱에서 가장 일반적으로 쓰는 방식
  • 권한 부여 서버가 클라이언트에 일회성 권한 부여 코드를 먼저 발급
  • 클라이언트는 이 코드를 토큰 엔드포인트에서 액세스 토큰으로 교환

PKCE (코드 교환을 위한 증명 키)

  • 권한 부여 코드 방식에 보안을 추가한 흐름
  • 로그인 요청 전에 클라이언트가 code_verifier를 생성하고 이를 기반으로 code_challenge를 생성
  • 권한 부여 서버는 code_challenge를 저장한 뒤 인가 코드를 발급
  • Access Token을 요청할 때 클라이언트가 code_verifier를 함께 전달
  • 서버가 두 값을 검증하여 인가 코드를 탈취한 공격자가 Access Token으로 교환하는 것을 방지
  • SPA, 모바일 앱 등에서 Authorization Code와 함께 많이 사용됨

SSO와 OAuth의 차이

구분SSOOAuth
역할인증 (사용자가 누구인지 확인)인가 (무엇에 접근 가능한지 부여)
방식ID 공급자(IdP) + SAML 등 사용, 사용자 이름/비밀번호로 신원 확인사용자를 인증하지 않고 리소스 접근 권한만 부여
관계SSO가 OAuth를 활용해 인증된 사용자를 여러 앱/서비스에 쉽게 연결하기도 함—

OpenID Connect (OIDC)

  • OAuth 2.0 기반으로 만들어진 인증 프로토콜
  • OAuth 자체는 인증 기능이 없기 때문에, "구글로 로그인"처럼 로그인 용도로 쓰일 때는 보통 OIDC가 신원을 확인하고, 그 위에서 OAuth가 리소스 접근 권한을 부여하는 구조

Ready GSM - OAuth 인증인가

readygsm-server는 구글과 카카오 로그인을 지원합니다.

흐름

전체적인 흐름은 다음과 같습니다.

사용자
↓
구글 / 카카오 로그인
↓
인가 코드(code) 발급
↓
Ready GSM 백엔드
↓
Access Token 요청
↓
사용자 정보 조회
↓
회원 조회 또는 생성
↓
Spring Security 인증
↓
Session 생성

  1. 프론트엔드가 사용자를 구글/카카오 로그인 화면으로 보내고 동의를 받습니다

  2. 구글/카카오가 프론트엔드에 인가 코드(code)를 반환합니다.

  3. 프론트엔드는 이 코드를 백엔드의 POST /api/v1/auth/{provider}로 전달합니다.

  4. 백엔드가 이 코드를 가지고 구글/카카오의 토큰 엔드포인트에 직접 요청해 액세스 토큰으로 교환합니다.

  5. 액세스 토큰으로 사용자 정보(이메일)를 조회하고, DB에서 회원을 찾거나 새로 가입시킵니다.

  6. 로그인 처리 후 HTTP Session에 인증 정보를 저장하여 로그인 상태를 유지합니다.

@PostMapping("/{provider}")
public ResponseEntity<Void> oauthLogin(
        @PathVariable String provider,
        @RequestBody OAuthCodeRequest request,
        HttpServletRequest httpRequest
) {
    oAuthAuthenticationService.execute(
        provider,
        request.code(),
        request.redirectUri(),
        httpRequest
    );

    return ResponseEntity.ok().build();
}

백엔드는 provider에 따라 Google 또는 Kakao Provider를 선택하고, 인가 코드를 이용해 Access Token과 사용자 정보를 가져옵니다.

OAuthProvider provider =
    oAuthProviderFactory.getProvider(providerName);

UserAuthInfo userAuthInfo =
    provider.getUserAuthInfo(code, redirectUri);

getUserAuthInfo() 내부에서 인가 코드로 Access Token을 발급받고, 발급받은 Access Token으로 사용자 정보(이메일)를 가져옵니다.

여기서 getUserAuthInfo()에는 인가 코드와 redirectUri도 함께 전달합니다.

Ready GSM에서는 로컬, 개발, 상용 환경 등 여러 환경에서 로그인을 진행할 수 있기 때문에 환경별 redirect_uri를 미리 허용 목록으로 관리합니다. 프론트엔드가 전달한 redirect_uri가 허용 목록에 포함되어 있는지 검증한 후, 해당 URI를 사용해 토큰 교환을 진행합니다.

GoogleTokenResponse tokenResponse =
    googleTokenClient.getToken(
        code,
        googleOAuthProperties.clientId(),
        googleOAuthProperties.clientSecret(),
        redirectUri
    );

GoogleUserInfoResponse userInfoResponse =
    googleUserInfoClient.getUserInfo(
        tokenResponse.accessToken()
    );

가져온 이메일과 Provider 정보를 이용해 Ready GSM의 회원을 조회합니다. 회원이 없다면 새로 생성합니다.

OAuth 사용자 정보
      ↓
회원 조회
      ↓
있음 → 로그인
없음 → 회원 생성

회원 정보를 바탕으로 Spring Security의 인증 객체를 만들고, SecurityContext를 HTTP Session에 저장하여 로그인 상태를 유지합니다.

인가 코드
   ↓
Access Token
   ↓
사용자 정보 조회
   ↓
회원 조회 / 생성
   ↓
Spring Security 인증
   ↓
HTTP Session 저장
   ↓
로그인 완료

즉 Ready GSM에서는 Google과 Kakao에서 Access Token을 발급받고, 이를 이용해 사용자 정보를 조회합니다. 이후 전달받은 사용자 정보로 Ready GSM의 자체 회원을 조회하거나 생성하고, Spring Security의 SecurityContext를 HTTP Session에 저장하여 로그인 상태를 관리합니다.

0개의 댓글