[리액트네이티브(RN)] OAuth 2.0 과 소셜로그인(네이버아이디로로그인[네아로])

2019. 11. 19. 23:13Programming/React Native

리액트 네이티브로 프로젝트를 진행하기로 했다.

그렇게 회원가입/로그인 구현 시 소셜로그인이야 워낙 api이용을 위한 가이드라인도 꼼꼼하게 되어있어 큰 걱정을 하지 않았으나, 

허허 우리는 expo cli 를 사용하고있었어서, and, ios로 앱을 export 하지 않을 것이기 때문에 사용하고있는 프레임워크들에서 네아로 구현을 했어야만 했다 ㅎㅎ

 

그래! 네이티브앱 내에서 웹을 porting하는 방식으로 소셜로그인을 구현하자!

그렇게 해서 이 대장정이 시작되었다... 

 

소셜로그인

React native expo로 개발을 진행하면서, 소셜로그인을 구현하는데 알아야 할 개념들을 먼저 알자.

OAuth 2.0이란?

  • API(or 서비스) 이용시 인증, 리소스(제공 서비스)에 대한 권한부여방법 중 하나.
    • 비유하자면, 로그인과 OAuth는 분리해서 이해해야한다! 방문증과 사원증의 차이..
  • 서버-클라이언트 사이에 인증 완료 시 권한부여의 결과로 액세스 토큰(Access Token)을 발급 -> 클라이언트: 액세스 토큰을 이용해 API(or 서비스)에 접근/서비스 요청 -> 서버: 액세스 토큰 기반으로 서비스/접근여부를 판단해 데이터 제공
  • 구글, 카카오, 페이스북에서 OAuth 2.0을 통해 서비스에대한 인증/권한부여를 사용하고있음

 

사용자 인증

[클라이언트-서버 최초 인증시]

  • 클라이언트: 이메일, 비밀번호를 리퀘스트 바디에 담아 서버로 인증 요청
  • 서버: 확인하여 인증된 클라이언트 정보를 세션에 저장← 패스포트가 하는 일

[클라이언트-서버 n(!=1)번째 인증시]

  • 클라이언트(최초 인증 내력o): 서버에서 받은 세션아이디를 쿠키에 저장 후 인증이 필요한 API 호출 시 세션 아이디 정보를 함께 담아 요청
  • 서버 : 쿠키의 인증했던 내력을 보고 api 응답을 보내줌

 

OAuth 2.0의 액세스 토큰(access token)

  1. 세션에 인증 정보를 저장 할 필요가 없음
    • 액세스 토큰에 인증정보가 있기 때문!
    • 서버에서는 디코딩하여 확인 가능
  2. 인증 후 획득한 액세스 토큰을 헤더에 넣어 호출
    • 개발 중 서버가 재구동 될 때 로그인 프로토콜을 호출하지 않아도 된다.

 

OAuth 적용 절차

OAuth 2.0 기반의 사용자 인증 기능을 통하여 네이버/카카오가 아닌 다른서비스에서 네이버의 사용자 인증 기능을 이용할 수 있게 하는 서비스

  1. 애플리케이션 등록
    네이버아이디로 로그인 적용을 위해 애플리케이션 등록, 클라이언트 아이디/시크릿 키 발급
  2. 애플리케이션 개발
  3. 서비스에 OAuth 적용

 

OAuth의 개념은 이렇고,
react native - expo 프로젝트에 실질적으로 사용하기 위한 내용/코드들을 짚고 넘어간다.
그러면서 AuthSession, Axios 에 관한 내용을 같이 이해하도록 하자.

 

 


Axios

Axios란?

  • HTTP 클라이언트 라이브러리
  • 비동기 방식으로 HTTP 데이터 요청을 실행
  • 내부적으로 axios는 직접적으로 XMLHttpRequest를 다루지 않고 “AJAX 호출(자바스크립트로 서버에 데이터를 요청)”이 가능하다.
    => 쉽게말해, axios를 통해 HTTP요청(웹서버-클라이언트 간 통신규약으로, 문서 교환을 위해 요청/응답하는 것)으로 데이터를 가져올 수 있다!

 

axios 설치

npm install axios --save;
$ yarn add axios

 

