Skip to content

social-login

Social Login

Oauth 2.0

  • https://datatracker.ietf.org/doc/html/rfc6749
  • OAuth 2.0은 주로 권한 부여를 위해 설계된 프로토콜로, 보호된 리소스에 접근하는 데 사용됩니다.
    • 액세스 토큰만을 사용하여 보호된 리소스에 접근합니다.
    • 제3자 애플리케이션이 사용자 대신 리소스 서버에 접근할 수 있도록 허용합니다.
    • 사용자 인증 기능이 직접적으로 포함되지 않으므로, 사용자 정보를 가져오기 위해 추가적인 API 호출이 필요합니다.

1. 사용자 로그인 (Authentication)

  • 사용자 소셜 로그인 클릭: 사용자가 애플리케이션에서 소셜 로그인 버튼을 클릭합니다.
  • 소셜 로그인 제공자로 리다이렉션: 사용자는 소셜 로그인 제공자(예: Google, Facebook)의 로그인 페이지로 리다이렉션됩니다.
  • 사용자 인증: 사용자가 소셜 로그인 제공자에게 로그인 자격 증명을 제출합니다.
  • Authorization Code 수신: 소셜 로그인 제공자가 애플리케이션 서버로 Authorization Code를 반환합니다.
  • Access Token 교환: 애플리케이션 서버가 Authorization Code를 Access Token으로 교환합니다.
  • Access Token 검증: 애플리케이션 서버가 Access Token을 검증하고 사용자 정보를 가져옵니다.
  • 세션 생성: 애플리케이션 서버가 검증된 사용자 정보를 기반으로 사용자 세션을 생성합니다.
sequenceDiagram
    participant User
    participant App
    participant SocialProvider as Social Login Provider

    User->>App: Click "Login with Social"
    App->>SocialProvider: Redirect to Social Login Provider
    SocialProvider->>User: Display Login Page
    User->>SocialProvider: Submit Login Credentials
    SocialProvider->>SocialProvider: Authenticate User
    SocialProvider->>App: Return Authorization Code
    App->>SocialProvider: Exchange Code for Token
    SocialProvider->>App: Return Access Token
    App->>App: Verify Token and Create Session
    App->>User: Redirect to Application
  • Authorization Code: 사용자가 소셜 로그인 제공자(예: Google, Facebook)에게 성공적으로 로그인하면, 제공자는 애플리케이션 서버에 Authorization Code를 반환합니다. 이 코드는 일회용이며 짧은 시간 동안만 유효합니다.

  • Authorization Code 교환: 애플리케이션 서버는 이 Authorization Code를 사용하여 소셜 로그인 제공자에게 Access Token을 요청합니다. 이 요청은 애플리케이션의 클라이언트 ID와 시크릿을 포함하여 인증되며, 이는 클라이언트가 합법적인 애플리케이션인지 확인하는 데 사용됩니다.

  • Access Token 발급: 소셜 로그인 제공자는 요청을 검증한 후 Access Token을 반환합니다. 이 토큰은 애플리케이션이 소셜 로그인 제공자의 API에 접근하는 데 사용됩니다.

2. 서비스 이용 (Authorization)

sequenceDiagram
    participant User
    participant App

    User->>App: Request Resource/Feature
    App->>App: Check Session and Permissions
    alt User has Permission
        App->>User: Provide Resource/Feature
    else User lacks Permission
        App->>User: Deny Access
    end
  • 세션 유지: 사용자가 애플리케이션을 사용하는 동안, 세션 쿠키 또는 토큰을 통해 지속적으로 인증된 상태를 유지합니다.
  • 권한 확인: 사용자가 특정 기능이나 리소스에 접근하려고 할 때마다, 애플리케이션 서버는 사용자의 권한을 확인합니다. 이는 사용자 프로필의 역할(Role)이나 권한(Permissions)을 통해 결정됩니다.
  • 서비스 제공: 사용자가 권한을 가지고 있는 경우, 요청한 기능이나 리소스에 접근할 수 있습니다. 그렇지 않은 경우, 접근이 거부됩니다.

3. 서비스 종료 (Logout)

sequenceDiagram
    participant User
    participant App

    User->>App: Click "Logout"
    App->>App: Destroy Session
    App->>User: Clear Session Cookie/Token
    opt Notify Social Login Provider
        App->>SocialProvider: Send Logout Request
    end
    User->>User: Redirect to Login Page
  • 사용자 로그아웃 클릭: 사용자가 애플리케이션에서 로그아웃 버튼을 클릭합니다.
  • 세션 종료: 애플리케이션 서버가 사용자의 세션을 종료하고, 클라이언트 측의 세션 쿠키 또는 토큰을 삭제합니다.
  • 소셜 로그인 제공자 로그아웃 (옵션): 필요에 따라, 애플리케이션은 소셜 로그인 제공자에게도 로그아웃 요청을 보낼 수 있습니다.

