socket.ioでAuth0を使う時verificationでエラー

https://github.com/auth0-community/auth0-socketio-jwt を使うとできそうですが、verify周りで少し詰まったのでメモです。

何も考えずに実装して以下のようなエラーが出た時の対処です。

connection_manager > node emit-example.js
unauthorized: {"message":"invalid algorithm","code":"invalid_token","type":"UnauthorizedError"}
/home/asmsuechan/src/asmsuechan/connection_manager/emit-example.js:33
      throw new Error(msg.data.type);
      ^

Error: UnauthorizedError
    at Socket.<anonymous> (/home/asmsuechan/src/asmsuechan/connection_manager/emit-example.js:33:13)
    at Socket.Emitter.emit (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/component-emitter/index.js:133:20)
    at Socket.onevent (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/socket.io-client/lib/socket.js:278:10)
    at Socket.onpacket (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/socket.io-client/lib/socket.js:236:12)
    at Manager.<anonymous> (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/component-bind/index.js:21:15)
    at Manager.Emitter.emit (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/component-emitter/index.js:133:20)
    at Manager.ondecoded (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/socket.io-client/lib/manager.js:345:8)
    at Decoder.<anonymous> (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/component-bind/index.js:21:15)
    at Decoder.Emitter.emit (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/component-emitter/index.js:133:20)
    at Decoder.add (/home/asmsuechan/src/asmsuechan/connection_manager/node_modules/socket.io-parser/index.js:251:12)

JWTのverifyでコケています。ライブラリの中を見たらjsonwebtokenをそのまま使っていた部分がコケていたので詳しくは https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback を参照。

  • どのアルゴリズムを使っているか調べる(たぶんRSA256)
  • algorithmsオプションをauthorize()メソッドに追加する
  • https://[your_domain].auth0.com/pem からpublic keyをダウンロードする

コードはこんな感じです。

const cert = fs.readFileSync('dev-mypubkey.pem');
io.of("/my_prj").on('connection', socketioJwt.authorize({
  secret: cert,
  timeout: 15000, // 15 seconds to send the authentication message
  algorithms: ['RS256']
})).on('authenticated', (socket) => {
  console.log('authenticated!')
})

なおbase64エンコードしたpemファイルでもOKです。Buffer.from(secret, 'base64')すれば使えます。実際に使う時はこちらが良いでしょう。