사용 법

  1. import

    import axuis from "axios";
  2. .GET

  • 네이버 oauth2.0을 통해 access_token에 get한 값을 저장한다.

    const {
        data: { access_token }
      } = await axios.get(`https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id=${NV_APP_ID}
      &client_secret=${NV_APP_SECRET}
      &code=${code}&state=${STATE_STRING}`);
    setToken(data.access_token); //setState
  • bearer 토큰을 주고는 것을 인증으로 한다.
    : Bearer 토큰이란, 암호화하지 않은 그냥! 토큰으로 기본적으로 HTTPS 를 사용하기 때문에 토큰을 안전하게 주고받는 것은 HTTPS의 암호화에 의존한다.
    API를 호출 할 때 간단하게 Header 에 넣어 보내는 것으로, api 테스트도 가능해다!

const config = {
  headers: {
    Authorization: `Bearer ${access_token}`
  }
};

받아온 네이버 api에 header를 담아 보내 다시한번 get하여 data를 얻는다.

const { data } = await axios.get(
  "https://openapi.naver.com/v1/nid/me",
  config
);
console.log(data);
setUser(data);

 

 


 

AuthSession

: webbrowser 위에 구축된 웹 브라우저 기반 OAuth flow(웹브라우저 기반 인증) 을 앱에 추가하는 방법!

  • 앱이 다양한 URL에 있을 수 있기때문에, expo에서 특히나 유용하다!

 

웹 브라우저 기반 인증 흐름의 작동 방식

  1. 시작 : user 가 login 버튼 누름
  2. 웹브라우저 열기: 앱이 웹브라우저를 열고, 로그인 페이지를 위한 openURL에는 일반적으로 앱을 식별하기위한 정보 + 성공시 redirection(리디렉션) 할 URL이 포함됨.
    cf. 웹브라우저는 쿠키에 기인증여부 등을 담고 움직이기때문에 최초 로그인 후에는, 다시 로그인 할 필요가 없다!
  3. 인증 공급자가 리디렉션: 성공적인 인증 시 인증 공급자 페이지의 URL이 제공 허용된 리디렉션 URL의 허용 목록에 존재하고, 리디렉션에는 위치 해시, 쿼리 매개변수 또는 둘다의 URL(ex. UserID, token) 등의 데이터가 포함되어있음
  4. 앱이 리디렉션 처리, 리디랙션 URL에서 데이터를 구문분석

 

AuthSession 사용법

  1. 사용자 인증
