🔑

ElectronでAuth0認証を使う

2022/03/15に公開約2,600字

概要

最近は Next.js でフロント側を作成しています。
SSR を使用しない環境がほとんどですが Webpack 関連とかめんどくさいことを丸投げできるのは便利ですね。

さらに Electron と組み合わせた Nextron の存在も相まってますます開発が捗るという感じです。

https://github.com/saltyshiomix/nextron

そんな Electron(Nextron)を使用して Auth0 で認証しようとすると Electron の Main プロセスで Express などで WebServer を起動してコールバックを取得するサンプルが多く存在しており、個人的には Auth0 の認証のために WebServer を立てるというのが気に食わないので他にないかなぁと探した記録です。

パッと検索した感じだと

と言ってもググれば誰でもすぐに見つけられます。

  • 公式で紹介されているチュートリアルに従って実装していく
  • electron-auth0-login をつかう

の 2 パターンが丸いかなぁと思いました。

公式のブログで紹介されているやーつ

https://auth0.com/blog/securing-electron-applications-with-openid-connect-and-oauth-2/

これは Express でローカルに WebServer を立てるパターンでした。electron-auth0-login がダメなら使うしかないなぁという感じ。

electron-auth0-login を使う

https://github.com/jbreckmckye/electron-auth0-login

本命です。

github にあるサンプルのような感じで使えば普通に使用可能ですが、renderer から使用方法としてして紹介されている手法は新しめの Electron では使用できませんので ipcRenderer.invoke でメインプロセスに実行させるのがいいかと思いました。

auth.ts に関しては現状以下のような感じにしています。

auth.ts
import { auth0Login } from 'electron-auth0-login';
import keytar from 'keytar';

export default auth0Login({
  debug: true,
  auth0: {
    audience: '{{使用するAPIとかのAudience}}',
    clientId: '{{Auth0のClientId}}',
    domain: '{{Auth0のドメイン}}',
    scopes: 'openid profile offline_access',
  },
  refreshTokens: { keytar, appName: '{{app名など}}' },
});

electron-auth0-login のページではリフレッシュトークンの保存先に keytar を使用すると、Windows 環境で問題があると書かれていますが、執筆時の 7.4.0 では対策がされているようなので普通に使用できるとのこと。

https://github.com/atom/node-keytar

問題がありました

よーしパパ早速つかっちゃうぞー!と使用してみたのですが getToken が返ってこない現象が起こりました。

どうやら内部で使用している got.post を await しているところで処理が返ってこないみたいでした。

処理としては

background.ts
(async () => {
  await app.whenReady();

  const token = await auth.getToken().catch((e) => console.error(e));

  // tokenをあれやこれやする

  const mainWindow = createWindow('main', {
    width: 1000,
    height: 600,
  });

  await mainWindow.loadURL('app://./home.html');
})();

こんな感じで whenReady で app の初期化を待ってから getToken しているので問題ないかと思っていたのですが...

どうやら BrowserWindow でウインドウの生成をした後なら OK みたいなので以下のように変更しました。

background.ts
(async () => {
  await app.whenReady();

  const mainWindow = createWindow('main', {
    width: 1000,
    height: 600,
    show: false,
  });
  mainWindow.once('ready-to-show', () => {
    mainWindow.show();
  });

  const token = await auth.getToken().catch((e) => console.error(e));

  // tokenをあれやこれやする

  await mainWindow.loadURL('app://./home.html');
})();

あとは ipcRenderer.invoke で renderer から取得できるようにするなりします。

おっと忘れてはいけない Auth0 設定

audience で指定した API の設定にて Access Setting -> Allow Offline Access をオンにしておかないと refresh_token を返してくれませんのでご注意

あとがき

とまぁわかってみれば簡単なのですが、小2時間かかってしまったのでメモ書きしておきます。

GitHubで編集を提案

Discussion

ログインするとコメントできます