OAuth2 Proxyで外部認証(1) GitHub編

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/e347bad7-cb23-7704-01eb-3789ab17dc11.png)

# 概要

- 自前の認証機能を持っていない、既存のウェブサイトや独自アプリがある
- Basic認証などで都度ID/パスワード設定するのは古臭いし管理たいへんなので止めたい
- シングルサインオンできる外部の認証機能を使いたい

⇒ リバースプロキシとして機能する OAuth2 Proxyを立てる


# [OAuth2 Proxy](https://github.com/oauth2-proxy/oauth2-proxy)の紹介

- 開発言語は GO言語 ⇒ ライブラリ同梱した単体実行ファイル生成可能
- ライセンスは [MITライセンス](https://github.com/oauth2-proxy/oauth2-proxy/blob/master/LICENSE)
- 証明書登録してTLSサイトとなることも可能（だが今回は使わない）
- 他のHTTPサーバのバックエンドとしても機能することも可能（今回はこの使い方をする）
- リバースプロキシの下流サーバはSNI未対応 ⇒ name based Virtual Hostには使えない（ちょっと残念）


# 仕様構成

こんな感じ。

![useCase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/7b41d815-a18d-4558-54d9-71396f2d77cd.png)


# 設定の流れ

Apacheベースの既存サイトが起動済み、仮想サーバ設定を追加していく想定。

起動済みサイトは `https://example.com` として例示する。


## OAuth2 Proxyダウンロード

今回は [releases](https://github.com/oauth2-proxy/oauth2-proxy/releases) から、ターゲットホストであるLinux x64バイナリをダウンロードしてそのまま使う。

v7.2.1を利用。


## OAuth2 Proxy設定ファイル記述


[認証プロバイダごとの設定方法](https://oauth2-proxy.github.io/oauth2-proxy/configuration/providers/) が紹介されているので、そちらを参考にする。
今回はGitHubを使うので、 [GitHubの項](https://oauth2-proxy.github.io/oauth2-proxy/configuration/providers/github) を参照する。

### GitHubでのアプリケーション登録

設定ファイルには、認証プロバイダに接続するための `client_id` と `client_secret` (秘密鍵)が必要になるので登録する。

説明に書いてある以下URLに飛ぶ。

[https://github.com/settings/developers](https://github.com/settings/developers)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/09f20ccf-1f7d-e823-6b20-8e3dbf521539.png)

右上の「New OAuth App」ボタンを押して新規アプリケーションを登録。
必須項目は以下だけ。

- Application name
- Homepage URL
- Authorization callback URL

最後がOAuth2 Proxyの設定に影響するので注意。

既存サイト（アプリ）にかぶらない任意のパスを設定する。たとえば以下とする。

[https://example.com/oauth2/callback](https://example.com/oauth2/callback)

決定したURLは、設定ファイルの `redirect_url` の項目として記述。

### `client_id`, `client_secret` の取得

GitHub のガイドに従って実行する。詳細は割愛。

### 全体記述例

未設定のものは省略

```oauth2-proxy.cfg
http_address = "127.0.0.1:3333"
reverse_proxy = true
redirect_url = "https://example.com/oauth2/callback"
upstreams = [
    "http://inside.example.com/"
]
header = true
pass_host_email_domains = [
    "your-mail.example.com"
]
provider = "github"
client_id = "xxxx"
client_secret = "xxxx"
cookie_secret = "xxxx"
```

`upstreams` が提供サイトの情報。
OAuth2 Proxyから見えさえすればよく、Hostヘッダも送らないようなので、プライベートなIPv4アドレス直指定でもよいと思われる。

`client_id`, `client_secret` は、前述で取得したものを利用。

`cookie_secret` には任意の値で構わないと思われるが、 `/dev/urandom` から取得したものを文字列として利用した（たしか）。


## OAuth2 Proxy起動

作成した `oauth2-proxy.cfg` を引数にして実行ファイルを起動する。

```
$ ./oauth2-proxy --config oauth2-proxy.cfg
```

とりあえず一般ユーザーでの手動起動。
systemdへの登録などは今後検討。


## 外部用サイトの仮想設定

外部サイト側のすべてのパスをOAuth2化したいわけではなかったので、`ProxyPass` / `ProxyPassReverse` で渡すための設定を追加。

```virtual.conf (既存のサイト設定)
<VitrualHost example.com:443>
        ProxyPass /oauth2/ http://127.0.0.1:3333/oauth2/ disablereuse=On
        ProxyPassReverse /oauth2/ http://127.0.0.1:3333/oauth2/
        ProxyPass /apps/ http://127.0.0.1:3333/apps/ disablereuse=On
        ProxyPassReverse /apps/ http://127.0.0.1:3333/apps/
</Virtualhost>
```

`/apps/` 以下が登録したいアプリケーション。
`/oauth2/` 以下が、GitHubや設定ファイルに記述したcallback urlのためのもの。


## 提供サイト側の設定

name based Virtual Hostだったので、ホストへ内部IPv4アドレス1コを追加。
IP addr based Virtual Hostとした。
詳細は本記事の範囲外なので割愛。

IP addr based Virtual Hostベースの仮想サーバで起動済みであれば、とくに新たな設定は不要と思われる。


## その他

アプリ側に簡単なCGIスクリプトを置いて、どんな情報が提供されているか確認してみた。

```/apps/env.cgi
HTTP_X_FORWARDED_EMAIL => 'k2ok@your-mail.example.com',
HTTP_X_FORWARDED_FOR => '127.0.0.1',
HTTP_X_FORWARDED_HOST => 'example.com',
HTTP_X_FORWARDED_SERVER => 'example.com',
HTTP_X_FORWARDED_USER => 'k2ok',
```

`HTTP_X_FORWARDED_EMAIL` は、実際にはGitHubに登録しているメールアドレスが入る。
`HTTP_X_FORWARDED_USER` は [GitHubの登録アカウント名](https://github.com/k2ok/) と思われる。


## 感想

リバースプロクシに対する基礎知識と、OAuth2の概要くらい分かっていれば容易に導入可能に見えた。

イントラネットで数名～数十名の限られたユーザーベースであれば、十分に耐えられそう。

自身は設定だけで認証情報を待たないので、スケールさせるのも難しくなさそうだが、1インスタンスでどれくらい耐えられるかは更に評価が必要そう。
（GOのマルチスレッド性能？がどんなもんかは寡聞にして知らず）

個人としては、スマホで宅内サーバーの古いミニアプリを利用するのに利用中。（まだ稼働40日程度）