ASP.NET CoreでIdentityServer4を使う････IdentityServer 開発ノウハウ1

# 今回のテーマ・課題
#### ASP.NET CoreのMVCアプリケーションでIdentity Server 4が起動するようにする最小限の手順を示す。
#### 参考サイト：
IdentityServerの設定と概要(https://identityserver4-ja.readthedocs.io/ja/latest/quickstarts/0_overview.html#)


## 1. ソリューションとプロジェクトの構成

|ソリューション名|目的|
|---|---|
|IS4QuickStart|IdentityServerのトライアルプロジェクトを統合するソリューション|

|プロジェクト名|目的|
|---|---|
|QS01_SettingUpIdentityServer|最初に作成するIdentityServerを使用したASP.NET Coreプロジェクト|

## 2. QS01_SettingUpIdentityServerの作成手順

1. ASP.NET Core の空のWebアプリケーションとして作成する。
2. Nuget Package ManagerでIdentity Server 4をインストールする。
  ("Install-Package IdentityServer4" ･･･ Nuget Package Console)
3. Startupの変更

```C#
// ･･･
using IdentityServer4.Models;

namespace QS01_SettingUpIdentityServer
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // IdentityServerをサービスとして追加する。
            // ※）注意事項
            // AddInMemoryClientsとAddInMemoryIdentityResourcesの2つのメソッドも指定する。
             services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryClients(new List<Client>())
                .AddInMemoryIdentityResources(new List<IdentityResource>());
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            // IdentityServerをミドルウェアとして登録
            app.UseIdentityServer();
            app.UseRouting();
            // ･･･
    }
}

```

### 注意事項
参考サイトでは、ConfigureServicesのコードは  
services.AddIdentityServer().AddDeveloperSigningCredential();  
までしか書いていないがこれだと、Program.Main()の  
CreateHostBuilder(args).Build().Run();で以下の例外がスローされConfigureに進まない！
```
InvalidOperationException: Unable to resolve service for type 'IdentityServer4.Stores.IClientStore'  v
  while attempting to activate 'IdentityServer4.Services.LogoutNotificationService'.
```

## 3．ホスティングの変更
IdentityServerはコンソールホストで実行してログの出力内容を常時チェックできるようにしておく。  
それをやるためにはプロジェクトのプロパティー|デバッグでプロファイルをIISExpressではなくプロジェクト本体にする。

![QS01_SettingUpIdentityServerのプロパティ|デバッグ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583684/b9439a4d-1b10-960a-7265-e896a0794820.jpeg)

### 注釈
1. IIS Expressと自己ホスティングに同じポートを設定すること。この方法で、クライアントの設定を変更することなく、2つの間で切り替えることができる。  

2. 起動時にコンソールホストを選択するには、Visual Studioの起動メニューでコンソールホストを選択する。

<hr />
## Gitから複製したサンプルコードの実行について

### 問題点(1)
クローンしたばかりのソリューションを開いてパッケージの復元をしようとすると  
>重大度レベル：エラー
コード：NETSDK1004
説明：資産ファイル'C:\Users\雅俊\Source\Repos\TrailRunner-MF\IdentityServer\samples\Quickstarts\1_ClientCredentials\src\IdentityServer\obj\project.assets.json'が見つかりません。 NuGet パッケージの復元を実行して、このファイルを生成してください。

のようなエラーが出て先に進めなくなる場合がある。
* 実際のプログラム･･･https://github.com/IdentityServer/IdentityServer4/tree/main/samples/Quickstarts/1_ClientCredentials

解決法は以下の通り。

1. Visual Studio >>ツール>>オプション>> Nuget Manager >>パッケージソース
2. サードパーティのパッケージソースのチェックを外しました。
3. ソリューションを再構築します。

![ツール|オプションメニューのNugetパッケージマネージャ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583684/7b06d5b4-45df-757a-0867-e154eb695d73.jpeg)

## 問題点(2)
GitHubから取ってきたQuickStartのソリューションは、Clientをスタートアッププロジェクトに指定してデバッグ開始してもちゃんと動かない。
必ずClient(=コンソールアプリケーション)のProgramクラスのMainメソッドの以下の箇所でエラーになってしまう。

```C#
namespace Client
{
    public class Program
    {
        private static async Task Main()
        {
            // discover endpoints from metadata
            var client = new HttpClient();

            var disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001"); // **ここ**
            if (disco.IsError)     // **かららずえらーになってしまう。**
            {
                Console.WriteLine(disco.Error); 
                return;
            }
        ････
```

### 解決方法
ソリューションを「マルチスタートアッププロジェクト」に指定する。
やり方は以下の通り。
1. ソリューションエクスプローラで最上位ノードのソリューションを選択した状態でコンテキストメニューを開き、プロパティーを開く。
2. マルチスタートアップを指定して、起動順序を入れ替え、アクションをそれぞれ「開始」に指定する。
![ソリューションのプロパティーダイアログ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583684/0c6ed82a-6544-c011-258f-33cbbc4c49b5.jpeg)

こうすればIdentityServer/Apiが起動したうえでClientが起動し、上述のclient.GetDiscoveryDocumentAsyncメソッドは成功しプログラムは継続する。
![IdentityServer/Apiが起動したうえでClientが起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583684/7002bf27-44c3-f6d5-a581-e2acbf458771.png)

<hr />
## ノウハウ
IdentityServer, Apiそれぞれに割り振られているIISExpress起動用のポート番号は、実行マシンで他の常駐プログラム（＝サービス）等で使用されていなければ、他のIISExpressでテストするソリューション内のWebアプリケーションとダブっても問題ない。
### 例
* ソリューションAのWebアプリケーションプロジェクトa-1がhttp://localhost:5001を使用する。

* ソリューションBのWebアプリケーションプロジェクトb-1もhttp://localhost:5001を使用する。

このときVisual Studiioが1つしか起動していなくてソリューションA/Bいずれか一方だけを実行していれば全然問題ない。
仮に2つ起動していてそれぞれソリューションA/Bを開いても、同時にデバッグ（またはデバッグなしで）開始しない限りお互いへの干渉はない。