소셜 로그인 유지를 위한 갱신토큰 (refresh_token) 사용 방법 질문입니다

매출이 오르면 내리는 수수료! 지금 수수료센터에서 전자결제(PG)수수료 비교견적 신청해 보세요!
소셜 로그인 유지를 위한 갱신토큰 (refresh_token) 사용 방법 질문입니다

QA

소셜 로그인 유지를 위한 갱신토큰 (refresh_token) 사용 방법 질문입니다

답변 2

본문

sns가입으로 네이버와 카카오를 사용중인데요. 너무 빨리 로그인이 풀려버려서 방법을 찾아보고 있습니다. 네이버의 경우는 refresh token이 있던데, 어떻게 그누보드에 적용해야할지 감이 안오네요.

 

네이버에서 개발가이드를 제공중인데 요청예제문을 봐도 어떻게 적용해야 할지 감감합니다.

https://developers.naver.com/docs/login/devguide/devguide.md

 

1995115441_1736588501.5658.jpg

 

어떻게 적용해야 할지 귀한 답변 부탁드립니다.

이 질문에 댓글 쓰기 :

답변 2

클라이언트 ID와 시크릿은 네이버 API에 접근하기 위한 인증 정보를 제공하지만, 리프레시 토큰은 액세스 토큰이 만료되었을 때 새로운 액세스 토큰을 발급받기 위해 사용하게 되므로,

따라서, 리프레시 토큰을 사용하여 새로운 액세스 토큰을 발급받는 로직을 추가하는 것이 필요하며,

OAuth2 라이브러리를 사용하여 리프레시 토큰을 관리하고 새로운 액세스 토큰을 발급받는 코드를 작성을 하셔야 할것입니다.

이유는

네이버 Client ID와 Client Secret은 이미 그누보드 환경설정에서 등록되어 있으므로 더 이상 설정할 필요 없게되므로, 리프레시 토큰 관리와는 별개의 문제이지만 이미 로직을 가지고있기때문에 로그인 시 Refresh Token 저장해야하므로 회원테이블에 필드추가하시고 네이버 콜벡처리에서 저장로직을 추가 해 줘야 할 것으로 보이며, 또한 Access Token이 만료되었을 때 Refresh Token을 사용해야하므로,  새로운 Access Token을 요청해야하므로, 갱신요청 로직이 구현이 추가로 되어야 합니다.

그렇면......음

 

※ 개요 ※

*네이버 OAuth2 로그인에서 갱신 토큰(refresh token)을 활용하여

  만료된 액세스 토큰(access token)을 재발급받는 로직 구현.

*필요 작업

  - 회원 테이블에 refresh_token 필드 추가.

  - 네이버 콜백 처리 시 refresh_token 저장 로직 추가.

  - 액세스 토큰 만료 시 새로운 액세스 토큰 요청 로직 구현.

*네이버 개발자 가이드

  ("https://developers.naver.com/docs/login/devguide/devguide.md")에 따라 API를 사용.

 

※ 구체적 구현 방법 ※

1. DB 변경

  회원 테이블에 refresh_token 필드를 추가.

2. 콜백 처리 로직

  네이버 로그인 완료 후 콜백에서 받은 refresh_token을 DB에 저장.

3. 갱신 로직

  액세스 토큰이 만료될 경우:

    - refresh_token으로 새로운 액세스 토큰 요청.

    - 새로 발급받은 토큰 정보로 갱신.

 

※ 예시 코드 ※   - 최신 그누보드 구조 참고 함.

DB 스키마 수정

member 테이블에 refresh_token 필드를 추가

ALTER TABLE member ADD COLUMN refresh_token VARCHAR(255) NOT NULL AFTER user_id;
콜백 처리 (naver_callback.php)

<?php
require_once('../lib/common.lib.php'); // lib 경로 맞춤
session_start();
// 환경 변수에서 네이버 클라이언트 ID와 시크릿 가져오기
$client_id = getenv('NAVER_CLIENT_ID') ?: die("NAVER_CLIENT_ID 환경 변수가 설정되지 않았습니다.");
$client_secret = getenv('NAVER_CLIENT_SECRET') ?: die("NAVER_CLIENT_SECRET 환경 변수가 설정되지 않았습니다.");
// 네이버 로그인 콜백에서 전달받은 코드 및 상태 값
$code = $_GET['code'];
$state = $_GET['state'];
// 네이버 API 호출 URL 구성
$url = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id={$client_id}&client_secret={$client_secret}&code={$code}&state={$state}";
// 안전한 API 호출
$response = call_naver_api($url);
if ($response && isset($response['access_token']) && isset($response['refresh_token'])) {
    $access_token = $response['access_token'];
    $refresh_token = $response['refresh_token'];
    // 사용자 세션에서 사용자 ID 가져오기
    if (isset($_SESSION['user_id'])) {
        $user_id = sql_real_escape_string($_SESSION['user_id']);
        // DB에 refresh_token 저장
        try {
            $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password', [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            ]);
            $stmt = $pdo->prepare("UPDATE member SET refresh_token = :refresh_token WHERE user_id = :user_id");
            $stmt->execute([
                ':refresh_token' => $refresh_token,
                ':user_id' => $user_id
            ]);
        } catch (PDOException $e) {
            error_log("DB 에러: " . $e->getMessage());
            echo "토큰 저장 중 문제가 발생했습니다. 관리자에게 문의하세요.";
        }
    } else {
        echo "사용자 세션 정보가 없습니다. 다시 로그인해주세요.";
    }
} else {
    error_log("네이버 API 응답 에러: " . json_encode($response));
    echo "네이버 로그인 처리 중 문제가 발생했습니다.";
}
/**
 * 네이버 API를 호출하는 함수
 *  string $url
 *  array|null
 */
