RaspberryPi上のサイトにAzure AD認証経由でログインしてみる。

自宅にRaspberryPiが2台(3B+とZero)あり、どっちも火を落として久しかったので復活させました。
1年近く触ってなかったので何を設定していたか忘れていました。
3B+は照度センサー、気温、気圧、湿度センサー、カメラを付けています。
照度センサー、気温、気圧、湿度センサー、は会社のMSDNで使えるAzure IoT Hubに各データをリアルタイムで出力し、Power BIでこれもリアルタイムにグラフが流れる設定にしているのですが、いったんここは省きます。
ZeroはiPhoneのSiriと連携して、「Hey Siri!寝室の電気付けて！」というとZeroに付けたLEDから照明の電気を操作できます。
これも省いて、今回の記事では3B+のカメラについてです。
カメラは照度などの各種センサーと一緒に映像データをリアルタイムにYou Tubeに送信する機能も付けており、普段は停止しています。
現在は3B+上にWebサーバを立ててphpでこのサイトにアクセスされたら自動でカメラを起動しカメラの映像をサイトにリアルタイムで流す、という仕組みのみで動いています。
元々ネットワークエンジニアなので、自宅へスマホ(iPhone)からVPNを張れるようにしており、iPhoneからいつでも自宅の様子を確認できる仕組みです。

### ■きっかけ
勿論自宅内の3B+と同じネットワーク内でもアクセス可能で、インターネットに公開することもできるのですがこれはやっていません。
いくら宅内やVPN経由のみとはいえ、認証なしにサイトにアクセス可能でカメラが自動起動するのは如何なものかと思い(自分で設計しといてなんですが・・・)Basic認証やダイジェスト認証を実装しましたが、それでも面白くないです。
日頃仕事で使っているAzure AD認証が使えたらカッコいいな、多要素認証なんて使えた日にはもっとカッコいいなというなんともつまらない思い付きからスタートした試みです。
結果多要素認証はライセンスの関係で実装できてないですが、ID、パスワードによるAzure AD認証は実装できております。

### ■前提条件
１．RaspberryPi3B+にWebサーバが構築されている。
２．自由に使えるAzure ADがある。

### ■設定
###１．Azure ADに認証用アプリケーションを登録する。
ブラウザに打ち慣れたURL、「portal.azure.com」と入力し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/9e7911ca-7069-846d-a82d-1b3d55593163.png)

Azure AD全体管理者権限を持つユーザでログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/0e7f7307-027e-d9bb-25e5-83107e495d48.png)

そして多要素認証聞いてきます。
ここでは電話番号認証にしているのでSMSが飛んできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/caab8ffc-049b-ccc4-ea3a-fc259bed8876.png)

私はポータルメニューをドッキングにしていて順序も最上位から2番目にAzure Active Directoryと決めているのでこの並びです。
赤枠の[Azure Active Directory]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/4618d78e-15ac-2591-cb41-98eeac19260c.png)

アプリの登録を行います。
これはRaspberryPiにログインするために認証が行われる際、RaspberryPiからAzure ADに「認証情報頂戴」って聞きに行くWeb APIです。
このアプリケーションの登録が行われて認証情報のやり取りをRaspberryPiと行うAzure AD側の窓口ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/1b10bf35-305a-80d2-e409-88196d13c187.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/ca951449-c494-34d2-c48e-c1e36ddbb61c.png)


ここで大事なのは
[このアプリケーションを使用したりこのAPIにアクセスしたりできるのはだれですか？]
と
[リダイレクトURL(省略可能)]
の2点です。
どちらの値も後から変更可能です。
必須パラメータは名前ですが、これはAzure AD内のアプリの識別子程度の認識で大丈夫です。
Azure AD認証に絡む設定パラメータではないです。
[このアプリ～]
のラジオボタンは自身のAzure ADのみを認証対象にするか、ほかのAzure ADで認証されたものも認証対象にするか、という内容です。
Azure AD認証をかけた後、アクセスさせるアプリが社内専用のものだと最上位、他の会社のAzure AD認証でも、とにかくAzure AD認証がかかっていればOKだよということであれば真ん中、個人アカウント(これはAzure ADアカウントが組織か、個人か、の違いの意味)でもAzure AD認証がかかっていればOKだよ、という意味です。
今回は最上位です。
[リダイレクトURL(省略可能)]はAzure AD認証後にクライアントのブラウザに返したいURLです。
今回はローカルアプリなので、https://192.168.~.~にしました。
ここは一度デプロイすると複数入力することができるようになり、検証で自宅内のアプリを一瞬だけインターネットに公開したんですが、宅内からは192～、インターネット経由ではFQDN、ときちんと両方とも動作してくれました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/730980c9-2b1a-af9a-607e-b26de5870314.png)


デプロイが完了するとアプリケーションができました！
ここで大事なのはテナントIDとアプリケーション(クライアント)IDとシークレット
シークレットは後から登録するのですが、アプリケーション(クライアント)IDはここに表示があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/66114df6-2665-98d0-8a72-95e98f290037.png)

テナントIDはAzure AD認証画面URLのオプションで付与することで目的のテナント目指してログインできるオプションみたいな値なのですが、これをRapsberryPiからリダイレクト先にしているすることでどのテナントでもOKなAzure AD画面から、自分のテナントのみに認証をかけることができるようになります。
先ほどのアプリケーション(クライアント)IDもこの画面から確認可能ですので、テナントIDと合わせてメモしておきましょう。
続いて
[証明書とシークレット]
をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/fa59324c-14c5-839d-c3ca-7f7fc2180a01.png)