[https://auth.expo.io/@your-user-name/your-app-slug](https://auth.expo.io/@your-user-name/your-app-slug)
  1. 인증 방식
  • 인증 성공 시 인증 공급자가 해당 Expo Auth URL로 리디렉션
  • Expo Auth 서비스가 다시 응용프로그램으로 리디렉션
  • 이때, 인증서비스가 다시 리디렉션하는 URL이 앱/독립실행형 앱 체계인
[https://auth.expo.io/@your-user-name/your-app-slug](https://auth.expo.io/@your-user-name/your-app-slug)  
또는  
yourscheme://~~~

에 게시된 URL과 일치하지 않으면 ->경고페이지!

  • expo에서 서비스 url
[https://auth.expo.io/@your-username/your-app-slug/start](https://auth.expo.io/@your-username/your-app-slug/start)

을 서비스 url로 하여, authsesi 5. API

  • AuthSession.startAsync(options) : AuthSession
let result=awaitAuthSession.startAsync({  
authUrl:`https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${NV_APP_ID}&redirect_uri=${encodeURIComponent(redirectUrl)}&state=${STATE_STRING}`,  
});
  • AuthSession.getRedirecrUrl() : 인증 공급자가 리디렉션해야하는 url을 가져옴
    encodeURIComponent() : gettRedirectUrl 해 가져온 url을 인코딩
let redirectUrl=AuthSession.getRedirectUrl();
  • AuthSession.startAsync() : 인증 세션을 시작하는 메서드.
    : 인증 공급자로부터 전달된 정보 (ex. userID)를 사용하여 개체로 확인되는 것을 반환!
const result = await AuthSession.startAsync({ authUrl: `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${NV_APP_ID}&redirect_uri=${encodeURIComponent( redirectUrl )}&state=${STATE_STRING}` });

this.setState({ result });

위 코드에서의 url/형식은 인증 서비스에 따라 다르다. 위는 네아로의 인증 서비스 예시다.

 

 


 

OAuth provider 를 사용하기 전 셋팅

리디렉션을 필요로 하는 AuthSession을 사용하려면 expo login을 꼭! 해주어야 한다.

bangsoyun-ui-MacBook-Pro:login-example pongso$ expo login  
┌─────────────────────────────────────────────────────────────┐  
│ │  
│ There is a new version of expo-cli available (3.0.10). │  
│ You are currently using expo-cli 2.18.0 │  
│ Run `npm install -g expo-cli` to get the latest version │  
│ │  
└─────────────────────────────────────────────────────────────┘  
? Username/Email Address: pongsoyun  
? Password: \[hidden\]

Success. You are now logged in as pongsoyun.

bangsoyun-ui-MacBook-Pro:login-example pongso$ exp start  
We've built a brand new CLI for Expo!  
Expo CLI is a drop in replacement for exp.  
Install: npm install -g expo-cli  
Use: expo --help  
Read more: [https://blog.expo.io/expo-cli-2-0-released-a7a9c250e99c](https://blog.expo.io/expo-cli-2-0-released-a7a9c250e99c)  
\[02:09:26\] Using project at /Users/pongso/loginExample/login-example  
\[02:09:30\] Starting Metro Bundler on port 19001.  
\[02:09:32\] Tunnel ready.  
\[02:09:32\] Expo is ready.

 


 

네이버 아이디로 로그인

  1. 네이버 개발자 회원가입 -> 로그인 -> 네아로(네이버 아이디로 로그인)/애플리케이션 등록
  2. api 설정 > 로그인 오픈 API 서비스 환경 > 환경 추가(Mobile web)
  • 리액트 네이티브 앱 개발 시, and/ios 로 빌드하고 앱 개발 시에는 android/ios 폴더 내부로 들어가 따로 작업을 해주어도 되지만,
    현재 우리는 expo를 이용하여 개발을 진행하고있기 때문에 앱내에서 외부 웹을 오픈할 것이다.
\[서비스 URL\]  
[https://auth.expo.io/@pongsoyun/login-example/start](https://auth.expo.io/@pongsoyun/login-example/start)

\[CallBack URL\]  
[https://auth.expo.io/@pongsoyun/login-example](https://auth.expo.io/@pongsoyun/login-example)

을 기재해 준다.
3. yarn start 를 통해 expo 실행
4. 코드
네아로 구현을 위해, 위에 기재한 개념들을 적용한 코드이다.

import React, { useState } from "react";  
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";  
import { AuthSession } from "expo";  
import axios from "axios";

//  
const NV\_APP\_ID = "YOUR\_CLIENT\_ID";  
const NV\_APP\_SECRET = "YOUR\_CLIENT\_PW";  
const STATE\_STRING = "YOUR\_SECRET\_STRING";

const styles = StyleSheet.create({  
container: {  
flex: 1,  
backgroundColor: "#fff",  
alignItems: "center",  
justifyContent: "center"  
}  
});

export default function App() {  
//useState(), token/code/user  
const \[token, setToken\] = useState();  
const \[code, setCode\] = useState();  
const \[user, setUser\] = useState();


//authsession


async function handlePressAsync() {  
let redirectUrl = AuthSession.getRedirectUrl();  
console.log(redirectUrl);  
console.log(encodeURIComponent(redirectUrl));


const result = await AuthSession.startAsync({
  authUrl: `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${NV_APP_ID}&redirect_uri=${encodeURIComponent(
    redirectUrl
  )}&state=${STATE_STRING}`
});

console.log("result", result);

setCode(result.code);

handleGetAccess();


}


//http data request


async function handleGetAccess() {  
const {  
data: { access\_token }  
} = await axios.get(`https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id=${NV_APP_ID} &client_secret=${NV_APP_SECRET} &code=${code}&state=${STATE_STRING}`);


const config = {
  headers: {
    Authorization: `Bearer ${access_token}`
  }
};

setToken(data.access_token);

const { data } = await axios.get(
  "https://openapi.naver.com/v1/nid/me",
  config
);
console.log(data);
setUser(data);


}

//TEXT press -> handlePressAsync()  
return (

네이버 아이디로 시작하기
//TEXT press -> handlePressAsync()
  return (
    <View style={styles.container}>
      <TouchableOpacity onPress={handlePressAsync}>
        <Text>네이버 아이디로 시작하기</Text>
      </TouchableOpacity>
    </View>
  );
}
  1. CALL BACK 응답정보
  2. API 요청 성공시 : http://콜백URL/redirect?code={code값}&state={state값}  
    API 요청 실패시 : http://콜백URL/redirect?state={state값}&error={에러코드값}&error\_description={에러메시지}

     

 

 

이 과정을 모두 거치고 검수를 마치면(영업일기준 약 3일~5일정도 소요되었다.)

내 애플리케이션\로그인오픈API서비스환경\애플리케이션 개발 상태가 서비스 적용으로 변경된다!

이러면 네아로 적용 완료 ㅎㅎ!