Expo로 OAuth를 구현해보자!

김지민·2022년 5월 4일
16
post-thumbnail

| 노잉(knowing)이라는 프로젝트를 진행한 내용을 바탕으로 다른 사람들은 Expo로 Oauth를 구현하며, 삽질을 하지 않았으면 하는 바람에 글을 써본다.

노잉홍보

노잉은 숏폼 Q&A 서비스이다.(틱톡 + 지식인) 많은 관심 부탁드립니다!!!!

OAuth를 왜 쓸까?

OAuth는 다른 서비스의 회원 정보를 안전하게 사용하기 위한 방법이다.
고객이 자신의 Google, Kakao, 네이버 등의 아이디/비밀번호를 우리 서비스에 알려주지 않더라도, 고객의 정보를 우리 서비스에서 안전하게 사용하기 위한 방법이다.

OAuth의 동작과정!

다음은 내가 만든 서비스의 오어쓰 동작과정이다.

  1. 우리 서비스에서 로그인을 누르면 각 플랫폼의 인증페이지로 넘어간다.
  2. 인증이 성공할 경우 링크로 보내준 redirect_uri로 코드와 함께 이동한다.
  3. 전달받은 코드를 우리 서비스 서버로 보내준다!
  4. 서버에서는 구글에게 코드를 전달해주고, 코드 안에있는 유저정보를 가져온다.
  5. 유저정보를 가지고있는 access_token을 다시 클라이언트로 준다!

대부분의 오어쓰는 이러한 과정으로 동작한다.

Expo Setting

우리가 Expo에서 OAuth를 사용하기 위해서는 각 플랫폼(구글, 네이버, 애플 등)에서 애플리케이션을 등록해줘야 한다. 그러기 위해서는 expo 프로젝트안에서 bundle id를 설정해줘야한다.
app.json

{
	"ios":
		"bundleIdentifier": "your bundle id",
	"android":
		"package": "your bundle id"
}

또한 Android의 경우 sha-1 인증서 디지털 지문이 필요한 플랫폼도 있다.

이러한 경우에는 당황하지 말고, 터미널을 킨 후, 자신의 Expo프로젝트로 이동하여

expo fetch:android:hashes

를 입력한다. 그러면 sha-1 인증서 디지털 지문을 구할 수 있다.

Expo Get Redirect Uri

Expo에서 RedirectUri를 얻는 방법은 2가지 정도가 있다.
1. 직접 redirect Uri를 만든다.
2. expo-auth-session을 통해 가져온다.

먼저 첫번째 방법을 사용한다면 app.json에 있는 slug와 자신이 로그인한 expo계정을 사용하여 만들 수 있다.
우리가 만든 Expo 프로젝트의 redirect uri는 https://auth.expo.io/@계정이름/slug가 된다.
또한 expo에 로그인 하는 방법은 expo cli를 다운받은뒤 expo login -u username -p password로 로그인하면 된다.

두번째 방법은 expo-auth-session에 getRedirectUrl을 사용한다.

import * as AuthSession from 'expo-auth-session';
const url = AuthSession.getRedirectUrl();

메게변수에 문자열을 넣는다면 "https://auth.expo.io/@계정이름/slug/문자열"식으로 나오게 된다.

Apple OAuth

오어스 중 그나마 쉬웠다고 생각했던 애플 OAuth에 대해 소개하겠다. Apple OAuth를 넣었던 이유는 OAuth를 사용하고 App Store에 올리기 위해서는 무조건 Apple로그인이 필요했기 때문이다.

Expo에서 Apple Login을 하기 위해서는 "expo-apple-authentication"을 사용했다.
이 라이브러리는 iOS에서만 동작하기 때문에 안드로이드에서는 사용할 수 없다.
공식문서: https://docs.expo.dev/versions/latest/sdk/apple-authentication/


위와 같이 애플로그인은 버튼 Component를 주며, 안에 각종 옵션들이 들어있다.
아래와 같은 대표적인 옵션이 있다.

  • onPress: 버튼을 눌렀을 경우 실행하는 함수를 넣는다.
  • buttonType: 문구를 "Sign In with Apple"나 "Continue with Apple" 중 선택할 수 있다.
  • buttonStyle: 버튼의 색깔을 선택할 수 있다.(BLACK, WHITE, WHITE_OUTLINE)

이제 로그인을 하기위해서 signInAsync라는 함수를 써야한다.

import * as AppleAuthentication from "expo-apple-authentication";

const credential = await AppleAuthentication.signInAsync({
              requestedScopes: [
                AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
                AppleAuthentication.AppleAuthenticationScope.EMAIL,
              ],
            });

으로 유저 정보들을 가져올 수 있다. 또한, Apple은 보안 정책상 처음 로그인 할 경우에만 유저 정보를 준다.

Naver OAuth

