AzureWebAppのIdPでOktaを使う方法（OpenIDConnect）とアプリ側で認証情報の取得

# 概要

- AzureWebApp の IdP を使った認証で、EntraID の代わりに Okta を使用する
    - Okta 側で OpenID Connect を使うための設定
    - AzureWebApp 側で OpenID Connect を使うための設定
- AzureWebApp で IdP 認証したユーザの認証情報の取得  
（今回の例では Gradio を使用。ただし header に自動的に設定されるため、どのウェブアプリでも取得が可能）

# 準備

- 事前に AzureWebApp を作成
    - 「既定のドメイン」を Okta の設定で使用するためメモする
    - IdP 認証の確認のみの場合アプリはデプロイしてもしていなくても良い
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/b61edb89-b27f-4d77-a624-8fff6f454d24.png)

# Okta

## Okta のアカウントを作成

:::note warn
記事作成時は developer edition を使っていたが廃止されるようなので差分が発生する可能性有り
https://developer.okta.com/blog/2025/05/13/okta-developer-edition-changes#deprecating-okta-developer-edition-organizations
:::

- 下記から登録すると個人でいろいろ試せる Okta アカウントを作成出来る
    - フリーメールだと駄目らしいので私は携帯電話のキャリアメールアドレスを使用した
    - スマホに Okta Verify が必要（ログインとかでワンタイムパスワードが必要）
https://developer.okta.com/signup/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/e83b9d9b-accf-42eb-93b5-c4c3bd9b7451.png)

~~- 登録が終わったら下記からログインする
https://okta-devok12.okta.com/~~
- 下記からログインする（Okta Integrator Free Plan 後）
https://developer.okta.com/login/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/095bc51c-ec86-4347-a76f-388e4a115263.png)


## Okta にアプリを作成

- 「アプリケーション」→「アプリケーション」→「アプリ統合を作成」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/c4585286-7a33-4d12-81ff-5f88e235bbf2.png)
- 「OIDC - OpenID Connect」「Webアプリケーション」を選択して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/501eaa7e-2430-4d78-a6d8-aab4b015c31f.png)
- 今回の動作確認では以下のように設定して保存する
    - アプリ名を適当に入力
    - サインインリダイレクト URI に AzureWebApp のドメイン情報 + 「/.auth/login/testOktaIdp2/callback」を入力する
        - [アプリケーションを ID プロバイダーに登録する](https://learn.microsoft.com/ja-jp/azure/app-service/configure-authentication-provider-openid-connect#-register-your-application-with-the-identity-provider)
        - **「testOktaIdp2」の部分は後ほど AzureWebApp 側で別途設定する任意の値**  
        （Okta 側は後から変更も可能なので一旦雑に決めても良い）
    - サインアウトリダイレクト URI に AzureWebApp のドメイン情報を入力する（何も入れなくても今回の動作確認では問題無いかもしれない）
    - 「Organizationの全員にアクセスを許可」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/39f463fb-83f7-49b5-88c9-2f3052d2254c.png)
- 作成後アプリが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/992f2813-8bea-4c39-bbf1-ebe3ba666d4a.png)

## Okta アプリの必要情報を保存

- 作成した Okta アプリの「クライアントID」「クライアントシークレット」を保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/41e0ef5d-63e3-40a6-8fd4-dd72ec241853.png)
- Okta 管理画面の「カスタムドメイン」の情報に「/.well-known/openid-configuration」を付与した URI を保存
例：https://test.okta.com/.well-known/openid-configuration
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/e5e291b1-2418-4f93-9947-c25c4429afba.png)

# AzureWebApp で OpenID Connect 認証の追加

- 「ID プロバイダーを追加」を選択して「OpenID Connect」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/16e817e3-53fa-49ae-a0ec-b7c59cec7438.png)
- 今回の動作確認では以下のように設定して保存する
    - OpenID プロバイダー名に先行手順で設定した `AzureWebApp のドメイン情報 + 「/.auth/login/testOktaIdp2/callback」` の「testOktaIdp2」部分を入力
    - メタデータ URL に先行手順で保存した`Okta 管理画面の「カスタムドメイン」の情報に「/.well-known/openid-configuration」を付与した URI` を入力
    - 「クライアントID」「クライアントシークレット」にそれぞれ Okta アプリから保存した値を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/9ae96efc-551c-4f69-af16-6a7d9b2b3e41.png)
- 追加した ID プロバイダーが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/152e4b1b-ff36-491b-923b-088d43ec671d.png)
- 一度アプリを再起動しておく（不要の可能性も有り）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/39bdce59-3d8d-4171-8918-4ed5b455043a.png)

# AzureWebApp の認証の動作確認

- シークレットモードでブラウザを立ち上げ AzureWebApp の URL にアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/32b7d456-042f-4e94-8c3d-3b01bce6ac3f.png)
- 上記アクセスするとリダイレクトされて Okta の画面が出るのでログインする
    - ログインすると AzureWebApp の画面に戻る
    （Webアプリをデプロイ済みであればアプリ画面が、未デプロイの時はAzureのデフォルト画面的なものが表示される）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/8b21a0e3-fd85-4bdf-a9b8-2579298459ab.png)

# 認証したユーザの情報をアプリ側で取得

## ユーザ情報取得の概要
- AzureWebApp の IdP 認証を行った場合 header の中に認証したユーザの情報が保存されてリクエストの度に送られる
[アプリ コードでユーザー クレームにアクセスする](https://learn.microsoft.com/ja-jp/azure/app-service/configure-authentication-user-identities#access-user-claims-in-app-code)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/9516d531-eeac-4ef8-a5a3-19122408c5f7.png)

## サンプルアプリの準備

- 例として以下のような Gradio アプリをデプロイする
    - `gr.Request` の `.headers` を使ってヘッダの中身を表示する
    ```python
    import gradio as gr
    
    def main():
        def user_info(request: gr.Request):
            return request.headers
    
        with gr.Blocks() as demo:
            userinfo = gr.Textbox(interactive=True)
            demo.load(fn=user_info, inputs=None, outputs=userinfo)
        demo.launch(server_port=8000, server_name='0.0.0.0')
    
    if __name__ == "__main__":
        main()
    ```

## 確認

- デプロイ後に AzureWebApp にアクセスすると以下のように header の情報が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/cdf0d26c-1ac1-4461-93d0-0bf0e8686b7d.png)
    - `x-ms-client-principal-name` で Okta 認証時の ID （多分）が得られる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/8d482a1b-f74e-4b0b-8568-e88cb45de588.png)
    - `x-ms-client-principal` には JWT が入っている
        - デコードすると氏名やメールアドレスが入っている事が分かる
        https://jwt.io/
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/12deb436-0825-49d0-a492-c5a377bf0d4a.png)
- AzureWebApp で認証したユーザの情報をアプリ側で得る事で、チャット履歴の管理やアプリ側でのユーザごとの機能制御など便利になりそうだった
    - 今回の例では個人的に Okta を使用する必要があったので Okta を使って認証を行ったが、認証情報の取得方法については EntraID を使った場合も同様に取得が可能となる
- 今回は AzureWebApp + Okta + OpenID Connect の認証を試したので、次は AzureWebApp + Okta + SAML を使った認証も試したい（AzureWebApp サービスの機能として提供されている認証ではなく、アプリ側の制御になりそうだが）