2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React nativeでoauth2.0の認証を行う方法

Last updated at Posted at 2023-05-10

どうもこんちにはたくびー(@takubii)です。
react native内でoauth2.0で認証を行う方法を最近勉強していました。
動くものができたので知識共有もかねて紹介したいと思います。

Linkingを使って外部ブラウザから認証を行う

Linkingを使用してアプリからブラウザへ認証ページへのリンクを作成します。
早速コードの方を見てもらいたいと思います。
申し訳ないですが、細かいところは省略しています。

ざっくりとした全体像

import React, {useState, useEffect} from 'react';
import {SafeAreaView, Linking} from 'react-native';

function App(): JSX.Element {
    const [accessToken, setAccessToken] = useState('');
    const [refreshToken, setRefreshToken] = useState('');

    // リダイレクトでアプリに帰ってきた時の処理をイベントリスナーに登録
    useEffect(() => {
        const listener = Linking.addEventListener('url', async event => {
            const redirectUrl = event.url;

            // トークンエンドポイントへアクセスしてアクセストークンを取得します
            const response = await fetch('{TOKEN_ENDPOINT}', {
                method: 'POST',
                // 必要な場合はヘッダーに情報を追加してください。
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    Authorization: `Basic ${encode('{YOUR_CLIENT_ID}:{YOUR_CLIENT_SECRET}')}`
                },
                body: `grant_type=authorization_code&redirect_uri=${redirectUrl}`,
            });

            if (!response.ok) {
                return;
            }

            const json = await response.json();
            setAccessToken(json.access_token);
            setRefreshToken(json.refresh_token);
        });

        return () => {
            listener.remove();
        };
    }, []);

    // アプリからブラウザの認証ページへ飛ばす処理
    const startAuth = async () => {
        // 認証に使うURLを入力してください
        const authUrl = '{AUTH_URL}';
        const canOpen = await Linking.canOpenURL(authUrl);

        if (!canOpen) {
            return;
        }

        await Linking.openURL(authUrl);
    };

    return (
        <SafeAreaView>
            <Button title="auth" onPress={startAuth} />
            {accessToken && <Text>{`access token = ${accessToken}`}</Text>}
        </SafeAreaView>
    );
}

各メソッドの詳細

全体のコードだけだと理解の把握に時間がかかると思うので、それぞれのメソッドで何をしているのか簡単に解説したいと思います。

startAuthの処理

以下のコードでボタンがクリックされた時に認証ページへ飛ばす処理をしています。
Linking.openURLを使うことでブラウザが開くので、ブラウザ側で認証を行ないます。
リダイレクトURLにアプリのスキーマに合わせたURLを含めることで認証後にアプリに戻ってきます。
※リダイレクトでアプリに戻す方法ですが、こちらの記事で書くととても長くなるので割愛します。

    const startAuth = async () => {
        // 認証に使うURLを入力してください
        const authUrl = `${AUTH_URL}?/response_type=${responseType}&scope=${scope}&client_id=${clientId}&redirect_uri=${redirectUri}`;
        const canOpen = await Linking.canOpenURL(authUrl);

        if (!canOpen) {
            return;
        }

        await Linking.openURL(authUrl);
    };

Linkingを使うためにはIOS、Androidでそれぞれ別途設定が必要になります。

IOS

/ios/{APP_NAME}/AppDelegate.mmに以下を追加してください。

/ios/{APP_NAME}/AppDelegate.mm
#import <React/RCTLinkingManager.h>
  :
  :
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}
Android
/android/app/src/main/AndroidManifest.xml
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

useEffect内の処理

こちらのuseEffect内ではリダイレクトでアプリに戻ってきた時の処理を記載しています。
AUTHORIZATION_ENDPOINTから戻ってきたURLにはcodeが含まれているので、そちらのcodeを利用してTokenの取得を行なっています。
やっていることは単純で、取得したURLをredirect_uriに含めてTOKEN_ENDPOINTへfetchしています。
通信が成功すればJSON形式でアクセストークンとリフレッシュトークンが返ってきます。

    useEffect(() => {
        const listener = Linking.addEventListener('url', async event => {
            const redirectUrl = event.url;

            // トークンエンドポイントへアクセスしてアクセストークンを取得します
            const response = await fetch('{TOKEN_ENDPOINT}', {
                method: 'POST',
                // 必要な場合はヘッダーに情報を追加してください。
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                    Authorization: `Basic ${encode('{YOUR_CLIENT_ID}:{YOUR_CLIENT_SECRET}')}`
                },
                body: `grant_type=authorization_code&redirect_uri=${redirectUrl}`,
            });

            if (!response.ok) {
                return;
            }

            const json = await response.json();
            setAccessToken(json.access_token);
            setRefreshToken(json.refresh_token);
        });

        return () => {
            listener.remove();
        };
    }, []);

終わりに

最後にこちらを実装するのに参考にしたサイトを添付します。
もしうまくいかなかった場合は以下を参考にしてください。
https://qiita.com/Nkzn/items/3a09c08286bd7d4bf88b
https://github.com/jhannes/react-native-oauth-demo/blob/master/README.md
https://reactnative.dev/docs/linking?syntax=ios&language=typescript

ここまで読んでいただきありがとうございます。
React NativeでOAuth2.0認証を実装する方法は調べても意外と出てこなくて思考錯誤を重ねました。
こちらの記事がお役に立っていただければ幸いです。
それでは、また別の機会があればお会いしましょう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?