オレオレSSL証明書で運用されているGHEにPassportでログインする
解決方法
つまりstrategy作ってから最後にこうするだけで良い
strategy._oauth2.setAgent(new https.Agent({rejectUnauthorized: false}))
以下詳しく
const strategy = new GithubStrategy({clientID, clientSecret, callbackURL})
でstrategy作って
passport.use(strategy, callback)
すればログインできる
GitHubだけでなく
GHE(GitHub Enterprise)にもログインできる
new GithubStrategy(options)
のoptionsに
さらに authorizationURL
と tokenURL
と userProfileURL
も追加すると、できる
documentには書かれてないが、コード読むとわかる
オプションがどんどん増えてこんな感じになる
js const options = {
authorizationURL: process.env.GHE_HOST + '/login/oauth/authorize',
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: process.env.APP_URL + '/auth/github/callback',
scope: ['user:email'],
state: true
tokenURL: process.env.GHE_HOST + '/login/oauth/access_token',
userAgent: 'scrapbox',
userProfileURL: process.env.GHE_HOST + '/api/v3/user'
}
const strategy = new Strategy(options, onLogin)
そこに普通にpassport-githubでOAuthしようとすると
InternalOAuthError: Failed to obtain access token
が発生する
間違った解決方法
require('https').globalAgent.options.rejectUnauthorized = false;
しろ、と書かれている
もし可能でも、やらないほうが良い
globalAgentを上書きできてしまったら
OAuth以外のライブラリも、全て影響を受けてしまう
危険すぎる
正しい解決方法
oauth npmのhttp agentを差し替える
passportの構造
passport-strategy
passportはフレームワークなので、普通に使うぶんには一番上の層しか意識しなくて済む
しかし、下の方で問題が起こるとコード追うのがけっこう大変
多層構造になっている為
上下のライブラリを行ったり来たりしながら追っていく必要がある
構造としてはpluginで拡張するタイプのフレームワークなら妥当な物だと思う
この辺は複雑性をどう縮減していくかという設計パターンの話で、まあ順当に設計すればpassportみたいになるはずなので、文句はない
このライブラリ内のこのインスタンスは、こっちのライブラリのコレだよな????という突き合わせが必要になってくる
npmの中にconsole.log仕込んで地道に調査していくしかない
やればできる
passport-googleとかだとさらにAPIのバージョン等があって、さらに層が増える
oauth npmが使うhttps agentを差し替える
1つずつライブラリの中のコードを追っていく
同時に使っている他のstrategyに影響を与えちゃったりしないかな?とか
だんだん気になってくるので、コード読まざるを得ない
const strategy = new GithubStrategy(options)
で作った strategy
の
strategy._oauth2
が、oauth npmのインスタンスである
これの中のhttp agentを差し替えたい
そういう目的で作られた抜け道がある
oauth npmの OAuth2.prototype.setAgent
を呼び出すと、OAuth npmのprototypeの _agent
を更新できようになった
2017年1月に実装された
_agent
を追っていく
prototype._agent
は
OAuth2.prototype._executeRequest
で使われるhttps agentを
上書きできる OAuth2.prototype._executeRequest
は OAuth2.prototype._request
から呼び出される
options._agent
はハードコーディングされていて、関数 _request
の引数からは操作できない
http_library.request(options)
で、 options.agent
として渡される
http_library
には、Nodejs標準のhttpとhttpsのどちらかが選ばれる
OAuth endpointのURLをparseして自動的に決定される
つまり https.requst(options)
になる
https.request(options[, callback])
passport-oauth2が指定しているhttps agentを調べる
agentは標準ライブラリの https.request
を呼び出した所で、毎回指定する必要がある
http agent差し替えても、同時に使ってる他のstrategyに影響は無い事がわかった
http agentを差し替える
というわけで
strategy._oauth2.setAgent(new https.Agent({rejectUnauthorized: false}))
という1行を書けば完成なのだが
影響範囲がどこまでなのか、しっかり調べると
コードリーディング大会が開催され、結構大変だった