apacheの基本認証設定とmod_wsgiを通じてflaskに認証情報を渡す

## 背景
今MacOSで開発しているflaskアプリはapache基本認証が必要です。そして、ユーザを管理するために認証情報をflaskに渡さなければならないという状況です。
認証情報のユーザ名はデフォルトで渡されるので何もしなくてもいいですが、パスワードも欲しいなら以下の記事が参考になれるかもしれません。
### 実行環境：
macOS -> Ventura 13.4
Apache -> 2.4.54
Python -> 3.10.11
pip3 -> 23.1.2
flask -> 2.3.2

## 用意
apacheからの認証情報を確認するために、環境変数を出力するflaskアプリが必要です。
環境設定とwsgiファイルは私の前の記事と同じです。
https://qiita.com/pabitele/items/6aa9269bd3109fee4806

hello.py
```
from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def display_env():
    env_vars = ""
    for key, value in request.environ.items():
        env_vars += f"{key}: {value}<br>"
    return env_vars

if __name__ == '__main__':
    app.run()
```
これは環境変数を一行ずつ出力するflaskアプリです。
## 設定ファイルの中身
まず設定ファイルの中身を見てみましょう。
```
<VirtualHost *:80>
    LoadModule wsgi_module /Users/rikanshin/.local/lib/python3.10/site-packages/mod_wsgi/server/mod_wsgi-py310.cpython-310-darwin.so "test"
    WSGIScriptAlias / /Users/rikanshin/Desktop/flask/myapp/test.wsgi
    WSGIPassAuthorization On
    <Directory /Users/rikanshin/Desktop/flask/myapp>
        Require all granted
    </Directory>
    <Location / >
        AuthType Basic
        AuthName "test basic auth"
        AuthUserFile "/etc/apache2/basic-auth/passwords"
        Require valid-user
    </Location>
</VirtualHost>
```

## 基本認証の設定
\<Location\>の中身は基本認証設定です。
*Location*の後は基本認証の適用範囲です。
*AuthType*は認証の種類、それを基本認証を指定します。
*AuthName*認証ダイアログのプロンプト情報を設定するためのディレクティブです。
*AuthUserFile*の後はユーザ名とパスワードのファイルのパスです。(後で作ります)
*Require valid-user*は認証成功したユーザだけアクセスできるという設定です。


まずユーザ名とパスワードのアカウントファイルを作りましょう。
ファイルの置く場所に移動して(私の場合は /etc/apache2/basic-auth)
```
htpasswd -c passwords(アカウントファイル名) test1(新規ユーザ名)
```
でファイルと最初のユーザを作ります。
次のようなものが出るはずです。
```
New password: 
Re-type new password: 
Adding password for user test1
```
二番目のユーザから次のコマンドでアカウントを作ります。
```
sudo htpasswd passwords(アカウントファイル名) test2(新規ユーザ名)
```
最後は
```
apachectl -t
```
でSyntax OKが出たらOK。
念の為サイトにアクセスして認証画面でログインして確認しましょう。

## 認証情報を渡す
**もしユーザ名だけ欲しいなら以下のことをやらなくてもいいです。**
**環境変数のREMOTE_USERの値を参照することでOKです。**

例の設定ファイルで
```
WSGIPassAuthorization On
```
という行があります。これは認証情報をwsgiアプリケーションに渡すための設定です。
詳細は以下となります。[^1]

>User Authentication
As is the case when using CGI scripts with Apache, authorisation headers are not passed through to WSGI applications. This is the case, as doing so could leak information about passwords through to a WSGI application which should not be able to see them when Apache is performing authorisation.
Unlike CGI scripts however, when using mod_wsgi, the WSGIPassAuthorization directive can be used to control whether HTTP authorisation headers are passed through to a WSGI application in the HTTP_AUTHORIZATION variable of the WSGI application environment when the equivalent HTTP request headers are present. This option would need to be set to On if the WSGI application was to handle authorisation rather than Apache doing it:
WSGIPassAuthorization On
If Apache is performing authorisation and not the WSGI application, a WSGI application can still find out what type of authorisation scheme was used by checking the variable AUTH_TYPE of the WSGI application environment. The login name of the authorised user can be determined by checking the variable REMOTE_USER.

WSGIPassAuthorization On　を設定したら、用意したflaskアプリにアクセスすると
![スクリーンショット 2023-06-16 12.40.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2848485/e9aefa22-f003-315c-7fa9-a03a9f770709.png)
のような環境変数があるはずです。

そもそもあるもの:
*REMOTE_USER* はユーザ名
*AUTH_TYPE* は認証種類

WSGIPassAuthorization Onで渡されるもの:
*HTTP_AUTHORIZATION* は認証種類と"ユーザ名:パスワード"という文字列をbase64でエンコードしたものです。

ここは例としてユーザはtest1でパスワードはabcです。検証してみましょう。
```
> echo 'dGVzdDE6YWJj'| base64 -D                                        
test1:abc
```
これで認証情報を渡すことができました。(パスワードを含めて)。

## まとめ
今回apacheの基本認証の設定と認証情報をflaskに渡す方法を記録しました。
お疲れ様でした。

[^1]:参照先:https://modwsgi.readthedocs.io/en/master/user-guides/configuration-guidelines.html