オレオレSSL証明書で運用されているGHEにPassportでログインする
解決方法
passport-githubが内部で使っているpassport-oauth2のhttp agentを差し替える
https://github.com/ciaranj/node-oauth/pull/324
つまりstrategy作ってから最後にこうするだけで良い
strategy._oauth2.setAgent(new https.Agent({rejectUnauthorized: false}))
/help-jp/自己証明書で運用されているGHEへの認証でも使っている
以下詳しく
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には書かれてないが、コード読むとわかる
https://github.com/jaredhanson/passport-github/blob/v1.1.0/lib/strategy.js#L51-L65
オプションがどんどん増えてこんな感じになる
code: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が発生する
間違った解決方法
https://stackoverflow.com/questions/21129989/internaloautherror-failed-to-obtain-access-token
require('https').globalAgent.options.rejectUnauthorized = false;しろ、と書かれている
このオプションは最近のnode.jsでは使えなくなっている
もし可能でも、やらないほうが良い
globalAgentを上書きできてしまったら
OAuth以外のライブラリも、全て影響を受けてしまう
危険すぎる
正しい解決方法
oauth npmのhttp agentを差し替える
passportの構造
passport
passport-strategy
passport-github
passport-oauth2
oauth npm
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を差し替えたい
そういう目的で作られた抜け道がある
Adding ability to specify an agent for OAuth2 requests by PhilipSkinner · Pull Request #324 · ciaranj/node-oauth
oauth npmのOAuth2.prototype.setAgentを呼び出すと、OAuth npmのprototypeの_agentを更新できようになった
https://github.com/ciaranj/node-oauth/blob/0.9.15/lib/oauth2.js#L25
2017年1月に実装された
_agentを追っていく
prototype._agentはOAuth2.prototype._executeRequestで使われるhttps agentを上書きできる
OAuth2.prototype._executeRequestはOAuth2.prototype._requestから呼び出される
options._agentはハードコーディングされていて、関数_requestの引数からは操作できない
https://github.com/ciaranj/node-oauth/blob/0.9.15/lib/oauth2.js#L146
http_library.request(options)で、options.agentとして渡される
http_libraryには、Nodejs標準のhttpとhttpsのどちらかが選ばれる
OAuth endpointのURLをparseして自動的に決定される
つまりhttps.requst(options)になる
https://nodejs.org/api/https.html#https_https_request_options_callback
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行を書けば完成なのだが
影響範囲がどこまでなのか、しっかり調べるとコードリーディング大会が開催され、結構大変だった