ここではシークレットを作成します。
[＋新しいクライアント シークレット]をクリックします。
有効期限を聞かれるので、お好きな年数をラジオボタンで選択します。
<font color="Red">この後出てくるシークレットは一度きりしか表示されませんので、必ずメモしてください。</font>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/b4a9d2c7-2459-0437-71e5-3b766874c721.png)

ここまでの手順で取得したアプリケーション(クライアント)IDとシークレットはセットで管理し、手順３.のOpen IDのConfファイル内に設定します。
これがいわゆるWeb APIのURIとAPIキーになります。
Azure ADに対するOpen IDって実はこれらのテナントIDやアプリケーション(クライアント)IDを使って一意のAzure AD認証用URLを生成して、APIキーを使ってAzure ADとセキュアなセッションを確立してるだけっぽいです。
で、確立したセッション内をID、パスワードではなくて認証の可否のみが流れる、という構造のようです。

###２．Raspberry PiにOpen IDをインストールする。
aptコマンドで一発です。

```shell
sudo apt-get install -y libapache2-mod-auth-openidc
```

###３．Open IDのConfファイルを設定する
基本的には既に手順１．で記載済みですが、Azure ADのテナントIDとクライアント(アプリケーション)ID、シークレットキーが肝でが、Azure ADに登録したアプリ―ケーションを選択し、以下の画面にある
[エンドポイント]
をクリックすると出てくる
[OpenID Connect メタデータ ドキュメント]
と
[OAuth 2.0 承認エンドポイント (v2)]
と
[OAuth 2.0 トークン エンドポイント (v2)]
もメモしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/67c79a04-1d33-dbdf-0166-29e25ac36b7f.png)

そしてこれらをOpenIDのConfファイルの該当の部分に入力します。
対応表としては

| Azure AD エンドポイントの表記            | Open IDのConfファイル内の設定値     |
|:---------------------------------------|:----------------------------------|
| OpenID Connect メタデータ ドキュメント   | OIDCProviderMetadataURL           |
| OAuth 2.0 承認エンドポイント (v2)        | OIDCProviderAuthorizationEndpoint |
| OAuth 2.0 トークン エンドポイント (v2)   | OIDCProviderTokenEndpoint         |

となっています。
またOpenIDをAzure AD認証で使う場合の固定の値があります。
これは以下の通り設定してください。

```
OIDCResponseType "code"

OIDCScope "openid"

OIDCPKCEMethod S256

OIDCAuthRequestParams prompt=consent
```

[OIDCResponseType "code"]はOpen ID ConnectへAzure ADがAPI認証を行った後、どのような形式でレスポンスを返してくるか、だと思います。
ここでid_tokenやtokenなど、複数選択することも可能ですがここではcodeを選択します。

[OIDCScope]はOpen ID ConnectのScopeを指定します。
openid以外にもemailやprofileも選択可能ですが、ここではopenidを選択します。

[OIDCPKCEMethod]はPlainとS256が選択でき、Azure ADとの認証情報のやりとりを平文(Plain)で行うかSHA256でハッシュ化して行うか、という意味でしょう。
S256を選択します。

[OIDCAuthRequestParams]はリクエストのパラメータをエンコードして通信するかのパラメータです。
prompt=consnt(同意)としましょう。

続いて公開したいアプリケーションに依存する設定値です。
OpenIDのConfファイルの前半に偏っています。


```
OIDCRedirectURI

OIDCCryptoPassphrase
```
[OIDCRedirectURI]は認証後に表示させたいURLです。
Azure ADのアプリケーションのリダイレクトURLと同じ値にしましょう。
[OIDCCryptoPassphrase]はOpne ID ConnectのCookieセッションを暗号化するのに利用するパスフレーズです。
ここ以外どこか別のパラメータと合わせないといけない、ということはありません。
ここだけで使うパラメータです。

###４．Webサーバでリダイレクト設定を行う
本当はOpen IDのConfファイルの設定通りにAzure AD＋テナントIDの画面に自動でリダイレクトされるはずなのですが、私の環境ではうまく動かなかったので苦肉の策でRaspberryPiのWeb画面にアクセスしたらAzure AD＋テナントID画面にリダイレクトされるようにしました。
私のRaspberryPiでは

/etc/apache2/sites-available/000-default.conf
に以下のように記載しました。

```shell:/etc/apache2/sites-available/000-default.conf
        RewriteEngine on
        RewriteCond %{REQUEST_URI} ^.*$
        RewriteRule ^/(.*)$ https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=アプリケーション(クライアント)ID&scope=openid
```

これだけです。
~~図とかなくてごめんなさい。~~
~~Qiita初めてなので図解のやり方がわからないです。~~
~~コマンドも作業ログとってあるので探して記載します。~~

~~まずは書くことが大事かなと思うので6割程度の完成度ですが、アップします。~~

これで完成ですかね。
OpneIDのConfigファイルの解釈とか間違えてたらごめんなさい。
お手数ですがご指摘頂ければ修正致します。
次回はAzure関係無いですが、同じくRaspberry PiにAsterisk入れてSoftbank光の光電話をiPhoneで受けれるようにしたので、これにしようと思います。
3桁の特殊番号発信に少し手間取りましたが、面白かったのとNTTのひかり電話(NTTはこれが商標)しか記事がなく、Softbankの光電話(Softbankはこれが商標)の記事を一切見なかったので、誰かの何かの参考になれば、という意味で書こうと思います。

今回はここまで。