Sandcorp샌드코프 · 웹·AI 제품 개발

새 프로젝트 받는 중 · 갱신 2026.11sandcorp.co.krGitHub

← 팁

인증

OAuth 콜백은 다시 온다 — 성공한 로그인은 멱등하게

뒤로 가기나 인앱 브라우저 복원으로 같은 state의 콜백이 다시 온다. 이미 로그인한 사용자라면 오류 대신 돌아갈 주소로 보낸다.

소셜 로그인은 성공했는데, 사용자가 뒤로 가기를 누르거나 인앱 브라우저가 탭을 복원하면 「잘못된 요청(400)」 화면이 뜬다. 사용자는 로그인이 실패한 줄 안다.

브라우저가 같은 콜백 URL을 다시 열면서 이미 쓴 state가 한 번 더 온다. state를 한 번만 쓰게 하는 것은 CSRF 방어로 맞다. 문제는 이미 로그인에 성공한 사용자의 재전송까지 똑같이 오류로 보여 준다는 것이다.

쓰인 state가 다시 왔을 때 사용자 상태로 가른다. 이미 로그인된 사용자라면 마지막 로그인의 돌아갈 주소로 리다이렉트한다. 로그인되지 않은 사용자라면 그대로 거절한다. 방어는 그대로 두고 성공한 로그인만 멱등하게 만드는 것이다.

from django.http import HttpResponseBadRequest
from django.shortcuts import redirect

def oauth_callback(request):
    state = request.GET.get("state", "")
    if not consume_state(request, state):  # 처음 쓰는 state일 때만 True
        if request.user.is_authenticated:
            return redirect(request.session.get("login_next", "/"))
        return HttpResponseBadRequest("만료된 로그인 요청입니다. 다시 시도해 주세요.")

    exchange_code_and_login(request, request.GET["code"])
    request.session["login_next"] = pop_next_url(request, state)
    return redirect(request.session["login_next"])

거절할 때도 사용자가 할 일을 알려 준다. 오류 코드만 보여 주지 말고 「다시 로그인」으로 이어지는 버튼을 둔다.

문의 →