본문 바로가기
.NET/API Integration

[.NET] ASP.NET Framework 4.x - 네이버 로그인 API 구현

by 가든가든 2023. 10. 5.
728x90

안녕하세요,

이번 포스팅은 구글, 카카오 로그인 API 연동에 이어서 네이버 로그인도 포스팅 해보려 합니다.

 

사실 구글, 카카오, 네이버 로그인 API 프로세스는 거의 비슷해서 GetAccessToken / GetUserInfo 등 토큰 가져오기 및 유저 정보 가져오기 파이프라인 메서드를 만들어 각 콜백 메서드에서 사용하는 방식으로 개발해도 좋습니다.

 

아래 문서를 참고해서 개발을 했고요.

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

본문 시작하도록 하겠습니다.

 

[시작전에 각 필요한 정보를 필드에 저장]

// Naver - Client ID / Redirect URI 확인 및 설정 - https://developers.naver.com/docs/login/devguide/devguide.md
        private readonly string naver_clientId = "";
        private readonly string naver_redirectUri = "";
        private readonly string naver_clientSecret = "";
        private readonly string naver_resquestUrl = "https://nid.naver.com/oauth2.0/authorize?response_type=code"; // 인가 코드 요청 URL
        private readonly string naver_TokenUrl = "https://nid.naver.com/oauth2.0/token"; // 토큰 코드 요청 URL

[인가 코드 가져오기]

kakao_resquest_url 해당 url로 (클라이언트)사용자 인증 후 인가 코드를 받는다.

  	private string RandomState()
        {   // CSRF 방지를 위한 랜덤 문자열 생성
            // 로그인 요청과 응답 사이에서 일치하는지 확인 필요 - 해당 메서드의 return 값인 state는 Naver에서 필수로 받음
            byte[] randomBytes = new byte[32];
            using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(randomBytes);
            }

            string state = Convert.ToBase64String(randomBytes);
            return state;
        }

        public ActionResult Login() // 요청 페이지
        {
            // Naver 로그인 구현 - RestAPI 직접 구현
            string state = RandomState(); // CSRF를 방지하기 위한 클라이언트 측의 인증값
            var naver_request_url = naver_resquestUrl + 
                "&client_id=" + naver_clientId +
                "&redirect_uri=" + naver_redirectUri +
                "&state=" + state;

            ViewBag.naver_resquest_url = naver_request_url;

            return View();
        }

가져온 인가코드는 Naver에서 설정한 리다이렉트 URI 콜백 경로로 전달이 되며, 인가코드와 함께 Naver에 토큰 가져오기를 요청한다. (GetAccessToken)

public async Task NaverLoginCallback(string code)
        {
            var tokenUrl = naver_TokenUrl;
            // Naver OAuth2 토큰 요청 데이터를 직접 구성
            var requestData = $"grant_type=authorization_code" +
                              $"&client_id={naver_clientId}" +
                              $"&redirect_uri={naver_redirectUri}" +
                              $"&code={code}" +
                              $"&client_secret={naver_clientSecret}";

            // POST 요청 보내기
            string accessToken = await GetAccessToken(tokenUrl, requestData);

            // Naver 사용자 정보를 가져오는 URL
            string userInfoUrl = "<https://openapi.naver.com/v1/nid/me>";

            // 참고 <https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info-request-header>
            string userInfo = await GetUserInfo(userInfoUrl, accessToken, secureResource: false, propertyKeys: null); // 토큰으로 유저 정보 가져오기

            TempData["UserProfile"] = userInfo;
        
            return RedirectToAction("LoginComInfo");
        }

[토큰 가져오기]

  • 닷넷에서 제공하는 HttpClient 클래스를 사용해서 Rest API 통신
  • 핵심 단계이며, Rest API Post로 요청을 하며, 인가 코드가 있어야 access_token을 받아 올 수 있다.
  • access_token을 받는데 성공한다면, 해당 토큰 값으로 Naver에서 제공하는 여러 기능의 API를 활용할 수 있다. (사이트 참고 - 현재는 GetUserInfo로 유저 정보 가져오기만 테스트로 구현 하였음)

 

[사용자 정보 가져오기]

[HttpPost]
        private async Task<string> GetUserInfo(string userInfoUrl, string accessToken, bool secureResource, string[] propertyKeys)
        {
            // 요청 헤더 설정 (인증 토큰을 포함)
            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");

            // 쿼리 파라미터 설정 (secureResource 및 propertyKeys)
            var queryParameters = new List<string>();
            if (secureResource)
            {
                queryParameters.Add("secure_resource=true");
            }
            if (propertyKeys != null && propertyKeys.Length > 0)
            {
                queryParameters.AddRange(propertyKeys.Select(key => $"property_keys[]={key}"));
            }

            // 쿼리 파라미터가 있을 경우 URL에 추가
            if (queryParameters.Any())
            {
                userInfoUrl += "?" + string.Join("&", queryParameters);
            }

            // 사용자 정보 요청 보내기
            HttpResponseMessage response = await httpClient.GetAsync(userInfoUrl);

            if (response.IsSuccessStatusCode)
            {
                string jsonResponse = await response.Content.ReadAsStringAsync();
                return jsonResponse;
            }
            else
            {
                string errorResponse = await response.Content.ReadAsStringAsync();
                return errorResponse;
            }
        }

[결과]

{
	"resultcode":"00",
	"message":"success",
	"response":{
		"id":"",
		"email":"이메일 주소",
		"name":""
	}
}

 

728x90