function call_naver_api($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        error_log('cURL 에러: ' . curl_error($ch));
        return null;
    }
    curl_close($ch);
    return json_decode($response, true);
}
?>
갱신 로직 (token_refresh.php)

<?php
require_once('../lib/common.lib.php'); // lib 경로 맞춤
/**
 * 네이버 갱신 토큰 API를 호출하여 새로운 액세스 토큰 발급
 *  string $user_id
 *  string|null 새로운 액세스 토큰
 */
function refresh_access_token($user_id) {
    $client_id = getenv('NAVER_CLIENT_ID') ?: die("NAVER_CLIENT_ID 환경 변수가 설정되지 않았습니다.");
    $client_secret = getenv('NAVER_CLIENT_SECRET') ?: die("NAVER_CLIENT_SECRET 환경 변수가 설정되지 않았습니다.");
    // DB에서 refresh_token 가져오기
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password', [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ]);
        $stmt = $pdo->prepare("SELECT refresh_token FROM member WHERE user_id = :user_id");
        $stmt->execute([':user_id' => $user_id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$row || empty($row['refresh_token'])) {
            echo "갱신 토큰이 없습니다. 다시 로그인해주세요.";
            return null;
        }
        $refresh_token = $row['refresh_token'];
    } catch (PDOException $e) {
        error_log("DB 에러: " . $e->getMessage());
        echo "토큰 갱신 중 문제가 발생했습니다. 관리자에게 문의하세요.";
        return null;
    }
    // 네이버 API 호출 URL 구성
    $url = "https://nid.naver.com/oauth2.0/token?grant_type=refresh_token&client_id={$client_id}&client_secret={$client_secret}&refresh_token={$refresh_token}";
    // 안전한 API 호출
    $response = call_naver_api($url);
    if ($response && isset($response['access_token'])) {
        return $response['access_token'];
    } else {
        error_log("토큰 갱신 실패: " . json_encode($response));
        echo "토큰 갱신 중 문제가 발생했습니다. 다시 시도해주세요.";
        return null;
    }
}
/**
 * 네이버 API를 호출하는 함수
 *  string $url
 *  array|null
 */
function call_naver_api($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        error_log('cURL 에러: ' . curl_error($ch));
        return null;
    }
    curl_close($ch);
    return json_decode($response, true);
}
// 사용 예시
session_start();
$user_id = $_SESSION['user_id'] ?? null;
if ($user_id) {
    $new_token = refresh_access_token($user_id);
    if ($new_token) {
        echo "새로운 토큰 발급 완료: " . $new_token;
    } else {
        echo "토큰 갱신 실패.";
    }
} else {
    echo "로그인 상태가 아닙니다.";
}
?>

 

※ 프로젝트 파일 구조 예시 ※

├── bbs

│ ├── login.php

│ ├── logout.php

│ ├── naver_callback.php # 새로 추가

│ └── ...

├── lib

│ ├── common.lib.php

│ ├── token_refresh.php # 새로 추가

│ └── ...

- login.php: 사용자가 로그인할 때 호출되는 초기화 파일.

- logout.php: 사용자가 로그아웃할 때 호출되는 파일.

- naver_callback.php: 네이버 인증 후 콜백 처리 및 DB에 refresh_token 저장.

- token_refresh.php: 기존 저장된 refresh_token을 이용해

  만료된 access_token을 갱신하는 로직을 처리.

 

※ 자체 검증 내용 ※

*API 요청 및 응답 구조는 네이버 개발자 가이드를 반영함.

*DB에 refresh_token 필드를 추가하여 사용자별 갱신 토큰 저장 가능.

*만료된 액세스 토큰을 갱신 토큰으로 교체 가능하게 됨
 

※ 검증 후 필요 조치 ※

1. 환경 변수 설정:

client_id와 client_secret은 안전하게 관리해야 하므로 환경 변수 또는 설정 파일로 옮김.

- Linux 환경 변수 설정 예


export NAVER_CLIENT_ID=your_client_id
export NAVER_CLIENT_SECRET=your_client_secret

2. DB 구조 업데이트:

refresh_token을 저장하기 위해 member 테이블에 해당 필드를 추가.

3. 테스트:

- 네이버 OAuth2 API 호출이 정상 동작하는지 테스트.

- 특히, naver_callback.php에서 refresh_token이 DB에 올바르게 저장되는지 확인.

- token_refresh.php가 refresh_token을 기반으로 새 access_token을 발급받는지 테스트.

4. 최종확인:

- 테스트 환경과 실제 운영 환경을 분리하여 충분한 테스트 후 적용.

- 네이버 로그인 관련 콜백 URL이 정확히 설정되었는지 확인.

- 네이버 API 정책과 토큰 관리 가이드를 정기적으로 확인하여 업데이트에 대비하며 사용.

답변을 작성하시기 전에 로그인 해주세요.
QA 내용 검색
질문등록
전체 0
© SIRSOFT
현재 페이지 제일 처음으로