OIDC (OpenID Connect)

  • https://openid.net/specs/openid-connect-core-1_0.html
  • OpenID Connect (OIDC)는 OAuth 2.0을 기반으로 한 인증 프로토콜로, 사용자의 신원을 확인하는 데 사용됩니다.
    • 액세스 토큰과 함께 ID 토큰을 사용하여 사용자의 신원을 확인합니다.
    • OIDC를 통해 애플리케이션은 사용자 인증과 권한 부여를 모두 처리할 수 있습니다.
  • OAuth 2.0만을 사용하는 경우, 애플리케이션은 액세스 토큰을 통해 보호된 리소스에 접근하지만, 사용자 인증과 관련된 정보를 얻기 위해 추가적인 단계를 거쳐야 합니다. OIDC는 이러한 과정을 단순화하여 사용자 인증을 보다 쉽게 구현할 수 있도록 합니다.
sequenceDiagram
    participant User
    participant App
    participant OIDC as OIDC Provider

    User->>App: Click "Login with OIDC"
    App->>OIDC: Redirect to OIDC Provider
    OIDC->>User: Display Login Page
    User->>OIDC: Submit Login Credentials
    OIDC->>OIDC: Authenticate User
    OIDC->>App: Return Authorization Code
    App->>OIDC: Exchange Code for Tokens
    OIDC->>App: Return Access Token and ID Token
    App->>App: Verify ID Token and Fetch User Info
    App->>User: Create Session and Redirect to App

Flask Example - OIDC

@app.route('/login')
def login():
    oidc_auth_url = 'https://accounts.google.com/o/oauth2/auth'
    client_id = 'YOUR_CLIENT_ID'
    redirect_uri = url_for('login_callback', _external=True)
    scope = 'openid email profile'
    return redirect(f'{oidc_auth_url}?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}')
  • 사용자가 로그인 버튼을 클릭하면, Flask 애플리케이션은 Google OAuth 2.0 인증 URL로 리다이렉션됩니다.
  • 사용자가 Google 로그인 페이지에서 로그인하면, Google은 Authorization Code를 생성하고 애플리케이션 서버로 리다이렉션합니다.
@app.route('/login/callback')
def login_callback():
    code = request.args.get('code')
    token_url = 'https://oauth2.googleapis.com/token'
    client_id = 'YOUR_CLIENT_ID'
    client_secret = 'YOUR_CLIENT_SECRET'
    redirect_uri = url_for('login_callback', _external=True)
    data = {
        'code': code,
        'client_id': client_id,
        'client_secret': client_secret,
        'redirect_uri': redirect_uri,
        'grant_type': 'authorization_code'
    }
    response = requests.post(token_url, data=data)
    token_response = response.json()
    id_token = token_response.get('id_token')
    access_token = token_response.get('access_token')

    # ID Token 검증 및 디코딩
    user_info = jwt.decode(id_token, options={"verify_signature": False})

    # 세션에 사용자 정보 저장
    session['user'] = {
        'id': user_info['sub'],
        'name': user_info['name'],
        'email': user_info['email'],
        'picture': user_info['picture']
    }

    return redirect(url_for('profile'))
  • 애플리케이션 서버는 Authorization Code를 사용하여 Google OAuth 2.0 토큰 엔드포인트로 POST 요청을 보냅니다.
  • Google은 애플리케이션 서버에 Access Token과 ID Token을 반환합니다.
  • ID Token은 JWT 형식으로 인코딩되어 있으며, 애플리케이션 서버에서 검증 및 디코딩하여 사용자 정보를 추출합니다.
  • 사용자 정보를 세션에 저장하고, 프로필 페이지로 리다이렉션합니다.
@app.route('/profile')
def profile():
    user = session.get('user')
    if not user:
        return redirect(url_for('login'))
    return f"""
    <h1>Welcome {user['name']}</h1>
    <img src="{user['picture']}" alt="Profile Picture">
    <p>Email: {user['email']}</p>
    <a href="/logout">Logout</a>
    """

@app.route('/logout')
def logout():
    session.pop('user', None)
    return redirect(url_for('login'))
  • 프로필 페이지에서 사용자 정보를 표시하고, 로그아웃 버튼을 제공합니다.
  • 로그아웃 버튼을 클릭하면, 세션에서 사용자 정보를 삭제하고 로그인 페이지로 리다이렉션합니다.

References