2019. 11. 19. 23:13ㆍProgramming/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)
- 세션에 인증 정보를 저장 할 필요가 없음
- 액세스 토큰에 인증정보가 있기 때문!
- 서버에서는 디코딩하여 확인 가능
- 인증 후 획득한 액세스 토큰을 헤더에 넣어 호출
- 개발 중 서버가 재구동 될 때 로그인 프로토콜을 호출하지 않아도 된다.
OAuth 적용 절차
OAuth 2.0 기반의 사용자 인증 기능을 통하여 네이버/카카오가 아닌 다른서비스에서 네이버의 사용자 인증 기능을 이용할 수 있게 하는 서비스
- 애플리케이션 등록
네이버아이디로 로그인 적용을 위해 애플리케이션 등록, 클라이언트 아이디/시크릿 키 발급 - 애플리케이션 개발
- 서비스에 OAuth 적용
OAuth의 개념은 이렇고,
react native - expo 프로젝트에 실질적으로 사용하기 위한 내용/코드들을 짚고 넘어간다.
그러면서 AuthSession, Axios 에 관한 내용을 같이 이해하도록 하자.
Axios
Axios란?
- HTTP 클라이언트 라이브러리
- 비동기 방식으로 HTTP 데이터 요청을 실행
- 내부적으로 axios는 직접적으로 XMLHttpRequest를 다루지 않고 “AJAX 호출(자바스크립트로 서버에 데이터를 요청)”이 가능하다.
=> 쉽게말해, axios를 통해 HTTP요청(웹서버-클라이언트 간 통신규약으로, 문서 교환을 위해 요청/응답하는 것)으로 데이터를 가져올 수 있다!
axios 설치
npm install axios --save;
$ yarn add axios
사용 법
-
import
import axuis from "axios";
-
.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에서 특히나 유용하다!
웹 브라우저 기반 인증 흐름의 작동 방식
- 시작 : user 가 login 버튼 누름
- 웹브라우저 열기: 앱이 웹브라우저를 열고, 로그인 페이지를 위한 openURL에는 일반적으로 앱을 식별하기위한 정보 + 성공시 redirection(리디렉션) 할 URL이 포함됨.
cf. 웹브라우저는 쿠키에 기인증여부 등을 담고 움직이기때문에 최초 로그인 후에는, 다시 로그인 할 필요가 없다! - 인증 공급자가 리디렉션: 성공적인 인증 시 인증 공급자 페이지의 URL이 제공 허용된 리디렉션 URL의 허용 목록에 존재하고, 리디렉션에는 위치 해시, 쿼리 매개변수 또는 둘다의 URL(ex. UserID, token) 등의 데이터가 포함되어있음
- 앱이 리디렉션 처리, 리디랙션 URL에서 데이터를 구문분석
AuthSession 사용법
- 사용자 인증
[https://auth.expo.io/@your-user-name/your-app-slug](https://auth.expo.io/@your-user-name/your-app-slug)
- 인증 방식
- 인증 성공 시 인증 공급자가 해당 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.
네이버 아이디로 로그인
- 네이버 개발자 회원가입 -> 로그인 -> 네아로(네이버 아이디로 로그인)/애플리케이션 등록
- 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>
);
}
- CALL BACK 응답정보
-
API 요청 성공시 : http://콜백URL/redirect?code={code값}&state={state값} API 요청 실패시 : http://콜백URL/redirect?state={state값}&error={에러코드값}&error\_description={에러메시지}
이 과정을 모두 거치고 검수를 마치면(영업일기준 약 3일~5일정도 소요되었다.)
내 애플리케이션\로그인오픈API서비스환경\애플리케이션 개발 상태가 서비스 적용으로 변경된다!
이러면 네아로 적용 완료 ㅎㅎ!
'Programming > React Native' 카테고리의 다른 글
React Hook 이란? (0) | 2020.02.24 |
---|---|
[리액트 네이티브] 참고할만한 사이트 (0) | 2019.05.29 |
[리액트네이티브] npm으로 expo cli가 다운로드 완료되었지만 -bash: command not found(찾을수없음) 의 현상 (4) | 2019.05.28 |