{
"$type": "site.standard.document",
"canonicalUrl": "https://blog.nove-b.dev//posts/auth-mastodon-react-native",
"description": "React NativeでMastodon認証を実装した",
"path": "/posts/auth-mastodon-react-native",
"publishedAt": "2024-12-20T00:00:00.000Z",
"site": "at://did:plc:2atly2y5kfyjcj5zap6pv4wd/site.standard.publication/3mmxeqr2tcb2k",
"tags": [
"React Native",
"Mastodon API"
],
"textContent": "Mastodonnのクラインアント用ネイティブアプリをReact NativeとExpoで作成している。\n\nバージョンは下記の通り。\n\n実装自体はできたんだけれど、正直いろいろと理解が足りていないので、整理してみる。\n\nインストールしたPackage\n\nexpo-auth-session\n\n> ブラウザベースの認証を処理するための API\n\n<iframe src=\"https://social.nove-b.dev/@nove_b/113674167224507515/embed\" class=\"mastodon-embed\" style=\"max-width: 100%; border: 0\" width=\"400\" allowfullscreen=\"allowfullscreen\"></iframe><script src=\"https://social.nove-b.dev/embed.js\" async=\"async\"></script>\n\n最初は認証時にWebViewを開いて認証に成功したらリダイレクトURIを用いてアプリ画面に戻すという仕組みを実装しようとしたんだけれど、そもそもリダイレクトURIがわからない。Expoの開発用URLを指定してみたけど、\n\nという謎のエラーが出てアプリ側に戻らない。\n\nそしてタスク管理でアプリに戻ると認証が成功しているという謎の現象が発生した。\n\n色々悩んでいたけどexpo-auth-session\nを使用したらリダイレクトURIの作成をいい感じにやってくれた。\n\nExpo AuthSessionにはexpo-crypto\nと一緒にインストールする必要があるって書いてあったけど、インストールしていない。今のところ問題はないので気にしないでおく。\n\nexpo-secure-store\n\nExpo SecureStore\n\nExpo用のローカルストレージ。\n\nで、一通りの作業ができる。\n\n認証に用いたMastodon API\n\n- ${instanceUrl}/api/v1/apps\n - クライアント アプリケーションを登録\n- ${instanceUrl}/oauth/authorize?\n - OAuth トークンを生成および管理\n- ${instanceUrl}/oauth/token\n - API 呼び出し中に使用するアクセス トークンを取得\n\n認証までのフロー\n\nアプリケーションを登録\n\nクライアント アプリケーションを登録APIを叩く。\n\nBodyにclient_name、redirect_uris、scopes、websiteが必要になる。\n\nclient_nameはアプリ名を指定し、redirect_urisはexpo-auth-sessionを使用し作成する。\n\nscopesは権限を指定し、websiteはアプリのウェブサイトをインプットする。\n\n成功すると、\n\nが取得できる。\n\nclient_id、client_secretは後ほど使用する。関数をまたいで使用するので、expo-secure-storeに保存した。\n\n認証画面を開く\n\n取得したclient_idを用い、認証URLを作成しブラウザで開く。\n\nその際、expo-web-browserを使用した。Expo WebBrowserだけどインストールした記憶がないので、たぶん標準で入っていた。\n\nreact-native-webviewとは異なり、ネイティブなブラウザモーダルを使用するらしい。\n\n使い分けの参考は下記の通り。\n\n| 要素 | expo-web-browser | react-native-webview |\n| ------------------------ | -------------------------------- | -------------------------------------------- |\n| 利用シーン | 外部リンクを簡単に開く場合 | ウェブページをアプリの一部として組み込む場合 |\n| 操作性 | 操作不可 | DOM操作やイベントリスニングが可能 |\n| UIの統合性 | 外部ブラウザ風のUI(独立性あり) | アプリ内に統合されたUI |\n| インストールの必要性 | 不要(Expoに標準搭載) | 必要(個別にインストール) |\n| パフォーマンス | 高速(ネイティブブラウザ) | やや劣る可能性あり |\n\nで、expo-web-browserには認証フローのメソッドがある。\n\n上記メソッドを実行すると下記フローが走る。\n\n1. 認証プロバイダーとのやり取り:<br> authUrlに指定したプロバイダー(例:\n GoogleやTwitter)に接続し、ユーザーが認証情報を入力できる画面を表示。\n1. リダイレクトハンドリング:<br>\n 認証が成功すると、プロバイダーはredirectUriにリダイレクト。<br>\n アプリはそのリダイレクトURLを受け取り、アクセストークンや認証コードを抽出して利用。\n1. ネイティブモーダルの使用:<br>WebBrowser.openAuthSessionAsyncは、ネイティブの認証モーダル(Safari\n View ControllerやChrome Custom\n Tabs)を使用するため、認証が安全かつシームレスに行える。\n\nアクセストークンの取得\n\n認証が完了したら、認証結果に含まれるcodeを用い、アクセストークンを取得する。その際、先ほど保存したclient_id、client_secretをBodyに含める。成功後したら認証が成功したということなので、取得したアクセストークンをexpo-secure-storeに保存して、アクセストークンを持っている人用のページにリダイレクトする。\n\nルートに関係ないディレクトがルートに紐づく問題\n\napp以下にmodelという型フォルダを作成したら、\n\nというエラーが吐き出された。どうやらReact nativeはファイル構造に基づいてルートを自動生成するらしい。\n\nしかしこれはルート判定してほしくない。除外判定の仕方がわからなかったので、appと同階層にsrcを作成しそこに格納した。\n\nこれが正しいかはわからない。",
"title": "React NativeでMastodon認証を実装した"
}