네이버 로그인은 expo-auth-session으로 구현했다.
expo-auth-session은 expo에서 각종 OAuth를 웹뷰 형식으로 처리해주는 라이브러리이다.
공식문서: https://docs.expo.dev/versions/v44.0.0/sdk/auth-session/

다음과 같은 방식으로 expo-auth-session을 사용할 수 있다.

const naverLogin = async () => {
    const result = await AuthSession.startAsync({
      authUrl: "https://nid.naver.com/oauth2.0/authorize?response_type=원하는 반환 형식&client_id=yourClientId&redirect_uri=yourExpoUri",
    });

    if (result.type === "success") {
      const code = result.params.code;
      mutate({
        id_token: code,
        provider: "NAVER",
      });
    }
  };

여기서 response_type은 code나 idToken등이 있다. 또한, client_id는 아까 위에서 말했듯이 애플리케이션 등록을 한 뒤 얻은 client_id를 사용하면 된다. rediect_uri또한 위에서 구한 redirect_uri를 사용하면된다.

Google OAuth

내가 느끼기에 가장 힘들었던 것 같다. 우선 구글은 2016년부터 더나은 사용성과 보안성을 위해 웹뷰에서의 OAuth사용을 제한했다. 그렇기 때문에 웹뷰로 구글 OAuth를 구현하는 것은 어려워졌다... ㅜㅜ
구글 OAuth를 위한 라이브러리는 expo-google-sign-in, expo-auth-session/providers/google가 있었는데, 각각의 라이브러리에 문제점이 있다.

  • expo-google-sign-in: 개발중에는 이 라이브러리 사용이 불가능하지만, 배포(standalone)를 할때에는 사용할 수 있다.
  • expo-auth-session/providers/google: 개발중에는 잘 동작하지만, 배포(standalone)를 하면 400(redirect_mismatch)가 나면서 동작하지 않는다.

나는 2번째 라이브러리를 사용한 뒤 배포 후 동작하지않아 많은 삽질을 했다...
그렇기 때문에 각자의 프로젝트에 맞게 라이브러리를 사용해야 한다.

expo-google-sign-in

expo-google-sign-in은 배포 후에만 사용가능하다. 또한 expo-auth-session을 사용하며, 더이상 사용되지 않는다고 하지만, expo-auth-session은 배포후 동작되지 않았기 때문에 어쩔 수 없이 사용했다.
공식문서: https://docs.expo.dev/versions/latest/sdk/google-sign-in/

사용법

import * as GoogleSignIn from "expo-google-sign-in";
//구글 로그인 설정
await GoogleSignIn.initAsync({
        signInType: GoogleSignIn.TYPES.DEFAULT,
        clientId:
          Platform.OS === "android"
            ? env.googleClientId.androidId
            : env.googleClientId.iosId,
        scopes: [
          GoogleSignIn.SCOPES.OPEN_ID,
          GoogleSignIn.SCOPES.EMAIL,
          GoogleSignIn.SCOPES.PROFILE,
        ],
      });
      //사용자가 Play 서비스가 아직 최신 상태가 아닌 경우 Play 서비스를 업데이트할 수 있는 모달 제공
      await GoogleSignIn.askForPlayServicesAsync();
      //구글 로그인으로 이동 및 response 반환
      const response = await GoogleSignIn.signInAsync({});

expo-auth-session/providers/google

이 라이브러리가 expo에서 사용하라고 하는 방법이다. 그렇지만 개발 중에만 사용가능하며, 배포후에는 에러가 나오게된다.
공식문서: https://docs.expo.dev/versions/latest/sdk/auth-session/#google

사용법

import * as Google from 'expo-auth-session/providers/google';

const [request, response, promptAsync] = Google.useAuthRequest({
	expoClientId: 빌드하기 전 사용할 Client_id,
    iosClientId: ios client_id,
    androidClientId: android client_id,
    webClientId: web Client_id,
    redirectUri: redirecUri,
    scopes: [가져올 유저정보],
    responseType: code나 idToken등 가져오고 싶은 타입,
    )}

const googleLogin = () => {
	promptAsync();
}

끝마치며

이렇게 expo로 여러 플랫폼의 OAtuh를 해보았는데, 처음에는 만만하게 봤다가 된통 당한 것 같다...
그렇기 때문에 다른사람은 나처럼 삽질을 하기보다는 이 글을 읽고 좀 더 편하게 OAuth를 구현하면 좋겠다.
또한, 반응이 좋으면 expo를 사용하면서 어려웠던 다른 부분들도 올릴까한다..
마지막으로 친구들과 함께 노력해서 만든 노잉 많은 관심 가져주고, 다운로드 해주면 좋겠당.... ㅎㅎ...

궁금한 점이 있거나 수정해야 하는 부분이 있으면 언제든 연락주세요!!
이메일 jm004471@gmail.com

0개의 댓글