2020-08-30に投稿

GitHub OAuth Appのトークンを取得失敗した

access tokenはクライアント側から取得できない

やりたかったこと

GitHubをJSONデータベース代わりに使いたかった. GitHub APIを使うとGitHubをREST APIから操作できるので, これにフロント付けたら簡易なデータベースを作れるのではと思ったわけです. これは結局Cross-Origin Request Blockedでできないことが分かりました.

忘れちゃうのもあれなので概要をメモしておきます.

環境

以下のパケージを利用しました.

またreact-adminで認可するロジックは以下を参考にしました.

OAuth Applicationの作成

Creating an OAuth Appを参考にしましょう.

作成されたGitHub OAuth Appには固有の値であるclient idとclient secretが付与されるます.

Auth Provider

react-adminで認証や認可を行うにはauth providerにロジックを書きます.

const authProvider = {
    login: params => Promise.resolve(),
    logout: params => Promise.resolve(),
    checkAuth: params => Promise.resolve(),
    checkError: error => Promise.resolve(),
    getPermissions: params => Promise.resolve(),
};

取得したトークンはローカルストレージに保存します. checkAuthではこのトークンがすでに設定されているかを確認し, 無ければログイン画面が表示されます.

checkAuth: () => {
    const user_name = localStorage.getItem('username');
    console.log(`checkAuth: ${user_name}`)
    return localStorage.getItem('username')
        ? Promise.resolve()
        : Promise.reject();
},

ログイン画面では2つの処理を行います. まず認可ページで認可を行います. 認可後はAuthorization callback URLに指定したページに戻ってくるのですが, この際codeというURLパラメータが付与されます. これとclient id, client secretを使ってトークンを取得します. stateは任意ですが一応付けてます.

import { createOAuthAppAuth } from '@octokit/auth-oauth-app';

const authorizeURL = new URL('oauth/authorize', process.env.login_url);
authorizeURL.searchParams.append('client_id', process.env.client_id);
authorizeURL.searchParams.append('scope', 'public_repo');
authorizeURL.searchParams.append('state', 'QAbgG6f9Rit2C5');

const auth = createOAuthAppAuth({
    clientId: process.env.client_id,
    clientSecret: process.env.client_secret,
});

login: async (params) => {
    const { searchParams } = new URL(window.location.href);

    if (!searchParams.has('code') || !searchParams.has('state')) {
        redirectToURL(authorizeURL)
        return Promise.resolve();
    }

    const code = searchParams.get('code');
    const state = searchParams.get('state');

    const tokenAuthentication = await auth({
        type: 'token',
        code: code,
        state: state,
    });

    const { token } = tokenAuthentication;

     localStorage.setItem('username', token);

    return Promise.resolve();
},

ところがauthでtokenを取得しようとすると失敗します. リバース・プロキシを設置してやるといけるようですが, 試してません.

OAuth Github web flow doesn't support CORS

補足

Next.jsとreact-adminを使うとDocument is not definedというエラーが出ます. hisotryというパッケージが内部でDOM APIを利用しているのですがNext.jsは最初ローカル側(サーバー側)で動くのでこの時点ではDOMが存在しません. クライアント側かどうか調べる必要があります. getStaticPropsはロカールで実行され, ファイルなどを取得してpropsとしてページ・コンポーネントに渡すことができます. この処理が終了するとブラウザ側の処理に移ることを利用するとコンポーネントを切り替えることができるようです.

How to prevent parent component from re-rendering with React (next.js) SSR two-pass rendering?

ツイッターでシェア
みんなに共有、忘れないようにメモ

ブレイン

Androidアプリ開発者を目指しています. 興味あることリスト: https://t.co/ew3bb6grdJ Github: https://t.co/9btqysHqWr Qiita: https://t.co/ZVRhjouauX

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント