generated at
オレオレSSL証明書で運用されているGHEにPassportでログインする

解決方法
passport-githubが内部で使っているpassport-oauth2のhttp agentを差し替える
つまりstrategy作ってから最後にこうするだけで良い
strategy._oauth2.setAgent(new https.Agent({rejectUnauthorized: false}))



以下詳しく

passportのlogin strategyであるpassport-githubを使うと、GitHubアカウントにOAuthするNodejsアプリが簡単に作れる
const strategy = new GithubStrategy({clientID, clientSecret, callbackURL}) でstrategy作って
passport.use(strategy, callback) すればログインできる
Express等に組み込むのも簡単

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)


オレオレSSL証明書で運用されているGHEにログインしたい
イントラネットで運用されているGHEは、自己署名証明書な場合があるようだ
そこに普通に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行を書けば完成なのだが
影響範囲がどこまでなのか、しっかり調べるとコードリーディング大会が開催され、結構大変だった