ようこそ! IdentityServer4

_images/logo.png

IdentityServer4は、ASP.NET Core 2用のOpenID ConnectおよびOAuth 2.0フレームワークです。

これにより、アプリケーションで次の機能が有効になります。:

  • Authentication as a Service: すべてのアプリケーション (web、ネイティブ、モバイル、サービス) のための集中ログインロジックとワークフロー。IdentityServer は、正式に 認定された OpenID Connect の実装です。
  • Single Sign-on / Sign-out: 複数のアプリケーションタイプに対してシングルサインオン (およびシングルアウト)。
  • Access Control for APIs: さまざまなタイプのクライアントのAPIのアクセストークンを発行します(例: サーバー間、Webアプリケーション、SPA、およびネイティブ/モバイルのアプリ。
  • Federation Gateway: Azure Active Directory、Google、Facebookなどの外部IDプロバイダをサポートしているため、これらの外部プロバイダへの接続方法の詳細からアプリケーションを保護することができます。
  • Focus on Customization: 最も重要な部分 - IdentityServerの多くの側面は、 お客様 のニーズに合わせてカスタマイズできます。 IdentityServerはフレームワークであり、箱入りの製品やSaaSではないので、シナリオに合った方法でシステムを適応させるためのコードを書くことができます。
  • Mature Open Source: IdentityServerは商用製品の構築を可能にする許可的な Apache 2 ライセンスを使用しています。 ガバナンスと法的支援を提供する .NET Foundation の一部です。
  • Free and Commercial Support: Identity platformの構築や実行に役立つ必要がある場合は、当社にご連絡ください 。 私たちがあなたを助けるいくつかの方法があります。

The Big Picture

最近のアプリケーションのほとんどは、このように見えます。:

_images/appArch.png

最も一般的な相互作用は次のとおりです。:

  • ブラウザはウェブアプリケーションと通信する
  • WebアプリケーションはWeb APIと通信します(時には、ユーザー自身のために、時にはユーザーのために)
  • ブラウザベースのアプリケーションはWeb APIと通信します
  • ネイティブアプリケーションはWeb APIと通信します
  • サーバーベースのアプリケーションがWeb APIと通信する
  • Web APIはWeb APIと通信します(時には、ユーザー自身のために、時にはユーザーのために)

通常、各層(フロントエンド、ミドルエンド、バックエンド)は、リソースを保護し、認証や認可を実装する必要があります。

これらの基本セキュリティー機能をセキュリティー・トークン・サービスにアウトソーシングすると、それらのアプリケーションとエンドポイント間でその機能が重複することはありません。

セキュリティトークンサービスをサポートするようにアプリケーションを再構築すると、次のアーキテクチャとプロトコルが使用されます。:

_images/protocols.png

このような設計は、セキュリティ上の懸念を2つの部分に分けます。:

認証

アプリケーションが現在のユーザーの身元を知る必要がある場合、認証が必要です。通常、これらのアプリケーションはそのユーザーに代わってデータを管理し、このユーザーが許可されているデータにのみアクセスできるようにする必要があります。そのための最も一般的な例は、(古典的な)Webアプリケーションですが、ネイティブおよびJSベースのアプリケーションでも認証が必要です。

最も一般的な認証プロトコルは、SAML2p、WS-Federation、OpenID Connectです。SA​​ML2pが最も普及し、最も広く普及しています。

OpenID Connectは3つのうち最新のものですが、現代的なアプリケーションの可能性が最も高いため、将来のものと考えられています。当初からモバイルアプリケーションのシナリオ用に開発されたもので、APIに対応するように設計されています。

APIアクセス

アプリケーションには、アプリケーションIDを使用するか、またはユーザーのIDを委任する、APIと通信する2つの基本的な方法があります。場合によっては、両方の方法を組み合わせる必要があります。

OAuth2は、アプリケーションがセキュリティトークンサービスからのアクセストークンを要求し、それらを使用してAPIと通信できるようにするプロトコルです。この委任により、認証と承認を一元化できるため、クライアントアプリケーションとAPIの両方の複雑さが軽減されます。

OpenID ConnectとOAuth 2.0 - より良い連携

OpenID ConnectとOAuth 2.0は非常によく似ています - 実際、OpenID ConnectはOAuth 2.0の上に拡張されています。基本的なセキュリティ上の2つの懸念事項、認証とAPIアクセスは、1つのプロトコルに統合されます。セキュリティトークンサービスへの1回のラウンドトリップが頻繁に行われます。

OpenID ConnectとOAuth 2.0の組み合わせは、近い将来、最新のアプリケーションを保護するための最良のアプローチだと考えています。IdentityServer4は、これら2つのプロトコルの実装であり、今日のモバイル、ネイティブ、およびWebアプリケーションの典型的なセキュリティ問題を解決するために高度に最適化されています。

IdentityServer4がどのように役立つか

IdentityServerは、仕様準拠のOpenID ConnectおよびOAuth 2.0エンドポイントを任意のASP.NET Coreアプリケーションに追加するミドルウェアです。

通常、ログインとログアウト・ページを含むアプリケーションを構築(または再利用)します(必要に応じて合意することもできます)。IdentityServerミドルウェアは、クライアント・アプリケーションがそれに対話できるように、必要なプロトコル・ヘッドを追加しますそれらの標準プロトコルを使用しています。

_images/middleware.png

ホスティングアプリケーションは、必要なだけ複雑にすることができますが、認証関連のUIだけを含めることで、攻撃の可能性をできるだけ小さくすることをお勧めします。

用語集

仕様、ドキュメンテーション、およびオブジェクトモデルでは、注意すべき用語を使用します。

_images/terminology.png

IdentityServer

IdentityServerはOpenID Connectプロバイダであり、OpenID ConnectとOAuth 2.0プロトコルを実装しています。

異なる文献では、同じ役割に対して異なる用語が使用されています。セキュリティトークンサービス、アイデンティティプロバイダ、認可サーバ、IP-STSなどがあります。

しかし、彼らは一言で言えば、クライアントにセキュリティトークンを発行するソフトウェアです。

IdentityServerには、次のような多くのジョブと機能があります。:

  • あなたのリソースを保護する
  • ローカルのアカウントストアを使用してユーザーを認証するか、外部のIDプロバイダを使用してユーザーを認証する
  • セッション管理とシングルサインオンを提供する
  • クライアントの管理と認証
  • IDとアクセストークンをクライアントに発行する
  • トークンを検証する

User

ユーザーは、登録されたクライアントを使用してリソースにアクセスしている人間です。

Client

クライアントとは、ユーザーの認証(IDトークンの要求)またはリソースへのアクセス(アクセストークンの要求)のためにIdentityServerからトークンを要求するソフトウェアのことです。トークンを要求する前に、まずクライアントをIdentityServerに登録する必要があります。

クライアントの例としては、Webアプリケーション、ネイティブモバイルアプリケーションまたはデスクトップアプリケーション、SPA、サーバープロセスなどがあります。

Resources

リソースとは、ユーザーのIDデータやAPIのいずれかをIdentityServerで保護したいものです。

すべてのリソースには一意の名前があります。クライアントはこの名前を使用して、アクセスするリソースを指定します。

identity data ユーザに関するアイデンティティ情報(別名:クレーム)、例えば名前または電子メールアドレス。

APIs APIリソースは、クライアントが呼び出そうとする機能を表します。通常、Web APIとしてモデル化されていますが、必ずしもそうではありません。

Identity Token

アイデンティティトークンは、認証プロセスの結果を表します。これには、ユーザの識別子(sub aka subject claim と呼ばれる)と、ユーザがいつ、どのように認証されたかに関する情報が最低限含まれています。追加のIDデータを含めることができます。

Access Token

アクセストークンを使用すると、APIリソースにアクセスできます。クライアントはアクセストークンを要求し、それらをAPIに転送します。アクセストークンには、クライアントとユーザーに関する情報(存在する場合)が含まれます。APIはその情報を使用してデータへのアクセスを許可します。

サポートされる仕様

IdentityServerは次の仕様を実装しています:

OpenID Connect

  • OpenID Connect Core 1.0 (spec)
  • OpenID Connect Discovery 1.0 (spec)
  • OpenID Connect Session Management 1.0 - draft 28 (spec)
  • OpenID Connect Front-Channel Logout 1.0 - draft 02 (spec)
  • OpenID Connect Back-Channel Logout 1.0 - draft 04 (spec)

OAuth 2.0

  • OAuth 2.0 (RFC 6749)
  • OAuth 2.0 Bearer Token Usage (RFC 6750)
  • OAuth 2.0 Multiple Response Types (spec)
  • OAuth 2.0 Form Post Response Mode (spec)
  • OAuth 2.0 Token Revocation (RFC 7009)
  • OAuth 2.0 Token Introspection (RFC 7662)
  • Proof Key for Code Exchange (RFC 7636)
  • JSON Web Tokens for Client Authentication (RFC 7523)

パッケージングとビルド

IdentityServerは多数のナゲットパッケージで構成されています。

IdentityServer4

nuget | github

コアIdentityServerオブジェクトモデル、サービス、およびミドルウェアが含まれています。インメモリ構成とユーザーストアのサポートのみが含まれていますが、構成を介して他のストアのサポートをプラグインできます。これは、他のリポジトリとパッケージについてです。

Quickstart UI

github

ログイン、ログアウト、同意ページなどの簡単なUIが含まれています。

Access token validation handler

nuget | github

APIのトークンを検証するためのASP.NET core 認証ハンドラ。ハンドラは、同じAPI内でJWTトークンと参照トークンの両方をサポートすることができます。

ASP.NET Core Identity

nuget | github

IdentityServer用のASP.NET Core Identity統合パッケージ。このパッケージは、IdentityServerユーザーにASP.NET ID管理ライブラリを使用するためのシンプルな構成APIを提供します。

EntityFramework Core

nuget | github

EntityFramework IdentityServerのコアストレージ実装。このパッケージは、IdentityServerの構成ストアと運用ストアのためのEntityFramework実装を提供します。

Dev builds

さらに私たちはMyGetに dev/interim ビルドを公開しています。試してみたい場合は、次のフィードをVisual Studioに追加してください:

https://www.myget.org/F/identity/

サポートとコンサルティングのオプション

IdentityServerには、いくつかの無料で商業的なサポートとコンサルティングのオプションがあります。

無償サポート

無料のサポートはコミュニティベースで、パブリックフォーラムを使用しています

StackOverflow

StackOverflowに関する質問を監視するIdentityServerを使用する人が増え続けています。 時間が許せば、可能な限り多くの質問にも答えようとします

このフィードを使用して、すべてのIdentityServer4関連の質問に登録することができます。:

https://stackoverflow.com/questions/tagged/?tagnames=identityserver4&sort=newest

新しい質問をするときに IdentityServer4 タグを使用してください

Gitter

Gitterチャットルームの他のIdentityServer4ユーザとチャットすることができます:

https://gitter.im/IdentityServer/IdentityServer4

Reporting a bug

バグや予期しない動作が見つかったと思われる場合は、Githubで 問題 を開いてください。 私たちはできるだけ早くあなたにお返しをしようとします。 私たちも日々仕事をしていることを理解してください。また、忙しくてすぐに返信することはできません。

また、投稿する前に 指針 もチェックしてください。

商用サポート

私たちは、アイデンティティ&アクセス制御アーキテクチャー、特にIdentityServer、特にIdentityServerのコンサルティング、メンタリング、カスタムソフトウェア開発を行っています。 可能なオプションについて議論するために、 私たちと 連絡してください。

Training

私たちは定期的に最新のアプリケーションのためのアイデンティティとアクセス制御に関するワークショップを行っています。 議題や今後開催される公開日程は こちら をご覧ください。私たちはあなたの会社で個人的に訓練を行うこともできます。 現場でのトレーニングを依頼するには、お問い合わせください

Admin UI, Identity Express and SAML2p support

当社のパートナーから市販されているいくつかのアドオン製品があります。https://www.identityserver.com/products/をご確認ください。

デモサーバとテスト

あなたのお気に入りのクライアントライブラリでIdentityServer4を試すことができます。私たちは demo.identityserver.io にテストインスタンスを持っています。メインページには、クライアントの設定方法とAPIの呼び出し方法が記載されています。

さらに、さまざまなIdentityServerとWeb APIの組み合わせ(IdentityServer 3と4、ASP.NET CoreとKatana)を実行するレポがあります。このテスト・ハーネスを使用して、すべての順列が機能することを確認します。 この リポジトリを複製することで、自分でテストすることができます。

貢献する

私たちはコミュニティの貢献には非常にオープンですが、あまり努力することなくこれを処理できるようにするためのガイドラインがいくつかあります。

貢献する方法?

貢献する最も簡単な方法は、問題を開いてディスカッションを開始することです。次に、機能や変更を実装できるかどうか、どのように実装するかを決定できます。コードの変更を伴うプルリクエストを提出する必要がある場合は、説明から始めて、最小限の変更を開始し、その変更をカバーするテストを提供してください。

これも最初に読んでください:Being a good open source citizen

一般的なフィードバックとディスカッション

core repo issue tracker に関するディスカッションを開始してください。

プラットフォーム

IdentityServerはASP.NET Core 2に対して構築され、.NET Framework 4.6.1(以上)および.NET Core 2(以上)で動作します。

バグや機能要求?

適切なGitHubリポジトリに新しい問題を記録してください:

貢献するコードとコンテンツ

コードやコンテンツを提供する前に、コントリビュータライセンス契約に署名する必要があります。これは、プルリクエストを開いた後に開始される自動プロセスです。

注釈

私たちはdevブランチに対してのみPRを受け付けます。

貢献プロジェクト

貢献プロジェクトを開始すると非常に感謝します(例えば、データベースXまたは構成ストアYのサポート)。それについて私達に教えてください。

私たちは一般的に、これらの寄付図書館の所有権を奪いたくないので、私たちはすでにコアプロジェクトのサポートに忙しいです。

命名規則

2017年10月現在、IdentityServer4。* nuget名前空間はパッケージ用に予約されています。次の命名規則を使用してください:

YourProjectName.IdentityServer4

または

IdentityServer4.Contrib.YourProjectName

セットアップと概要

新しいIdentityServerプロジェクトを開始するには、基本的に2つの方法があります。:

  • ゼロから始めます
  • Visual StudioでASP.NET IDテンプレートを使い始める

「ゼロから始めます」から始めれば、いくつかのヘルパーとメモリ内のストアが提供されるので、最初から永続性について心配する必要はありません。

ASP.NET Identityを使い始めると、簡単に統合することができます。

クイックスタートは、さまざまな一般的なIdentityServerシナリオのためのステップバイステップの指示を提供します。彼らは絶対的な基本から始まり、より複雑になります - あなたがそれらを順番に行うことが推奨されます。

すべてのクイックスタートには参照ソリューションがあります。このコード は、quickstartsフォルダの IdentityServer4.Samples リポジトリにあります。

基本設定

スクリーンショットにはVisual Studioが表示されます。 - これは必須条件ではありません。

Creating the quickstart IdentityServer

まず、新しいASP.NET coreプロジェクトを作成します。

_images/0_new_web_project.png

「Empty」オプションを選択します。

_images/0_empty_web.png

次に、 IdentityServer4 nuget パッケージを追加します。:

_images/0_nuget.png

別の方法として、パッケージマネージャコンソールを使用して、次のコマンドを実行して依存関係を追加することもできます。:

"Install-Package IdentityServer4"

注釈

IdentityServerビルド番号1.xターゲットASP.NETコア1.1、およびアイデンティティサーバービルド番号2.xはASP.NETコア2.0をターゲットとしています。

IdentityServerは、通常のパターンを使用してASP.NETコアホストにサービスを設定し、追加します。 ConfigureServices 必要なサービス構成され、DIシステムに加え。では Configure ミドルウェアHTTPパイプラインに追加されます。

Startup.cs ファイルを次のように変更します。:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentityServer()
            .AddDeveloperSigningCredential();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseIdentityServer();
    }
}

AddIdentityServer DIにIdentityServerサービスを登録します。また、実行時状態のインメモリ・ストアも登録します。これは開発シナリオに役立ちます。実動シナリオでは、データベースまたはキャッシュのような永続ストアまたは共有ストアが必要です。詳細については、 EntityFramework のクイックスタートを参照してください。

AddDeveloperSigningCredential拡張子は、署名トークンのための一時的なキーマテリアルを作成します。これはやり直すのにも役立つかもしれませんが、実動シナリオのためのいくつかの永続的なキーマテリアルに置き換える必要があります。詳細については、cryptography docs のドキュメントを参照してください。

注釈

IdentityServerはまだ起動する準備ができていません。以下のクイックスタートで必要なサービスを追加します。

ホスティングの変更

既定では、Visual StudioはIIS Expressを使用してWebプロジェクトをホストします。コンソールにリアルタイムのログ出力を見ることができないことを除いて、これはまったく問題ありません。

IdentityServerはロギングを大量に使用しますが、UIの「表示可能な」エラーメッセージまたはクライアントに返されるエラーメッセージは意図的に曖昧です。

コンソールホストでIdentityServerを実行することをお勧めします。これは、Visual Studioで起動プロファイルを切り替えることで実行できます。また、IdentityServerを起動するたびにブラウザを起動する必要はありません。これをオフにすることもできます。:

_images/0_launch_profile.png

さらに、これらのクイックスタートの一貫したURLでIdentityServerを実行すると便利です。また、上記の起動プロファイルダイアログでこのURLを設定し、使用する必要があります http://localhost:5000/ 。上のスクリーンショットでは、このURLが設定されていることがわかります。

注釈

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

起動時にコンソールホストを選択するには、Visual Studioの起動メニューでコンソールホストを選択する必要があります。:

_images/0_choose_launch.png

クイックスタートの実行方法

前述のとおり、すべてのクイックスタートには参照ソリューションがあります。このコード は、quickstartsフォルダの IdentityServer4.Samples レポで見つけることができ ます。

クイックスタートソリューションの個々の部分を実行する最も簡単な方法は、起動モードを「現在の選択」に設定することです。ソリューションを右クリックし、[Startup Projectsを設定]を選択します。:

_images/0_startup_mode.png

通常、まずIdentityServerを起動してから、APIを起動してから、クライアントを起動します。実際にデバッグしたい場合は、デバッガでのみ実行してください。それ以外の場合は、プロジェクトを実行するにはCtrl + F5を使用するのが最善の方法です。

クライアント証明書を使用したAPIの保護

このクイックスタートは、IdentityServerを使用してAPIを保護するための最も基本的なシナリオを示しています。

このシナリオでは、アクセスするAPIとクライアントを定義します。クライアントはIdentityServerでアクセストークンを要求し、アクセストークンを使用してAPIにアクセスします。

APIの定義

スコープは、保護するシステムのリソース(APIなど)を定義します。

このチュートリアルではメモリ内の設定を使用しているので、APIを追加するには、型のオブジェクトを作成し ApiResource て適切なプロパティを設定するだけです。

Config.cs プロジェクトにファイルなどを追加し、次のコードを追加します。:

public static IEnumerable<ApiResource> GetApiResources()
{
    return new List<ApiResource>
    {
        new ApiResource("api1", "My API")
    };
}

クライアントの定義

次のステップは、このAPIにアクセスできるクライアントを定義することです。

このシナリオでは、クライアントには対話ユーザーがなく、IdentityServerでいわゆるクライアントシークレットを使用して認証されます。Config.cs ファイルに次のコードを追加します。:

public static IEnumerable<Client> GetClients()
{
    return new List<Client>
    {
        new Client
        {
            ClientId = "client",

            // no interactive user, use the clientid/secret for authentication
            AllowedGrantTypes = GrantTypes.ClientCredentials,

            // secret for authentication
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },

            // scopes that client has access to
            AllowedScopes = { "api1" }
        }
    };
}

IdentityServerの設定

スコープとクライアント定義を使用するようにIdentityServerを設定するには、ConfigureServices メソッドにコードを追加する必要があります。カバーの下で、関連する店舗とデータをDIシステムに追加することができます。:

public void ConfigureServices(IServiceCollection services)
{
    // configure identity server with in-memory stores, keys, clients and resources
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients());
}

つまり、サーバーを実行してブラウザをナビゲートすると``http://localhost:5000/.well-known/openid-configuration`` 、いわゆる発見文書が表示されます。これは、クライアントとAPIが必要な構成データをダウンロードするために使用されます。

_images/1_discovery.png

APIの追加

次に、ソリューションにAPIを追加します。

ASP.NET Core Web APIテンプレートを使用できます。ここでも、Kestrelと起動プロファイルを以前と同じように設定したのと同じ手法を使用してポートを制御することをお勧めします。このチュートリアルでは、APIを実行するように設定していることを前提としています http://localhost:5001

The controller

APIプロジェクトに新しいコントローラを追加する:

[Route("identity")]
[Authorize]
public class IdentityController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}

このコントローラーは後で認可要件をテストするために使用されるだけでなく、APIの目でクレームIDを視覚化するために使用されます。

Configuration

最後のステップは、DIと認証ミドルウェアに認証サービスをパイプラインに追加することです。これらは:

  • 受信したトークンを検証して、信頼できる発行元からのものであることを確認する
  • トークンがこのapi(別名スコープ)で使用するのに有効であることを検証する

IdentityServer4.AccessTokenValidation NuGetパッケージをプロジェクトに追加します。

_images/1_nuget_accesstokenvalidation.png

スタートアップを次のように更新します。:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvcCore()
            .AddAuthorization()
            .AddJsonFormatters();

        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ApiName = "api1";
            });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseAuthentication();

        app.UseMvc();
    }
}

AddAuthentication DIに認証サービスを追加``"Bearer"`` し、デフォルトスキームとして設定します。 AddIdentityServerAuthentication 認証サービスで使用するためにIdentityServerアクセス​​トークン検証ハンドラをDIに追加します。 UseAuthentication 認証ミドルウェアをパイプラインに追加するため、ホストへのすべてのコールで認証が自動的に実行されます。

ブラウザーを使用してコントローラー (http://localhost:5001/identity)に移動する場合は、代わりに401ステータスコードを取得する必要があります。つまり、APIには資格情報が必要です。

それで、APIはIdentityServerによって保護されています。

クライアントの作成

最後のステップでは、アクセストークンを要求するクライアントを作成し、このトークンを使用してAPIにアクセスします。そのためには、ソリューションにコンソールプロジェクトを追加してください(see full code here)。

IdentityServerのトークンエンドポイントはOAuth 2.0プロトコルを実装しており、生のHTTPを使用してアクセスできます。しかし、使いやすいAPIでプロトコルのやりとりをカプセル化するIdentityModelというクライアントライブラリがあります。

IdentityModel NuGetパッケージをアプリケーションに追加します。

_images/1_nuget_identitymodel.png

IdentityModelには、ディスカバリー・エンドポイントで使用するクライアント・ライブラリーが含まれています。この方法で、IdentityServerのベースアドレスを知る必要があります。実際のエンドポイントアドレスは、メタデータから読み取ることができます。:

// discover endpoints from metadata
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
if (disco.IsError)
{
    Console.WriteLine(disco.Error);
    return;
}

次に、 TokenClient クラスを使用してトークンを要求できます。インスタンスを作成するには、トークンエンドポイントのアドレス、クライアントID、および秘密を渡す必要があります。

次に、この RequestClientCredentialsAsync メソッドを使用してAPIのトークンをリクエストできます。:

// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");

if (tokenResponse.IsError)
{
    Console.WriteLine(tokenResponse.Error);
    return;
}

Console.WriteLine(tokenResponse.Json);

注釈

コンソールからのアクセストークンをコピーして jwt.io に貼り付けて、生のトークンを調べます。

最後のステップはAPIを呼び出すことです。

APIにアクセストークンを送信するには、通常、HTTP Authorizationヘッダーを使用します。これは、SetBearerToken 拡張メソッドを使用して行われます。:

// call api
var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);

var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
    Console.WriteLine(response.StatusCode);
}
else
{
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(JArray.Parse(content));
}

出力は次のようになります。:

_images/1_client_screenshot.png

注釈

デフォルトでは、アクセストークンにスコープ、有効期間(nbfおよびexp)、クライアントID(client_id)および発行者名(iss)に関するクレームが含まれます。

さらなる実験

これまでの成功パスに焦点を当てたこのウォークスルー

  • クライアントはトークンを要求できました
  • クライアントはトークンを使用してAPIにアクセスできます

システムをどのように動作させるかを知るためにエラーを引き起こすようになりました。

  • 実行していないときにIdentityServerに接続しようとする(利用できない)
  • 無効なクライアントIDまたはシークレットを使用してトークンを要求しようとする
  • トークン要求中に無効なスコープを要求しようとする
  • APIが実行されていないときに呼び出す(利用できない)
  • トークンをAPIに送信しない
  • トークン内のスコープとは異なるスコープを要求するようにAPIを構成する

パスワードを使用したAPIの保護

OAuth 2.0のリソースオーナーパスワードの付与により、クライアントはユーザー名とパスワードをトークンサービスに送信し、そのユーザーを表すアクセストークンを取得できます。

この仕様では、「信頼できる」(または従来の)アプリケーションに対してのみ、リソース所有者のパスワード付与を使用することを推奨しています。一般に、ユーザーを認証してアクセストークンを要求する場合、対話型のOpenID Connectフローの1つを使用する方が、通常ははるかに優れています。

それにもかかわらず、このグラント・タイプは、ユーザーの概念をクイックスタートのIdentityServerに導入することを可能にします。

ユーザーの追加

リソース(別名スコープ)とクライアント用のメモリ内のストアと同様、ユーザー用のストアもあります。

注釈

ユーザーアカウントを適切に保存および管理する方法の詳細については、ASP.NET IDベースのクイックスタートを参照してください。

このクラスTestUserは、テストユーザーとその主張を表します。configクラスに次のコードを追加して、2人のユーザーを作成しましょう:

まず、次のusingステートメントをConfig.csファイルに追加します。:

using IdentityServer4.Test;

public static List<TestUser> GetUsers()
{
    return new List<TestUser>
    {
        new TestUser
        {
            SubjectId = "1",
            Username = "alice",
            Password = "password"
        },
        new TestUser
        {
            SubjectId = "2",
            Username = "bob",
            Password = "password"
        }
    };
}

次に、テストユーザーをIdentityServerに登録します。:

public void ConfigureServices(IServiceCollection services)
{
    // configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients())
        .AddTestUsers(Config.GetUsers());
}

AddTestUsers拡張メソッドは、ボンネットの下に物事のカップルを行います

  • リソース所有者のパスワード付与のサポートを追加
  • ログインUIによって通常使用されるユーザー関連サービスへのサポートを追加します(次のクイックスタートで使用します)
  • テストユーザーに基づくプロファイルサービスのサポートが追加されました(次回のクイックスタートで詳しく説明します)

リソース所有者のパスワード付与のためのクライアントの追加

AllowedGrantTypesプロパティーを変更することによって、既存のクライアントに許可タイプのサポートを追加することができ ます。あなたのクライアントが絶対にサポートされている両方の権限タイプを使用できるようにする必要がある場合。

通常、リソース所有者のユースケース用に個別のクライアントを作成し、クライアント構成に次のものを追加します。:

public static IEnumerable<Client> GetClients()
{
    return new List<Client>
    {
        // other clients omitted...

        // resource owner password grant client
        new Client
        {
            ClientId = "ro.client",
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = { "api1" }
        }
    };
}

パスワードの付与を使ってトークンを要求する

クライアントは、クライアントの資格認可のために行ったのと非常によく似ています。主な違いは、クライアントが何とかユーザーのパスワードを収集し、トークン要求中にトークンサービスに送信することです。

再びIdentityModel TokenClientがここで助けてくれるでしょう:

// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password", "api1");

if (tokenResponse.IsError)
{
    Console.WriteLine(tokenResponse.Error);
    return;
}

Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");

トークンをID APIエンドポイントに送信すると、クライアントの資格認可と比較して小さいが重要な違いがあることに気づくでしょう。アクセストークンにはsub、ユーザーを一意に識別するクレームが含まれます。この「サブ」クレームは、APIへの呼び出し後にコンテンツ変数を調べることによって見ることができ、コンソールアプリケーションによって画面にも表示されます。

sub クレームの有無(または不在)により、APIはクライアントの代わりにコールを、ユーザーの代わりにコールを区別できます。

OpenID Connectによるユーザ認証の追加

このクイックスタートでは、私たちのIdentityServerにOpenID Connectプロトコルによる対話型ユーザー認証のサポートを追加したいと考えています。

これが完了すると、IdentityServerを認証に使用するMVCアプリケーションを作成します。

UIの追加

OpenID Connectに必要なすべてのプロトコルサポートは、すでにIdentityServerに組み込まれています。ログイン、ログアウト、同意とエラーに必要なUI部品を提供する必要があります。

ルック・アンド・フィールと正確なワークフローは、すべてのIdentityServer実装で常に異なると思われますが、私たちはMVCベースのサンプルUIを提供しています。

このUIは、 クイックスタートUIレポ にあります。このレポを複製またはダウンロードし、コントローラ、ビュー、モデル、およびCSSをIdentityServer Webアプリケーションにドロップすることができます。

または、IdentityServer Webアプリケーションと同じディレクトリにあるコマンドラインからこのコマンドを実行して、ダウンロードを自動化することもできます。:

iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))

Unix / Linuxの場合:

\curl -L https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.sh | bash

MVC UIアセ​​ットを追加したら、DIシステムとパイプラインの両方でMVCをホスティングアプリケーションに追加する必要があります。MVCを追加 ConfigureServices して AddMvc 拡張メソッド:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    // configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients())
        .AddTestUsers(Config.GetUsers());
}

パイプラインの最後のミドルウェアとしてMVCを追加 Configure して UseMvc 拡張メソッド:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseIdentityServer();

    app.UseStaticFiles();
    app.UseMvcWithDefaultRoute();
}

詳細については、クイックスタートUIの readme を参照してください。

注釈

release UIリポジトリのブランチには、最新の安定版と一致するUIがあります。 dev branch はIdentityServer4の現在の dev のビルドと一緒に行きます。特定のバージョンのUIをお探しの場合は、タグを確認してください。

しばらく時間をかけてコントローラーとモデルを調べ、理解していれば簡単に将来の変更を加えることができます。ほとんどのコードは、「機能フォルダ」スタイルを使用して「クイックスタート」フォルダに保存されています。このスタイルがあなたに合っていない場合は、自由にコードを整理してください。

MVCクライアントの作成

次に、ソリューションにMVCアプリケーションを追加します。そのためには、ASP.NET Core "Web Application"(つまりMVC)テンプレートを使用します。ウィザードの「認証」設定を構成しないでください。このクイックスタートで手動で行います。プロジェクトを作成したら、ポート5002を使用するようにアプリケーションを設定します(その方法については、概要の部分を参照してください)。

OpenID Connect認証のサポートをMVCアプリケーションに追加するには、以下をConfigureServicesinに追加しますStartup。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

    services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";

            options.Authority = "http://localhost:5000";
            options.RequireHttpsMetadata = false;

            options.ClientId = "mvc";
            options.SaveTokens = true;
        });
}

AddAuthenticationDIに認証サービスを追加します。プライマリが(を介してユーザを認証するための手段として、私たちはクッキーを使用している"Cookies"などDefaultScheme)。私たちは、ユーザーにログインする必要があるときに、OpenID Connectスキームを使用DefaultChallengeSchemeする"oidc"ため、を設定します。

次に、AddCookieCookieを処理できるハンドラを追加します。

最後に、AddOpenIdConnectOpenID Connectプロトコルを実行するハンドラを設定するために使用されます。これAuthorityは、IdentityServerを信頼していることを示しています。私たちは、その後、経由でこのクライアントを識別するClientId。 SignInSchemeOpenID Connectプロトコルが完了したら、Cookieハンドラを使用してCookieを発行するために使用されます。またSaveTokens、Cookie内のIdentityServerからトークンを永続化するために使用されます(後で必要になるため)。

また、JWTクレームタイプマッピングを無効にして、よく知られているクレーム(例えば、 'sub'や 'idp'など)が無修正で流れるようにしました。

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

そして、認証サービスを追加し、それぞれの要求に応じて実行することを確認するためUseAuthenticationにConfigureでStartup:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseAuthentication();

    app.UseStaticFiles();
    app.UseMvcWithDefaultRoute();
}

認証ミドルウェアは、MVCの前にパイプラインで追加する必要があります。

最後のステップは、認証ハンドシェイクをトリガーすることです。そのためには、ホームコントローラーに移動し[Authorize]、アクションの1つを追加します。そのアクションのビューを変更して、ユーザーの主張を表示します(例:

<dl>
    @foreach (var claim in User.Claims)
    {
        <dt>@claim.Type</dt>
        <dd>@claim.Value</dd>
    }
</dl>

ブラウザを使用してそのコントローラに移動すると、IdentityServerへのリダイレクトが試みられます。これは、MVCクライアントがまだ登録されていないためエラーになります。

OpenID Connect IDスコープのサポートの追加

OAuth 2.0と同様に、OpenID Connectもスコープの概念を使用しています。ここでも、スコープは保護したい、そしてクライアントがアクセスしたいものを表しています。OAuthとは対照的に、OIDCのスコープはAPIを表すのではなく、ユーザーID、名前、電子メールアドレスなどのIDデータを表します。

新しいヘルパー(in )を追加して、オブジェクトのコレクションを作成することにより、標準openid(subject id)とprofile(first name、last nameなど..)スコープのサポートを追加します。Config.csIdentityResource

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
    };
}

注釈

すべての標準的なスコープとそれに対応するクレームは、OpenID Connect 仕様

これらのアイデンティティーリソースをIdentityServerの設定に追加する必要がありますStartup.cs。AddInMemoryIdentityResources電話をかける場合は、拡張方法を使用してくださいAddIdentityServer():

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    // configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients())
        .AddTestUsers(Config.GetUsers());
}

OpenID Connect暗黙のフローのためのクライアントの追加

最後の手順は、MVCクライアントの新しい設定エントリをIdentityServerに追加することです。

OpenID Connectベースのクライアントは、これまでに追加したOAuth 2.0クライアントと非常によく似ています。しかし、OIDCのフローは常にインタラクティブなので、リダイレクトURLを設定に追加する必要があります。

クライアント構成に次のものを追加します。

public static IEnumerable<Client> GetClients()
{
    return new List<Client>
    {
        // other clients omitted...

        // OpenID Connect implicit flow client (MVC)
        new Client
        {
            ClientId = "mvc",
            ClientName = "MVC Client",
            AllowedGrantTypes = GrantTypes.Implicit,

            // where to redirect to after login
            RedirectUris = { "http://localhost:5002/signin-oidc" },

            // where to redirect to after logout
            PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile
            }
        }
    };
}

クライアントのテスト

最終的には、新しいMVCクライアントのためのすべての場所にする必要があります。

保護されたコントローラの操作に移動して、認証ハンドシェイクをトリガーします。IdentityServerのログインページへのリダイレクトが表示されます。

_images/3_login.png

ログインに成功すると、同意画面が表示されます。ここで、ユーザは、自分のアイデンティティ情報をクライアントアプリケーションにリリースしたいかどうかを決定することができる。

注釈

RequireConsentクライアントオブジェクトのプロパティを使用して、クライアントごとに同意を無効にすることができます。

_images/3_consent.png

最後に、ブラウザはクライアントアプリケーションにリダイレクトされ、クライアントアプリケーションはユーザーの主張を示します。

_images/3_claims.png

注釈

開発中に、トークンを検証できないことを示す例外が表示されることがあります。これは、署名キーマテリアルがオンザフライで作成され、メモリ内でのみ保持されるためです。この例外は、クライアントとIdentityServerが同期しなくなった場合に発生します。次回メタデータが追いついたときにクライアントで操作を繰り返すだけで、すべて正常に動作します。

サインアウトの追加

最後のステップは、MVCクライアントにサインアウトを追加することです。

IdentityServerのような認証サービスでは、ローカルアプリケーションのCookieをクリアするだけでは不十分です。さらに、中央シングルサインオンセッションをクリアするために、IdentityServerへの往復を行う必要があります。

正確なプロトコル手順は、OpenID Connectミドルウェア内で実装されています。単に、次のコードを一部のコントローラに追加してログアウトをトリガーします。

public async Task Logout()
{
    await HttpContext.SignOutAsync("Cookies");
    await HttpContext.SignOutAsync("oidc");
}

これにより、ローカルCookieがクリアされ、IdentityServerにリダイレクトされます。IdentityServerはクッキーをクリアして、ユーザにMVCアプリケーションに戻るためのリンクを与えます。

さらなる実験

前述のように、OpenID Connectミドルウェアはデフォルトでプロファイルスコープを要求します。このスコープには、名前やウェブサイトなどの主張も含まれます。

これらのクレームをユーザに追加して、IdentityServerがそれらをアイデンティティトークンに入れることができます:

public static List<TestUser> GetUsers()
{
    return new List<TestUser>
    {
        new TestUser
        {
            SubjectId = "1",
            Username = "alice",
            Password = "password",

            Claims = new []
            {
                new Claim("name", "Alice"),
                new Claim("website", "https://alice.com")
            }
        },
        new TestUser
        {
            SubjectId = "2",
            Username = "bob",
            Password = "password",

            Claims = new []
            {
                new Claim("name", "Bob"),
                new Claim("website", "https://bob.com")
            }
        }
    };
}

次に認証すると、クレームページに追加のクレームが表示されます。

クレームを追加して、さらに多くの範囲を自由に感じてください。ScopeOpenID Connectミドルウェアのプロパティは、認証時にIdentityServerに送信されるスコープを設定する場所です。

また、トークンに対する要求の取得は拡張性の点であることも注目に値するIProfileService。私たちが使用しているのでAddTestUsers、TestUserProfileServiceデフォルトで使用されます。ここでソースコード を調べることで、その動作を確認することができます。

外部認証のサポートの追加

次に、外部認証のサポートを追加します。これは本当に簡単です。本当に必要なのはASP.NET Core互換の認証ハンドラです。

ASP.NET Core自体は、Google、Facebook、Twitter、Microsoft Account、OpenID Connectをサポートしています。さらに、他の多くの認証プロバイダの実装をここで見つけることができます。

Googleサポートを追加する

認証にGoogleを使用できるようにするには、まずGoogleに登録する必要があります。これは開発者コンソールで行われます。新しいプロジェクトを作成し、Google+ APIを有効にして、/ signin-googleのパスをベースアドレス(http:// localhost:5000 / signin-googleなど)に追加してローカルIdentityServerのコールバックアドレスを設定します。

ポート5000で実行している場合は、下記のコードスニペットのクライアントID /シークレットを使用することができます。これは、事前に登録されているためです。

まず、DIにGoogle認証ハンドラを追加します。これは、このスニペットを次の場所ConfigureServicesに追加することで行いますStartup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    // configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients())
        .AddTestUsers(Config.GetUsers());

    services.AddAuthentication()
        .AddGoogle("Google", options =>
        {
            options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

            options.ClientId = "434483408261-55tc8n0cs4ff1fe21ea8df2o443v2iuc.apps.googleusercontent.com";
            options.ClientSecret = "3gcoTrEDPPJ0ukn_aYYT6PWo";
        });
}

デフォルトでは、IdentityServerは、外部認証の結果(定数に基づくスキームを使用IdentityServerConstants.ExternalCookieAuthenticationScheme)のために特にCookieハンドラを構成します。Googleハンドラの設定では、そのCookieハンドラが使用されます。これがどのように行われたかをよりよく理解するにはAccountController、クイックスタートフォルダの下にあるクラスを参照してください。

次に、MVCクライアントを実行して認証を試みます。ログインページにGoogleのボタンが表示されます:

_images/4_login_page.png

認証後、クレームが現在Googleデータから取得されていることがわかります。

_images/4_external_claims.png

さらなる実験

追加の外部プロバイダを追加できます。私たちはあなたがOpenID Connectを使って統合できるIdentityServer4のクラウドホストデモ版を持っています。

DIにOpenId Connectハンドラを追加する:

services.AddAuthentication()
    .AddGoogle("Google", options =>
    {
        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

        options.ClientId = "434483408261-55tc8n0cs4ff1fe21ea8df2o443v2iuc.apps.googleusercontent.com";
        options.ClientSecret = "3gcoTrEDPPJ0ukn_aYYT6PWo";
    })
    .AddOpenIdConnect("oidc", "OpenID Connect", options =>
    {
        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
        options.SignOutScheme = IdentityServerConstants.SignoutScheme;

        options.Authority = "https://demo.identityserver.io/";
        options.ClientId = "implicit";

        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = "name",
            RoleClaimType = "role"
        };
    });

これで、ユーザーはクラウドホストデモIDプロバイダを使用できるようになりました。

注釈

クイックスタートUIは外部ユーザーを自動的にプロビジョニングします。外部ユーザが初めてログインすると、新しいローカルユーザが作成され、すべての外部クレームが新しいユーザにコピーされて関連付けられます。あなたがこのような状況に対処する方法は、あなた次第です。たぶん、ある種の登録UIを最初に表示したいと思うかもしれません。デフォルトのクイックスタートのソースコードは、ここで見つけることができます。自動プロビジョニングが実行されるコントローラは、ここで見つけることができます。

ハイブリッドフローへの切り替えとAPIアクセスの追加

以前のクイックスタートでは、APIアクセスとユーザー認証の両方を検討しました。今度は2つの部分を一緒に持っていきたいと思っています。

OpenID ConnectとOAuth 2.0の組み合わせの美しさは、単一のプロトコルとトークンサービスとの単一の交換の両方で達成できるということです。

前回のクイックスタートでは、OpenID Connect暗黙のフローを使用しました。暗黙のフローでは、すべてのトークンがブラウザを介して送信されますが、これはアイデンティティトークンにとってはまったく問題ありません。今度は、アクセストークンを要求したい。

アクセストークンはアイデンティティトークンよりもはるかに敏感であり、必要でない場合には「外部」の世界にそれらを公開したくありません。OpenID Connectには「Hybrid Flow」というフローがあり、これは両方の世界のベストを提供し、アイデンティティトークンはブラウザチャネル経由で送信されるため、クライアントはそれ以上の作業を行う前に検証することができます。検証が成功すると、クライアントはトークンサービスのバックチャネルを開いてアクセストークンを取得します。

クライアント設定の変更

多くの変更は必要ありません。最初に、クライアントがハイブリッドフローを使用できるようにしたいとします。さらに、クライアントがユーザーのコンテキストに属さないサーバーからサーバーへのAPI呼び出しを許可するようにします(クライアントの資格情報のクイックスタートに非常に似ています)。これはAllowedGrantTypesプロパティを使用して表されます。

次に、クライアントシークレットを追加する必要があります。これは、バックチャンネルのアクセストークンを取得するために使用されます。

最後に、クライアントにoffline_accessスコープへのアクセスを許可します。これにより、長期間存続するAPIアクセスのリフレッシュトークンを要求できます。

new Client
{
    ClientId = "mvc",
    ClientName = "MVC Client",
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

    ClientSecrets =
    {
        new Secret("secret".Sha256())
    },

    RedirectUris           = { "http://localhost:5002/signin-oidc" },
    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "api1"
    },
    AllowOfflineAccess = true
};

MVCクライアントの変更

MVCクライアントの変更も最小限に抑えられています。ASP.NET Core OpenID Connectハンドラには、ハイブリッドフローの組み込みサポートが含まれているため、一部のコンフィグレーション値を変更するだけで済みます。

ClientSecretIdentityServerの秘密と一致するように設定します。スコープoffline_accessとapi1スコープを追加し、ResponseTypeを(これは基本的に「ハイブリッドフローを使用する」という意味の)code id_token .

.AddOpenIdConnect("oidc", options =>
{
    options.SignInScheme = "Cookies";

    options.Authority = "http://localhost:5000";
    options.RequireHttpsMetadata = false;

    options.ClientId = "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = "code id_token";

    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;

    options.Scope.Add("api1");
    options.Scope.Add("offline_access");
    options.ClaimActions.MapJsonKey("website", "website");
});

MVCクライアントを実行すると、大きな違いはなく、同意画面に追加のAPIとオフラインアクセススコープが表示されるようになりました。

アクセストークンの使用

OpenID Connectミドルウェアは自動的にあなたのためにトークン(私たちの場合はID、アクセス、更新)を保存します。それがSaveTokensセッティングです。

技術的には、トークンはクッキーのプロパティセクション内に格納されます。それらにアクセスする最も簡単な方法は、Microsoft.AspNetCore.Authentication名前空間の拡張メソッドを使用することです。

例えばあなたのクレームビューでは:

<dt>access token</dt>
<dd>@await ViewContext.HttpContext.GetTokenAsync("access_token")</dd>

<dt>refresh token</dt>
<dd>@await ViewContext.HttpContext.GetTokenAsync("refresh_token")</dd>

アクセストークンを使用してAPIにアクセスするには、トークンを取得して HttpClient に設定するだけです。

public async Task<IActionResult> CallApiUsingUserAccessToken()
{
    var accessToken = await HttpContext.GetTokenAsync("access_token");

    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    var content = await client.GetStringAsync("http://localhost:5001/identity");

    ViewBag.Json = JArray.Parse(content).ToString();
    return View("json");
}

ASP.NET Core Identityの使用

IdentityServerは柔軟性を重視して設計されているため、ユーザーやデータ(パスワードを含む)に必要なデータベースを使用できます。新しいユーザーデータベースを使用する場合は、ASP.NET IDを選択することができます。このクイックスタートでは、IdentityServerでASP.NET IDを使用する方法を示します。

このクイックスタートは、以前のクイックスタートをすべて完了したことを前提としています。このクイックスタートでASP.NETアイデンティティを使用するアプローチは、Visual StudioのASP.NETアイデンティティテンプレートから新しいプロジェクトを作成することです。この新しいプロジェクトは、以前のクイックスタートで作成した以前のIdentityServerプロジェクトに代わるものです。このソリューションの他のプロジェクト(クライアントとAPI用)はすべて同じままです。

ASP.NETアイデンティティのための新しいプロジェクト

まず、ASP.NET Identity用の新しいプロジェクトをソリューションに追加します。ASP.NET IDには多くのコードが必要なので、Visual Studioのテンプレートを使用するのが理にかなっています。最終的にIdentityServerの古いプロジェクトを削除します(他のクイックスタートに従っていると仮定します)。ただし、移行する必要がある項目がいくつかあります(以前のクイックスタートで説明したように、

新しい "ASP.NETコアWebアプリケーション"プロジェクトを作成します。

_images/6_new_web_project.png

次に、 "Webアプリケーションテンプレート(Model-View-Controller)"オプションを選択します。

_images/6_web_app_template.png

その後、 "Change Authentication"ボタンをクリックし、 "Individual User Accounts"(ASP.NET IDを使用することを意味します)を選択します:

_images/6_change_authentication.png

最後に、新しいプロジェクトダイアログは次のようになります。それが終わったら、「OK」をクリックしてプロジェクトを作成します。

_images/6_web_app_template_with_aspnet_identity.png

ホスティングの変更

ポート5000で実行するようにホスティングを変更することを忘れないでください(これはここで説明します)。これは既存のクライアントとapiプロジェクトが引き続き機能するように重要です。

IdentityServerパッケージを追加する

IdentityServer4.AspNetIdentityNuGetパッケージを追加します。これはIdentityServer4パッケージに依存するため、自動的に推移的な依存関係として追加されます。

_images/6_nuget.png

スコープとクライアントの設定

これがIdentityServerの新しいプロジェクトであるにもかかわらず、従来のクイックスタートと同じスコープとクライアント構成が必要です。以前のクイックスタートで使用した構成クラス(Config.cs内)をこの新しいプロジェクトにコピーします。

(今のところ)必要な設定への変更の1つは、MVCクライアントの同意を無効にすることです。以前のIdentityServerプロジェクトの同意コードをまだコピーしていないので、今度はこれをMVCクライアントに変更して設定しRequireConsent=falseます。

new Client
{
    ClientId = "mvc",
    ClientName = "MVC Client",
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

    RequireConsent = false,

    ClientSecrets =
    {
        new Secret("secret".Sha256())
    },

    RedirectUris           = { "http://localhost:5002/signin-oidc" },
    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "api1"
    },
    AllowOfflineAccess = true
}

IdentityServerの設定

前と同じように、IdentityServer はStartup.csConfigureServicesとの両方で設定する必要があります。Configure

ConfigureServices

これは、ASP.NET IDのために生成されたテンプレートコードと、IdentityServerに必要な追加(最後に)の両方を示しています。以前のクイックスタートでは、AddTestUsers拡張メソッドを使用してユーザーを登録しましたが、この状況では、AddAspNetIdentity代わりにASP.NET IDユーザーを使用するように拡張メソッドを置き換えています。AddAspNetIdentity拡張メソッドは、あなたのASP.NETアイデンティティユーザタイプ(に必要なものと同じである一般的なパラメータが必要ですAddIdentityテンプレートからの方法を)。

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    services.AddMvc();

    // configure identity server with in-memory stores, keys, clients and scopes
    services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryPersistedGrants()
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients())
        .AddAspNetIdentity<ApplicationUser>();
}

注釈

IdentityServerがASP.NET IDの一部の設定を上書きしているため、ASP.NET IDを使用する場合、IdentityServerがDIシステムに ASP.NET IDの後に登録されることが重要です。

設定

これには、ASP.NET ID用に生成されたテンプレートコードと、その呼び出しをUseIdentityServer置き換える呼び出しの両方が表示されますUseAuthentication。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    // app.UseAuthentication(); // not needed, since UseIdentityServer adds the authentication middleware
    app.UseIdentityServer();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

ユーザデータベースの作成

これが新しいASP.NET IDプロジェクトであることを考えると、データベースを作成する必要があります。これを行うには、プロジェクトディレクトリからコマンドプロンプトを実行し、次のように実行します。dotnet ef database update -c ApplicationDbContext

_images/6_ef_database_update.png

ユーザの作成

この時点で、プロジェクトを実行し、データベースにユーザーを作成/登録することができます。アプリケーションを起動し、ホームページから「登録」リンクをクリックしてください:

_images/6_home_page.png

そして、登録ページで新しいユーザーアカウントを作成します:

_images/6_register_page.png

ユーザーアカウントがあるので、ログインし、クライアントを使用し、APIを呼び出すことができるはずです。

MVCクライアントを使用したログイン

MVCクライアントアプリケーションを起動すると、「安全な」リンクをクリックしてログインすることができるはずです。

_images/6_mvc_client.png

ASP.NET IDログインページにリダイレクトする必要があります。新しく作成されたユーザーとのログイン:

_images/6_login.png

ログイン後、承諾ページをスキップして(上記の変更が加えられた場合)、ユーザーのクレームを記載するMVCクライアントアプリケーションにすぐにリダイレクトされます。

_images/6_claims.png

ユーザーに代わってAPIを呼び出すには、「アプリケーションIDを使用してAPIを呼び出す」をクリックすることもできます。

_images/6_api_claims.png

そして、あなたはASP.NET Identityからのユーザでログインしました。

次は何ですか?

IdentityServerの以前のクイックスタートプロジェクトでは、同意ページ、エラーページ、およびログアウトページが提供されていました。これらの欠けている部分のコードは、以前のクイックスタートプロジェクトからこれにコピーすることができます。これを済ませたら、最終的に古いIdentityServerプロジェクトを削除/削除できます。また、これを済ませたらRequireConsent=true、MVCクライアント設定でフラグを再度有効にすることを忘れないでください。

このクイックスタートのサンプルコードは既にこれらの手順を完了しているため、これらの機能をすべて使い始めることができます。楽しい!

JavaScriptクライアントの追加

このクイックスタートでは、JavaScriptクライアントアプリケーションを構築する方法を説明します。ユーザーはIdentityServerにログインし、IdentityServerによって発行されたアクセストークンを使用してWeb APIを呼び出し、IdentityServerからログアウトします。

JavaScriptクライアント用の新しいプロジェクト

JavaScriptアプリケーション用の新しいプロジェクトを作成します。単純に空のWebプロジェクトでも、空のASP.NET Coreアプリケーションでもかまいません。このクイックスタートでは、空のASP.NETコアアプリケーションが使用されます。

新しいASP.NET Core Webアプリケーションを作成します。

_images/7_new_project.png

「空」テンプレートを選択します。

_images/7_empty_template.png

"OK"ボタンをクリックしてプロジェクトを作成します。

ホスティングの変更

ポート5003で実行するようにホスティングを変更します(ここで説明します)。

静的ファイルミドルウェアを追加する

このプロジェクトは主にクライアント側で動作するように設計されているため、アプリケーションを構成する静的なHTMLファイルとJavaScriptファイルを提供するためにASP.NET Coreが必要です。静的ファイルミドルウェアは、これを行うために設計されています。

メソッド内のStartup.csに静的ファイルミドルウェアを登録しますConfigure。

public void Configure(IApplicationBuilder app)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

このミドルウェアは、アプリケーションの〜/ wwwrootフォルダにある静的ファイルを提供します。ここで、HTMLファイルとJavaScriptファイルを配置します。

oidc-client リファレンス

MVCプロジェクトでは、ライブラリを使用してOpenID Connectプロトコルを処理しました。このプロジェクトでは、JavaScriptで動作し、ブラウザで動作するように設計されているものを除き、同様のライブラリが必要です。oidcクライアントライブラリは、そのようなライブラリです。これは、NPM、Bower、githubから直接ダウンロードすることができます。

NPM

NPMを使用してoidc-clientをダウンロードする場合は、次の手順を実行します。

新しいNPMパッケージファイルをプロジェクトに追加し、package.jsonという名前を付けます。

_images/7_add_package_json.png

でpackage.jsonを追加dependencyするにはoidc-client:

"dependencies": {
  "oidc-client": "1.4.1"
}

このファイルを保存したら、Visual Studioは自動的にこれらのパッケージをnode_modulesというフォルダに復元します。

_images/7_node_modules.png

名前のファイルを探しoidc-client.jsに〜/ node_modules / oidc-クライアント/ distののフォルダを、アプリケーションの中にそれをコピーし、〜/のwwwrootフォルダ。〜/ wwwrootに NPMパッケージをコピーするもっと洗練された方法がありますが、これらのテクニックはこのクイックスタートの対象外です。

HTMLファイルとJavaScriptファイルを追加する

次に、HTMLファイルとJavaScriptファイルを〜/ wwwrootに追加します。2つのHTMLファイルと1つのアプリケーション固有のJavaScriptファイル(oidc-client.jsライブラリに加えて)があります。では〜/ wwwrootに、名前のHTMLファイルを追加したindex.htmlとcallback.htmlを、と呼ばれるJavaScriptファイルを追加app.jsを。

index.html

これはアプリケーションのメインページになります。ユーザーがログイン、ログアウト、およびWeb APIの呼び出しを行うためのボタン用のHTMLが含まれています。また<script>、2つのJavaScriptファイルを含むタグも含まれています。また<pre>、ユーザーにメッセージを表示するために使用されます。

これは次のようになります。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <button id="login">Login</button>
    <button id="api">Call API</button>
    <button id="logout">Logout</button>

    <pre id="results"></pre>

    <script src="oidc-client.js"></script>
    <script src="app.js"></script>
</body>
</html>

app.js

これには、アプリケーションのメインコードが含まれます。まず、ヘルパ関数を追加してメッセージをログに記録します<pre>。

function log() {
    document.getElementById('results').innerText = '';

    Array.prototype.forEach.call(arguments, function (msg) {
        if (msg instanceof Error) {
            msg = "Error: " + msg.message;
        }
        else if (typeof msg !== 'string') {
            msg = JSON.stringify(msg, null, 2);
        }
        document.getElementById('results').innerHTML += msg + '\r\n';
    });
}

次に、「クリック」イベントハンドラを3つのボタンに登録するコードを追加します。

document.getElementById("login").addEventListener("click", login, false);
document.getElementById("api").addEventListener("click", api, false);
document.getElementById("logout").addEventListener("click", logout, false);

次に、oidc-clientライブラリのUserManagerクラスを使用して、OpenID Connectプロトコルを管理できます。これには、MVCクライアントで必要とされたのと同じ設定が必要です(値は異なりますが)。構成およびインスタンス化するには、このコードを追加します:UserManager

var config = {
    authority: "http://localhost:5000",
    client_id: "js",
    redirect_uri: "http://localhost:5003/callback.html",
    response_type: "id_token token",
    scope:"openid profile api1",
    post_logout_redirect_uri : "http://localhost:5003/index.html",
};
var mgr = new Oidc.UserManager(config);

次に、ユーザーがJavaScriptアプリケーションにログインしているかどうかを知るAPIをUserManager提供しgetUserます。JavaScript Promiseを使用して結果を非同期的に返します。返されるUserオブジェクトにはprofile、ユーザーの要求を含むプロパティがあります。このコードを追加して、ユーザーがJavaScriptアプリケーションにログインしているかどうかを検出します。

mgr.getUser().then(function (user) {
    if (user) {
        log("User logged in", user.profile);
    }
    else {
        log("User not logged in");
    }
});

次に、我々は実装したいlogin、apiとlogout機能を。これUserManagerはsigninRedirect、ユーザsignoutRedirectをログインさせ、ユーザをログアウトさせるためのものです。User我々は上記のコードで得られたオブジェクトもありaccess_token、ウェブAPIの認証に使用することができますプロパティを。これaccess_tokenは、ベアラ方式のAuthorizationヘッダーを介してWeb APIに渡されます。このコードを追加して、アプリケーションでこれらの3つの機能を実装します。

function login() {
    mgr.signinRedirect();
}

function api() {
    mgr.getUser().then(function (user) {
        var url = "http://localhost:5001/identity";

        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = function () {
            log(xhr.status, JSON.parse(xhr.responseText));
        }
        xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
        xhr.send();
    });
}

function logout() {
    mgr.signoutRedirect();
}

See: Protecting an API using Client Credentials <http://docs.identityserver.io/en/release/quickstarts/1_client_credentials.html> for information on how to create the api used in the code above.

callback.html

このHTMLファイルは、redirect_uriユーザーがIdentityServerにログインすると指定されたページです。それは、IdentityServerとのOpenID Connectプロトコルサインインハンドシェイクを完了します。これのためのコードは、UserManager以前使用したクラスによってすべて提供されています。ログインが完了したら、ユーザーをメインのindex.htmlページにリダイレクトすることができます。サインインプロセスを完了するためにこのコードを追加してください:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <script src="oidc-client.js"></script>
    <script>
        new Oidc.UserManager().signinRedirectCallback().then(function () {
            window.location = "index.html";
        }).catch(function (e) {
            console.error(e);
        });
    </script>
</body>
</html>

JavaScriptクライアント用のIdentityServerにクライアント登録を追加する

クライアントアプリケーションがすぐに使えるようになったので、この新しいJavaScriptクライアント用にIdentityServerに設定エントリを定義する必要があります。IdentityServerプロジェクトで、クライアント構成(Config.cs内)を探します。新しいJavaScriptアプリケーションのリストに新しいクライアントを追加します。次のような構成にする必要があります。

// JavaScript Client
new Client
{
    ClientId = "js",
    ClientName = "JavaScript Client",
    AllowedGrantTypes = GrantTypes.Implicit,
    AllowAccessTokensViaBrowser = true,

    RedirectUris =           { "http://localhost:5003/callback.html" },
    PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
    AllowedCorsOrigins =     { "http://localhost:5003" },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "api1"
    }
}

CORSでWeb APIへのAjax呼び出しを許可する

必要な設定の最後の1つは、Web APIプロジェクトでCORSを設定することです。これにより、http:// localhost:5003からhttp:// localhost:5001へのAjax呼び出しが可能になります。

Configure CORS

依存性注入システムにCORSサービスを追加ConfigureServicesでStartup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore()
        .AddAuthorization()
        .AddJsonFormatters();

    services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "http://localhost:5000";
            options.RequireHttpsMetadata = false;

            options.ApiName = "api1";
        });

    services.AddCors(options =>
    {
        // this defines a CORS policy called "default"
        options.AddPolicy("default", policy =>
        {
            policy.WithOrigins("http://localhost:5003")
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
    });
}

CORSミドルウェアをパイプラインに追加しConfigureます。

public void Configure(IApplicationBuilder app)
{
    app.UseCors("default");

    app.UseAuthentication();

    app.UseMvc();
}

JavaScriptアプリケーションを実行する

これで、JavaScriptクライアントアプリケーションを実行できるはずです。

_images/7_not_logged_in.png

ユーザーにサインインするには、[ログイン]ボタンをクリックします。ユーザーがJavaScriptアプリケーションに戻ったら、プロフィール情報が表示されます。

_images/7_logged_in.png

"API"ボタンをクリックしてWeb APIを呼び出します:

_images/7_api_results.png

最後に「ログアウト」をクリックしてユーザーにサインアウトします。

_images/7_signed_out.png

サインイン、ログアウト、およびWeb APIへの呼び出しの認証にIdentityServerを使用するJavaScriptクライアントアプリケーションが開始されました。

構成データと運用データにEntityFramework Coreを使用する

IdentityServerは拡張性のために設計されており、拡張性のポイントの1つは、IdentityServerが必要とするデータに使用される記憶メカニズムです。このクイックスタートでは、EntityFramework(EF)をこのデータのストレージメカニズムとして使用するようにIdentityServerを設定する方法を示します(今まで使用していたインメモリ実装を使用するのではなく)。

注釈

EFサポートを手動で設定するだけでなく、EFサポートで新しいプロジェクトを作成するためのIdentityServerテンプレートもあります。それを作成するために使用します。詳細はこちらを参照してください。dotnet new is4ef

IdentityServer4.EntityFramework

データベースに移動するデータには2種類あります。1つは設定データ(リソースとクライアント)です。2つ目はIdentityServerが使用中に生成する操作データ(トークン、コード、同意)です。これらのストアはインタフェースでモデル化されており、これらのインタフェースのEF実装をIdentityServer4.EntityFramework Nugetパッケージに提供しています。

まず、IdentityServerプロジェクトのIdentityServer4.EntityFramework Nugetパッケージへの参照を追加します。

_images/8_nuget.png

SqlServerの使用

EFの柔軟性を考えると、EFでサポートされているデータベースを使用できます。このクイックスタートでは、Visual Studioに付属するLocalDbバージョンのSqlServerを使用します。

データベーススキーマの変更とEF移行の使用

IdentityServer4.EntityFrameworkのパッケージには、IdentityServerのモデルからマップするエンティティクラスが含まれています。IdentityServerのモデルが変更されると、IdentityServer4.EntityFrameworkのエンティティクラスも変更されます。IdentityServer4.EntityFrameworkを使用して時間をかけてアップグレードするときには、独自のデータベーススキーマと、エンティティクラスの変更に応じてそのスキーマに必要な変更を行う責任があります。これらの変更を管理するための1つのアプローチは、EF移行を使用することです。このクイックスタートでは、その方法を示します。移行があなたの好みでない場合は、スキーマの変更を適切な方法で管理できます。

注釈

SqlServer用のSQLスクリプトは、IdentityServer4.EntityFrameworkのエンティティ用にメンテナンスされています。彼らはここに位置しています。

移行のためのEFツーリング

EF移行を使用してスキーマの変更を追跡することに加えて、これを使用してデータベースに初期スキーマを作成します。これには、EFコアツールの使用が必要です(詳細はこちら)。これらを今追加します。残念ながら、これは.csprojファイルを手動で編集する必要があります。プロジェクトを右クリックし、 "edit projectname.csproj"を選択して.csprojを編集するには:

注釈

IdentityServerホストの初期プロジェクトの作成方法に応じて、csprojファイルでこれらのツールを設定している可能性があります。そうであれば、次のセクションに進むことができます。

_images/8_edit_csproj.png

そして、最後の</ Project>要素の前にスニペットを追加します。

<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>

これは次のようになります。

_images/8_csproj.png

ファイルを保存して閉じます。ツールが正しくインストールされていることをテストするには、プロジェクトと同じディレクトリにコマンドシェルを開き、dotnet efを実行します。これは次のようになります。

_images/8_dotnet_ef_command_line.png

Configuring the stores

次のステップは、現在の通話交換することでAddInMemoryClients、AddInMemoryIdentityResources、そしてAddInMemoryApiResources内ConfigureServicesでの方法Startup.csを。このコードで置き換えます:

const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.Quickstart.EntityFramework-2.0.0;trusted_connection=yes;";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddTestUsers(Config.GetUsers())
    // this adds the config data from DB (clients, resources)
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = builder =>
            builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));
    })
    // this adds the operational data from DB (codes, tokens, consents)
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = builder =>
            builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));

        // this enables automatic token cleanup. this is optional.
        options.EnableTokenCleanup = true;
        options.TokenCleanupInterval = 30;
    });

これらの名前空間をファイルに追加する必要があるかもしれません:

using Microsoft.EntityFrameworkCore;
using System.Reflection;

上記のコードは、接続文字列をハードコーディングしています。必要に応じて変更することができます。また、への呼び出しAddConfigurationStoreとは、AddOperationalStoreEF-裏打ちされた店舗の実装を登録しています。

これらのAPIに渡される「ビルダー」コールバック関数は、これらの2つのストアのそれぞれDbContextOptionsBuilderに対してfor を構成できるEFメカニズムですDbContext。これはDbContext、使用するデータベースプロバイダを使用してクラスを構成する方法です。この場合、UseSqlServer私たちはSqlServerを使用して呼び出します。また、これは接続文字列が提供される場所です。

in "options"コールバック関数UseSqlServerは、EF移行が定義されているアセンブリを構成するものです。EFでは、データベースのスキーマを定義するためにマイグレーションを使用する必要があります。

注釈

これらの移行は、データベースとプロバイダに固有のものであるため、ホスティング・アプリケーションでこれらの移行を定義する必要があります。

次に移行を追加します。

移行の追加

移行を作成するには、IdentityServerプロジェクトディレクトリでコマンドプロンプトを開きます。コマンドプロンプトで、次の2つのコマンドを実行します。

dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb

これは次のようになります。

_images/8_add_migrations.png

あなたは今見るべきである〜/データ/移行/ IdentityServerのプロジェクトにフォルダを。これには、新しく作成された移行のコードが含まれています。

注釈

データベースプロジェクトが別のクラスライブラリで、 '<your-name> DbContext'型のオブジェクトを作成できませんでした。'IDesignTimeDbContextFactory'の実装をプロジェクトに追加するか、デザイン時にサポートされている追加のパターンについてはhttps://go.microsoft.com/fwlink/?linkid=851728を参照してください。IDesignTimeDbContextFactoryの実装を追加することによって、PersistedGrantDbContextとConfigurationDbContextの両方のファクトリの実装が必要になります。

データベースの初期化

これで移行が完了したため、移行からデータベースを作成するコードを記述できます。また、前のクイックスタートで定義したメモリ内の構成データをデータベースにシードします。

でStartup.csデータベースを初期化するために、このメソッドを追加します。

private void InitializeDatabase(IApplicationBuilder app)
{
    using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

        var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
        context.Database.Migrate();
        if (!context.Clients.Any())
        {
            foreach (var client in Config.GetClients())
            {
                context.Clients.Add(client.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.IdentityResources.Any())
        {
            foreach (var resource in Config.GetIdentityResources())
            {
                context.IdentityResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.ApiResources.Any())
        {
            foreach (var resource in Config.GetApiResources())
            {
                context.ApiResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }
    }
}

そして、Configureメソッドから呼び出すことができます:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // this will do the initial DB population
    InitializeDatabase(app);

    // the rest of the code that was already here
    // ...
}

IdentityServerプロジェクトを実行する場合は、データベースを作成し、クイックスタート構成データをシードします。SQL Server Management StudioまたはVisual Studioを使用して、データの接続および検査を行うことができます。

_images/8_database.png

注釈

上記のInitializeDatabaseヘルパーAPIは、データベースをシードするのに便利ですが、このアプローチは、アプリケーションが実行されるたびに実行するのが理想的ではありません。データベースが移入されたら、APIへの呼び出しを削除することを検討してください。

クライアントアプリケーションを実行する

これで、データベース構成に基づいて、既存のクライアントアプリケーションを実行してサインインし、トークンを取得し、APIを呼び出すことができるようになりました。

注釈

このセクションにあるコードは、Config.csとその架空のユーザーAliceとBobに依然として依存しています。ユーザーリストが短く静的な場合は、調整されたConfig.csのバージョンで十分ですが、データベース内でより大きくて流動的なユーザーリストを動的に管理したい場合があります。ASP.NET IDは考慮すべきオプションの1つで、このソリューションのサンプル実装は次のセクションのクイックスタートに一覧表示されています。

コミュニティのクイックスタートとサンプル

これらのサンプルは、IdentityServer組織によって管理されていません。IdentityServer組織はコミュニティサンプルにうまくリンクしますが、サンプルについては何ら保証することはできません。著者に直接お問い合わせください。

IdentityServer4 EF and ASP.NET Identity

この サンプルでは、​​EFとASP.NET IDのクイックスタート(#6と#8)を組み合わせています。

Co-hosting IdentityServer4 and a Web API

このサンプルは、APIを保護しているIdentityServerと同じホストにAPIをホストする方法を示しています。

https://github.com/brockallen/IdentityServerAndApi

IdentityServer4 samples for MongoDB

  • IdentityServer4-mongo:Quickstart#8 EntityFrameworkの設定と似ていますが、MongoDBを設定データとして使用しています。
  • IdentityServer4-mongo-AspIdentity:より洗練されたサンプルは、MongoDBを使用して設定データを使用するアイデンティティ管理用のASP.NET IDを使用します。

https://github.com/souzartn/IdentityServer4.Samples.Mongo

Exchanging external tokens from Facebook, Google and Twitter

  • 拡張認証を使用して外部認証トークンをIDサーバーのacesssトークンに交換する方法を示します。

https://github.com/waqaskhan540/IdentityServerExternalAuth

ASP.NET Core MVC RazorPages template for IdentityServer4 Quickstart UI

Razor Pages based QuickStart sample by Martin Fletcher.

.NET Core and ASP.NET Core "Platform" scenario

  • 信頼できる「内部」アプリケーションと「外部」アプリケーションとの、.NET Core 2.0およびASP.NET Core 2.0アプリケーションとの相互作用を示します。

https://github.com/BenjaminAbt/Samples.AspNetCore-IdentityServer4

Securing a Node API with tokens from IdentityServer4 using JWKS

  • IdentityServer4のJWKSエンドポイントとRS256アルゴリズムを使用してノード(Express)APIを保護する方法を示します。
  • 高品質の実稼働準備完了モジュールを使用するIdentityServer4.SamplesのNodeJsApiサンプルの代替品を提供します。

https://github.com/lyphtec/idsvr4-node-jwks

スタートアップ

IdentityServerは、ミドルウェアとサービスの組み合わせです。すべての設定はスタートアップクラスで行われます。

サービスの設定

IdentityServerサービスをDIシステムに追加するには、次の関数を呼び出します。:

public void ConfigureServices(IServiceCollection services)
{
    var builder = services.AddIdentityServer();
}

オプションで、この呼び出しにオプションを渡すことができます。オプションの詳細については ここを 参照してください。

これはビルダーオブジェクトを返します。ビルダーオブジェクトには、追加のサービスを結ぶ便利なメソッドが多数あります。

Key material

  • AddSigningCredential
    指定された鍵素材をさまざまなトークン作成/検証サービスに提供する署名鍵サービスを追加します。 X509Certificate2SigningCredential または証明書ストアからの証明書への参照を渡すことができます。
  • AddDeveloperSigningCredential
    起動時に一時的なキーマテリアルを作成します。これは、開発者が使用する証明書を持っていない場合のみのシナリオです。生成された鍵はファイルシステムに永続化され、サーバの再起動の間に安定した状態になります(渡すことで無効にすることができます false )。これは、開発中にクライアント/ apiメタデータキャッシュが同期しなくなった場合の問題を解決します。
  • AddValidationKey
    トークンを検証するためのキーを追加します。それらは内部トークンバリデーターによって使用され、ディスカバリー文書に表示されます。 X509Certificate2SigningCredential または証明書ストアからの証明書への参照を渡すことができます。これは、重要なロールオーバーシナリオに役立ちます。

In-Memory configuration stores

さまざまな「メモリー内」構成APIを使用すると、構成オブジェクトのメモリー内リストからIdentityServerを構成できます。これらの「インメモリ」コレクションは、ホスティングアプリケーションでハードコーディングすることも、構成ファイルやデータベースから動的にロードすることもできます。ただし、設計上、これらのコレクションはホスティングアプリケーションの起動時にのみ作成されます。

これらの構成APIの使用は、実行時に構成データをデータベースに動的に照会する必要がないプロトタイピング、開発、および/またはテストの際に使用するために設計されています。この構成のスタイルは、構成がほとんど変更されない場合や、値を変更する必要がある場合にアプリケーションを再起動する必要がある場合には、実動シナリオにも適しています。

  • AddInMemoryClients
    Registers IClientStore and ICorsPolicyService implementations based on the in-memory collection of Client configuration objects.
  • AddInMemoryIdentityResources
    Registers IResourceStore implementation based on the in-memory collection of IdentityResource configuration objects.
  • AddInMemoryApiResources
    Registers IResourceStore implementation based on the in-memory collection of ApiResource configuration objects.

Test stores

The TestUser class models a user, their credentials, and claims in IdentityServer. Use of TestUser is simiar to the use of the "in-memory" stores in that it is intended for when prototyping, developing, and/or testing. The use of TestUser is not recommended in production.

  • AddTestUsers
    Registers TestUserStore based on a collection of TestUser objects. TestUserStore is used by the default quickstart UI. Also registers implementations of IProfileService and IResourceOwnerPasswordValidator.

Additional services

  • AddExtensionGrantValidator
    Adds IExtensionGrantValidator implementation for use with extension grants.
  • AddSecretParser
    Adds ISecretParser implementation for parsing client or API resource credentials.
  • AddSecretValidator
    Adds ISecretValidator implementation for validating client or API resource credentials against a credential store.
  • AddResourceOwnerValidator
    Adds IResourceOwnerPasswordValidator implementation for validating user credentials for the resource owner password credentials grant type.
  • AddProfileService
    Adds IProfileService implementation for connecting to your custom user profile store. The DefaultProfileService class provides the default implementation which relies upon the authentication cookie as the only source of claims for issuing in tokens.
  • AddAuthorizeInteractionResponseGenerator
    Adds IAuthorizeInteractionResponseGenerator implementation to customize logic at authorization endpoint for when a user must be shown a UI for error, login, consent, or any other custom page. The AuthorizeInteractionResponseGenerator class provides a default implementation, so consider deriving from this existing class if you need to augment the existing behavior.
  • AddCustomAuthorizeRequestValidator
    Adds ICustomAuthorizeRequestValidator implementation to customize request parameter validation at the authorization endpoint.
  • AddCustomTokenRequestValidator
    Adds ICustomTokenRequestValidator implementation to customize request parameter validation at the token endpoint.
  • AddRedirectUriValidator
    Adds IRedirectUriValidator implementation to customize redirect URI validation.
  • AddAppAuthRedirectUriValidator
    Adds a an "AppAuth" (OAuth 2.0 for Native Apps) compliant redirect URI validator (does strict validation but also allows http://127.0.0.1 with random port).
  • AddJwtBearerClientAuthentication
    Adds support for client authentication using JWT bearer assertions.

Caching

Client and resource configuration data is used frequently by IdentityServer. If this data is being loaded from a database or other external store, then it might be expensive to frequently re-load the same data.

  • AddInMemoryCaching
    To use any of the caches described below, an implementation of ICache<T> must be registered in DI. This API registers a default in-memory implementation of ICache<T> that's based on ASP.NET Core's MemoryCache.
  • AddClientStoreCache
    Registers a IClientStore decorator implementation which will maintain an in-memory cache of Client configuration objects. The cache duration is configurable on the Caching configuration options on the IdentityServerOptions.
  • AddResourceStoreCache
    Registers a IResourceStore decorator implementation which will maintain an in-memory cache of IdentityResource and ApiResource configuration objects. The cache duration is configurable on the Caching configuration options on the IdentityServerOptions.
  • AddCorsPolicyCache
    Registers a ICorsPolicyService decorator implementation which will maintain an in-memory cache of the results of the CORS policy service evaluation. The cache duration is configurable on the Caching configuration options on the IdentityServerOptions.

Further customization of the cache is possible:

The default caching relies upon the ICache<T> implementation. If you wish to customize the caching behavior for the specific configuration objects, you can replace this implementation in the dependency injection system.

The default implementation of the ICache<T> itself relies upon the IMemoryCache interface (and MemoryCache implementation) provided by .NET. If you wish to customize the in-memory caching behavior, you can replace the IMemoryCache implementation in the dependency injection system.

Configuring the pipeline

You need to add IdentityServer to the pipeline by calling:

public void Configure(IApplicationBuilder app)
{
    app.UseIdentityServer();
}

注釈

UseIdentityServer includes a call to UseAuthentication, so it's not necessary to have both.

There is no additional configuration for the middleware.

Be aware that order matters in the pipeline. For example, you will want to add IdentitySever before the UI framework that implements the login screen.

リソースの定義

システムで最初に定義するのは、保護したいリソースです。プロファイルデータやメールアドレス、APIへのアクセスなど、ユーザーの身元情報になります。

注釈

C#オブジェクトモデルを使用してリソースを定義することも、データストアからロードすることもできます。IResourceStoreこれらの低レベルの詳細に関する取引の実装。このドキュメントでは、インメモリ実装を使用しています。

アイデンティティリソースの定義

アイデンティティリソースは、ユーザーのID、名前、電子メールアドレスなどのデータです。アイデンティティーリソースには一意の名前があり、任意のクレームタイプを割り当てることができます。これらの主張は、ユーザーのIDトークンに含まれます。クライアントは、このscopeパラメータを使用してIDリソースへのアクセスを要求します。

OpenID Connect仕様では、いくつかの標準的なアイデンティティリソースが指定されています。最低要件は、ユーザーの一意のIDを発行するためのサポートを提供することです(サブジェクトIDとも呼ばれます)。これは、以下のような標準的なアイデンティティリソースを公開することによって行われopenidます。

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId()
    };
}

IdentityResourcesのクラスは、仕様(OpenIDの、電子メール、プロフィール、電話、およびアドレス)で定義されたすべてのスコープをサポートしています。それらをすべてサポートしたい場合は、サポートされているIDリソースのリストに追加することができます。

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Email(),
        new IdentityResources.Profile(),
        new IdentityResources.Phone(),
        new IdentityResources.Address()
    };
}

カスタムIDリソースの定義

カスタムIDリソースを定義することもできます。新しいIdentityResourceクラスを作成し、名前とオプションで表示名と説明を指定し、このリソースが要求されたときにアイデンティティトークンに含めるユーザークレームを定義します。

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    var customProfile = new IdentityResource(
        name: "custom.profile",
        displayName: "Custom profile",
        claimTypes: new[] { "name", "email", "status" });

    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        customProfile
    };
}

アイデンティティリソース設定の詳細については、リファレンスセクションを参照してください。

APIリソースの定義

クライアントがAPIのアクセストークンを要求できるようにするには、APIリソースを定義する必要があります。

APIのトークンにアクセスするには、スコープとして登録する必要があります。今回スコープのタイプはResourceタイプです:

public static IEnumerable<ApiResource> GetApis()
{
    return new[]
    {
        // simple API with a single scope (in this case the scope name is the same as the api name)
        new ApiResource("api1", "Some API 1"),

        // expanded version if more control is needed
        new ApiResource
        {
            Name = "api2",

            // secret for using introspection endpoint
            ApiSecrets =
            {
                new Secret("secret".Sha256())
            },

            // include the following using claims in access token (in addition to subject id)
            UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Email },

            // this API defines two scopes
            Scopes =
            {
                new Scope()
                {
                    Name = "api2.full_access",
                    DisplayName = "Full access to API 2",
                },
                new Scope
                {
                    Name = "api2.read_only",
                    DisplayName = "Read only access to API 2"
                }
            }
        }
    };
}

APIリソース設定の詳細については、 参照 セクションを参照してください。

注釈

リソースによって定義されたユーザークレームは、 IProfileService の拡張性ポイントによって読み込まれます。

クライアントの定義

クライアントは、IDサーバーからトークンを要求できるアプリケーションを表します。

詳細は異なりますが、通常はクライアントに対して以下の共通設定を定義します。

  • 一意のクライアントID
  • 必要なら秘密
  • トークンサービスとの許可された対話(許可タイプと呼ばれる)
  • アイデンティティおよび/またはアクセストークンが送信される(リダイレクトURIと呼ばれる)ネットワークロケーションは、
  • クライアントがアクセスできるスコープのリスト(別名リソース)

注釈

実行時に、クライアントは.htmlの実装を介して取得されますIClientStore。これにより、設定ファイルやデータベースなどの任意のデータソースから読み込むことができます。このドキュメントでは、クライアントストアのメモリ内バージョンを使用します。拡張メソッドを使用しConfigureServicesてインメモリストアを配線することができAddInMemoryClientsます。

サーバ間通信のためのクライアントの定義

このシナリオでは、対話ユーザーは存在しません。サービス(別名クライアント)はAPI(別名スコープ)と通信したいと考えています。

public class Clients
{
    public static IEnumerable<Client> Get()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "service.client",
                ClientSecrets = { new Secret("secret".Sha256()) },

                AllowedGrantTypes = GrantTypes.ClientCredentials,
                AllowedScopes = { "api1", "api2.read_only" }
            }
        };
    }
}

ユーザ認証と委任されたアクセスとAPIのためのブラウザベースのJavaScriptクライアント(例えばSPA)の定義

このクライアントは、暗黙のフローを使用して、JavaScriptからIDとアクセストークンを要求します。

var jsClient = new Client
{
    ClientId = "js",
    ClientName = "JavaScript Client",
    ClientUri = "http://identityserver.io",

    AllowedGrantTypes = GrantTypes.Implicit,
    AllowAccessTokensViaBrowser = true,

    RedirectUris =           { "http://localhost:7017/index.html" },
    PostLogoutRedirectUris = { "http://localhost:7017/index.html" },
    AllowedCorsOrigins =     { "http://localhost:7017" },

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email,

        "api1", "api2.read_only"
    }
};

認証とデリゲートされたAPIアクセスを使用するためのサーバー側Webアプリケーション(MVCなど)の定義

対話型サーバー側(またはネイティブデスクトップ/モバイル)アプリケーションは、ハイブリッドフローを使用します。このフローは、アクセストークンがバックチャネルコールのみで送信されるため(バックプレーントークンにアクセスできるため)、最高のセキュリティを提供します。

var mvcClient = new Client
{
    ClientId = "mvc",
    ClientName = "MVC Client",
    ClientUri = "http://identityserver.io",

    AllowedGrantTypes = GrantTypes.Hybrid,
    AllowOfflineAccess = true,
    ClientSecrets = { new Secret("secret".Sha256()) },

    RedirectUris =           { "http://localhost:21402/signin-oidc" },
    PostLogoutRedirectUris = { "http://localhost:21402/" },
    FrontChannelLogoutUri =  "http://localhost:21402/signout-oidc",

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email,

        "api1", "api2.read_only"
    },
};

サインイン

IdentityServerがユーザーの代わりにトークンを発行するには、そのユーザーはIdentityServerにサインインする必要があります。

ログインユーザーインターフェイスとID管理システム

dentityServerは、ユーザ認証のためのユーザインタフェースまたはユーザデータベースを提供しません。これらはあなたが提供したり開発したりすることが期待されるものです。

基本的なUI(ログイン、ログアウト、同意、管理)の出発点が必要な場合は、クイックスタートUIを使用できます。

クイックスタートUIは、メモリ内のデータベースに対してユーザーを認証します。これらのビットを実際のユーザーストアへのアクセスで置き換えます。ASP.NET IDを使用するサンプルがあります。

ログインワークフロー

IdentityServerが承認エンドポイントで要求を受信し、そのユーザーが認証されていない場合、ユーザーは構成済みのログインページにリダイレクトされます。オプションのUserInteraction設定を使用してログインページへのパスをIdentityServerに通知する必要があります(デフォルトは/account/login)。returnUrlパラメータは、ログインが完了すると、ユーザーをリダイレクトする必要がありますログインページを知らせる渡されます。

_images/signin_flow.png

注釈

パラメータを介してオープンリダイレクト攻撃に注意してreturnUrlください。あなたはreturnUrlよく知られている場所を参照することを検証する必要があります。パラメータの検証には、API のインタラクションサービスを参照してreturnUrlください。

ログインコンテキスト

ログイン・ページでは、ログイン・エクスペリエンス(クライアント、プロンプト・パラメーター、IdPヒントなど)をカスタマイズするために、要求のコンテキストに関する情報が必要な場合があります。これはGetAuthorizationContextAsync、インタラクションサービスの APIを介して利用可能になります。

Sign-in with External Identity Providers

ASP.NETコアは、外部認証に柔軟に対応します。これにはいくつかのステップが必要です。

注釈

ASP.NET IDを使用している場合、基礎となる技術的詳細の多くはあなたから隠されています。また、Microsoftのドキュメントを読み、ASP.NET IDのクイックスタートを行うことをお勧めします。

外部プロバイダの認証ハンドラの追加

外部プロバイダと通信するために必要なプロトコル実装は、認証ハンドラにカプセル化されています。一部のプロバイダは独自のプロトコル(Facebookなどのソーシャルプロバイダなど)を使用しており、一部のプロトコルではOpenID Connect、WS-Federation、SAML2pなどの標準プロトコルを使用しています。

外部認証を追加して構成する手順については、このクイックスタートを参照してください。

クッキーの役割

外部認証ハンドラの1つのオプションが呼び出されますSignInScheme。例:

services.AddAuthentication()
    .AddGoogle("Google", options =>
    {
        options.SignInScheme = "scheme of cookie handler to use";

        options.ClientId = "...";
        options.ClientSecret = "...";
    })

サインイン方式は、外部プロバイダの結果を一時的に保存するクッキーハンドラの名前を指定します。通常、外部認証プロセスを完了するまで、数回のリダイレクトが行われるため、これは必要です。

これがあまり一般的でない場合、IdentityServerはこの外部プロバイダワークフロー専用のCookieハンドラを登録します。スキームはIdentityServerConstants.ExternalCookieAuthenticationScheme定数によって表されます。外部のCookieハンドラを使用する場合は、SignInScheme上記の値をIdentityServerConstants.ExternalCookieAuthenticationScheme定数に割り当てます。

services.AddAuthentication()
    .AddGoogle("Google", options =>
    {
        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

        options.ClientId = "...";
        options.ClientSecret = "...";
    })

次のように独自のカスタムCookieハンドラを登録することもできます。

services.AddAuthentication()
    .AddCookie("YourCustomScheme")
    .AddGoogle("Google", options =>
    {
        options.SignInScheme = "YourCustomScheme";

        options.ClientId = "...";
        options.ClientSecret = "...";
    })

注釈

特別なシナリオでは、外部のCookieメカニズムを短絡し、外部のユーザーをメインのCookieハンドラに直接転送することもできます。これには通常、外部ハンドラでイベントを処理して、外部IDソースから正しいクレーム変換を実行する必要があります。

認証ハンドラのトリガ

(またはMVCを使用して)ChallengeAsync拡張メソッドをHttpContext使用して外部認証ハンドラを呼び出しChallengeResultます。

通常、コールバックページへのパスや簿記のプロバイダ名など、チャレンジ操作にいくつかのオプションを渡します。

var callbackUrl = Url.Action("ExternalLoginCallback");

var props = new AuthenticationProperties
{
    RedirectUri = callbackUrl,
    Items =
    {
        { "scheme", provider },
        { "returnUrl", returnUrl }
    }
};

return Challenge(provider, props);

コールバックの処理とユーザのサインイン

コールバックページでは、一般的なタスクは次のとおりです。

  • 外部プロバイダから返されたIDを調べます。
  • そのユーザーに対処する方法を決定します。これは、新規ユーザーまたは再帰ユーザーの場合は、これが実際の状況に基づいて異なる可能性があります。
  • 新しいユーザーは、許可される前に追加の手順とUIが必要になることがあります。
  • おそらく外部プロバイダーにリンクされている新しい内部ユーザーアカウントを作成します。
  • 保管したい外部クレームを保管してください。
  • 一時的なクッキーを削除する
  • ユーザーにサインインする

外部IDの検査

// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
    throw new Exception("External authentication error");
}

// retrieve claims of the external user
var externalUser = result.Principal;
if (externalUser == null)
{
    throw new Exception("External authentication error");
}

// retrieve claims of the external user
var claims = externalUser.Claims.ToList();

// try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier
// depending on the external provider, some other claim type might be used
var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
if (userIdClaim == null)
{
    userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
}
if (userIdClaim == null)
{
    throw new Exception("Unknown userid");
}

var externalUserId = userIdClaim.Value;
var externalProvider = userIdClaim.Issuer;

// use externalProvider and externalUserId to find your user, or provision a new user

クリーンアップとサインイン:

// issue authentication cookie for user
await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, props, additionalClaims.ToArray());

// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

// validate return URL and redirect back to authorization endpoint or a local page
if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
{
    return Redirect(returnUrl);
}

return Redirect("~/");

State, URL length, and ISecureDataFormat

サインインのために外部プロバイダーにリダイレクトするとき、クライアントアプリケーションからの頻繁な状態は往復する必要があります。これは、クライアントを離れる前に状態がキャプチャされ、ユーザーがクライアントアプリケーションに戻るまで保持されることを意味します。OpenID Connectを含む多くのプロトコルは、要求の一部としてパラメータとして何らかの状態を渡すことを許可し、アイデンティティプロバイダはその状態を応答に返します。ASP.NET Coreによって提供されるOpenID Connect認証ハンドラは、このプロトコルの機能を利用しており、これがreturnUrl上記の機能を実装する方法です。

リクエストパラメータに状態を格納する際の問題は、リクエストURLが(2000文字の共通の制限を超えて)大きくなりすぎる可能性があることです。OpenID Connect認証ハンドラは、リクエストURLではなくサーバに状態を保存するための拡張ポイントを提供します。OpenIdConnectOptionsISecureDataFormat<AuthenticationProperties>で実装して設定することで、これを実装することができます。

幸いにも、IdentityServerはIDistributedCache、DIコンテナ(標準などMemoryDistributedCache)に登録されている実装に基づいて、この実装を提供します。IdentityServerが提供する安全なデータフォーマットの実装を使用するには、DIを設定AddOidcStateDataFormatterCacheするIServiceCollectionときに拡張メソッドを呼び出します。パラメータが渡されない場合、設定されたすべてのOpenID Connectハンドラは、IdentityServerが提供する安全なデータフォーマットの実装を使用します。

public void ConfigureServices(IServiceCollection services)
{
    // configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
    services.AddOidcStateDataFormatterCache();

    services.AddAuthentication()
        .AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
        {
            // ...
        })
        .AddOpenIdConnect("aad", "Azure AD", options =>
        {
            // ...
        })
        .AddOpenIdConnect("adfs", "ADFS", options =>
        {
            // ...
        });
}

特定のスキームのみを設定する場合は、それらのスキームをパラメータとして渡します。

public void ConfigureServices(IServiceCollection services)
{
    // configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
    services.AddOidcStateDataFormatterCache("aad", "demoidsrv");

    services.AddAuthentication()
        .AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
        {
            // ...
        })
        .AddOpenIdConnect("aad", "Azure AD", options =>
        {
            // ...
        })
        .AddOpenIdConnect("adfs", "ADFS", options =>
        {
            // ...
        });
}

Windows認証

サポートされているプラ​​ットフォームでは、Windows認証(Active Directoryなど)を使用してIdentityServerを使用してユーザーを認証できます。現在、Windows認証は、IdentityServerを次の方法でホストする場合に使用できます。

  • IISとIIS統合パッケージを使用するWindows上のKestrel
  • Windows上のHTTP.sysサーバー

いずれの場合も、スキームChallengeAsyncのHttpContext使用でAPIを使用することによってWindows認証がトリガーされます"Windows"。クイックスタートUIのアカウントコントローラには、必要なロジックが実装されています。

Kestrelの使用

Kestrelを使用する場合は、IISの背後で実行し、IIS統合を使用する必要があります。

var host = new WebHostBuilder()
    .UseKestrel()
    .UseUrls("http://localhost:5000")
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

KestrelはWebHost.CreateDefaultBuilder、設定方法を使用するときに自動的に設定されますWebHostBuilder。

また、IIS(またはIIS Express)の仮想ディレクトリでWindowsと匿名認証を有効にする必要があります。

IIS統合レイヤーは、Windows認証ハンドラーをDIに構成し、認証サービスを介して呼び出すことができます。通常、IdentityServerではこの自動動作を無効にすることをお勧めします。これは以下で行われConfigureServicesます:

services.Configure<IISOptions>(iis =>
{
    iis.AuthenticationDisplayName = "Windows";
    iis.AutomaticAuthentication = false;
});

注釈

既定では、表示名は空白で、Windows認証ボタンはクイックスタートUIに表示されません。外部プロバイダの自動検出に頼っている場合は、表示名を設定する必要があります。

サインアウト

IdentityServerのサインアウトは、認証Cookieを削除するだけの簡単な方法ですが、完全なフェデレーションによるサインアウトを行うには、クライアントアプリケーション(さらにアップストリームのアイデンティティプロバイダ)にもユーザーを署名することを検討する必要があります。

ユーザーがログアウトしたことをクライアントに通知する

サインアウトプロセスの一環として、ユーザーがログアウトしたことをクライアントアプリケーションに通知する必要があります。IdentityServerは、サーバー側クライアント(MVCなど)、サーバー側クライアント(MVCなど)のバックチャネル仕様、ブラウザベースのJavaScriptクライアント(たとえばSPA、React、Angular など)のセッション管理仕様のフロントチャネル仕様をサポートしています、など)。

フロントチャネルサーバー側クライアント

Front-channel仕様でサーバー側クライアントアプリケーションから<iframe>ユーザーをサインアウトするには、IdentityServerの「ログアウト」ページで、ユーザーがログアウトしたことをクライアントに通知する必要があります。通知を受けたいクライアントは、FrontChannelLogoutUri設定値を設定する必要があります。IdentityServerは、ユーザーがログインしたクライアントを追跡GetLogoutContextAsyncし、IIdentityServerInteractionService(詳細)で呼び出されたAPIを提供します。このAPIは、ログアウトしたページがプロパティにレンダリングする必要LogoutRequestがあるSignOutIFrameUrlプロパティを持つオブジェクトを返します<iframe>。

バックチャネルサーバー側のクライアント

バックチャネル仕様を使用してサーバー側のクライアントアプリケーションからユーザーをサインアウトするにはSignOutIFrameUrl、IdentityServer のエンドポイントが自動的にサーバー間の呼び出しをトリガーし、署名済みのサインアウト要求をクライアントに渡します。つまり、フロントチャネルクライアントがなくても、IdentityServerの「ログアウト」ページで<iframe>はSignOutIFrameUrl、前述のように「to 」をレンダリングする必要があります。通知を受けたいクライアントは、BackChannelLogoutUri設定値を設定する必要があります。

ブラウザベースのJavaScriptクライアント

セッション管理仕様がどのように設計されているかを考えると、これらのクライアントにユーザーがログアウトしたことを通知するために必要なことは、IdentityServerでは特別なことは何もありません。ただし、クライアントはcheck_session_iframeで監視を実行する必要があり、これはoidc-client JavaScriptライブラリによって実装されます。

クライアントアプリケーションによって開始サインアウト

ログアウトがクライアントアプリケーションによって開始された場合、クライアントは最初にエンドセッションエンドポイントにユーザーをリダイレクトしました。エンドセッションエンドポイントでの処理では、ログアウトページへのリダイレクトを介していくつかの一時的な状態(たとえば、クライアントのポストログアウトリダイレクトuri)が維持される必要があります。この状態はログアウトページで使用することができ、状態の識別子はlogoutIdパラメータを介してログアウトページに渡されます。

インタラクションサービスのGetLogoutContextAsyncAPIを使用して状態をロードできます。theに興味があるのは、ログアウトの要求が認証されたかどうかを示します。したがって、ユーザーにログアウトを促さないのは安全です。ShowSignoutPromptShowSignoutPrompt

デフォルトでは、この状態はlogoutId値を介して渡される保護されたデータ構造として管理されます。エンド・セッション・エンドポイントとログアウト・ページの間で他の永続性を使用する場合はIMessageStore<LogoutMessage>、DIで実装を実装して登録できます。

外部IDプロバイダのサインアウト

ユーザーがIdentityServer からサインアウトしているときに、外部IDプロバイダを使用してサインインした場合、外部プロバイダからもサインアウトする必要があります。サポートしているプロトコルと機能に依存するため、すべての外部プロバイダがログアウトをサポートするわけではありません。

サインアウトのために外部アイデンティティプロバイダにリダイレクトする必要があることを検出するには、通常idp、IdentityServerのクッキーに発行されたクレームを使用します。このクレームに設定された値AuthenticationSchemeは、対応する認証ミドルウェアの値です。サインアウト時に、この申し立ては外部からのサインアウトが必要かどうかを知るために相談されます。

ユーザーを外部IDプロバイダにリダイレクトすることは、通常のサインアウトワークフローで既に必要とされているクリーンアップと状態管理のために問題があります。IdentityServerで通常のサインアウトとクリーンアッププロセスを完了する唯一の方法は、外部アイデンティティプロバイダから、ログアウト後にユーザーをIdentityServerにリダイレクトするように要求することです。サポートしているプロトコルと機能に依存するため、外部プロバイダはすべてログアウト後リダイレクトをサポートしているわけではありません。

ログアウト時のワークフローでは、IdentityServerの認証Cookieを取り消し、外部プロバイダにリダイレクトしてログアウト後のリダイレクトを要求します。ログアウト後のリダイレクトは、ここで説明する必要なサインアウト状態(つまり、logoutIdパラメータ値)を維持する必要があります。外部プロバイダのログアウト後にIdentityServerにリダイレクトするには、ASP.NET CoreのAPI を使用RedirectUriするAuthenticationProperties場合に使用する必要がありSignOutAsyncます。たとえば、次のようにします。

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutInputModel model)
{
    // build a model so the logged out page knows what to display
    var vm = await _account.BuildLoggedOutViewModelAsync(model.LogoutId);

    var user = HttpContext.User;
    if (user?.Identity.IsAuthenticated == true)
    {
        // delete local authentication cookie
        await HttpContext.SignOutAsync();

        // raise the logout event
        await _events.RaiseAsync(new UserLogoutSuccessEvent(user.GetSubjectId(), user.GetName()));
    }

    // check if we need to trigger sign-out at an upstream identity provider
    if (vm.TriggerExternalSignout)
    {
        // build a return URL so the upstream provider will redirect back
        // to us after the user has logged out. this allows us to then
        // complete our single sign-out processing.
        string url = Url.Action("Logout", new { logoutId = vm.LogoutId });

        // this triggers a redirect to the external provider for sign-out
        return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
    }

    return View("LoggedOut", vm);
}

ユーザが外部プロバイダからログアウトしてリダイレクトされると、IdentityServerの通常のログアウト処理が実行され、logoutId必要なクリーンアップをすべて処理します。

Federated Sign-out

フェデレーション・サインアウトは、ユーザーが外部アイデンティティ・プロバイダを使用してIdentityServerにログインした後、ユーザーがIdentityServerに未知のワークフローを介してその外部アイデンティティ・プロバイダからログアウトする状況です。ユーザーがサインアウトすると、IdentityServerとIdentityServerを使用するすべてのアプリケーションからユーザーにサインインできるように、IdentityServerに通知すると便利です。

すべての外部IDプロバイダがフェデレーション・ログアウトをサポートしているわけではありませんが、ユーザーがログアウトしたことをクライアントに通知するメカニズムを提供します。この通知は通常<iframe>、外部IDプロバイダの「ログアウト」ページからのリクエストの形式で行われます。IdentityServerは次に、その外部のアイデンティティプロバイダの内部からの要求の形式で、すべてのクライアント(ここで説明したように)に通知する必要があります。<iframe><iframe>

フェデレーションによるサインアウトを特殊なケースにするのは、フェデレーションによるサインアウト要求がIdentityServerの通常のログアウトエンドポイントではないということです(通常のログアウトと比較した場合)。実際、各外部IdentityProviderは、IdentityServerホストとは異なるエンドポイントを持ちます。これは、各外部IDプロバイダが異なるプロトコルを使用し、各ミドルウェアが異なるエンドポイントでリッスンするという事実によるものです。

これらのすべての要因の正味の効果は、通常のサインアウトワークフローと同様にレンダリングされる「ログアウト」ページがないことです。つまり、IdentityServerのクライアントへのサインアウト通知が欠落しています。フェデレーション・ログアウトを達成するために必要な通知を表示するために、これらのフェデレーション・ログアウト・エンドポイントごとにコードを追加する必要があります。

幸い、IdentityServerにはすでにこのコードが含まれています。要求がIdentityServerに来て、外部認証プロバイダのハンドラを起動すると、これらは連合サインアウト要求であり、彼らがしている場合、それは自動的に同じをレンダリングする場合、IdentityServerは検出し<iframe>てサインアウトするために、ここで説明しました。簡単に言えば、連合サインアウトは自動的にサポートされています。

Federation Gateway

一般的なアーキテクチャは、いわゆるフェデレーションゲートウェイです。このアプローチでは、IdentityServerは1つ以上の外部IDプロバイダへのゲートウェイとして機能します。

_images/federation_gateway.png

このアーキテクチャには次の利点があります。

  • あなたのアプリケーションは、1つのトークンサービス(ゲートウェイ)について知っているだけで、外部プロバイダへの接続に関するすべての詳細が隠されています。これは、アプリケーションを更新することなく、外部プロバイダを追加または変更できることを意味します。
  • (外部サービスプロバイダーとは対照的に)ゲートウェイを制御します。これは、変更を加えることができ、外部プロバイダーが自分のサービスに対して行う変更からアプリケーションを保護できることを意味します。
  • ほとんどの外部プロバイダは、クレームおよびクレームタイプの固定セットのみをサポートしています。ゲートウェイを中央に置くことで、プロバイダからの応答をドメイン固有のID情報を変換/追加/修正することができます。
  • 一部のプロバイダはアクセストークン(ソーシャルプロバイダなど)をサポートしていません。ゲートウェイはAPIについて知っているため、外部IDに基づいてアクセストークンを発行できます。
  • 一部のプロバイダは、接続するアプリケーションの数によって料金を請求します。ゲートウェイは、外部プロバイダへの単一のアプリケーションとして機能します。内部的には、必要な数のアプリケーションに接続できます。
  • 一部のプロバイダはプロプライエタリプロトコルを使用したり、標準的なプロトコルに独自の変更を加えました。ゲートウェイでは、それに対処する必要がある場所は1つだけです。
  • 1つの場所ですべての認証(内部または外部)を強制することで、アイデンティティマッピングに関する膨大な柔軟性を提供し、すべてのアプリケーションに安定したIDを提供し、新しい要件を処理します

言い換えれば、フェデレーションゲートウェイを所有することで、アイデンティティインフラストラクチャを大いに制御できます。また、ユーザーの身元が最も重要な資産の1つなので、ゲートウェイを制御することをお勧めします。

実装

私たちのクイックスタートUIには、以下の機能の一部を利用しています。また、外部認証クイックスタートと外部プロバイダに関するドキュメントもチェックしてください。

  • IdentityServerアプリケーションに認証ハンドラを追加することにより、外部IDプロバイダのサポートを追加できます。
  • これらの外部プロバイダーを呼び出すことによってプログラムでクエリできますIAuthenticationSchemeProvider。これにより、登録された外部プロバイダに基づいてログインページを動的にレンダリングできます。
  • 私たちのクライアント設定モデルでは、利用可能なプロバイダをクライアントごとに制限することができます(IdentityProviderRestrictionsプロパティを使用する)。
  • またEnableLocalLogin、クライアントのプロパティを使用して、ユーザー名/パスワード入力をレンダリングするかどうかをUIに伝えることもできます。
  • 私たちのクイックスタートUIは、すべての外部認証呼び出しを単一のコールバック(クラスを参照ExternalLoginCallbackしてくださいAccountController)を通じてファンネルします。これにより、後処理のための単一のポイントが可能になります。

APIの保護

IdentityServerはデフォルトで JWT (JSON Webトークン)形式のアクセストークンを発行します。

JWTのトークンを検証するための関連プラットフォームはすべて今日サポートされています。JWTライブラリの一覧は here からご覧いただけます。人気のあるライブラリは、例えば:

ASP.NET CoreベースのAPIを保護することは、DIでJWTベアラ認証ハンドラを構成し、認証ミドルウェアをパイプラインに追加することだけです。

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                // base-address of your identityserver
                options.Authority = "https://demo.identityserver.io";

                // name of the API resource
                options.Audience = "api1";
            });
    }

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {
        app.UseAuthentication();
        app.UseMvc();
    }
}

IdentityServer認証ハンドラ

私たちの認証ハンドラは上記のハンドラと同じ目的を果たします(実際にはMicrosoft JWTライブラリを内部的に使用します)が、いくつかの追加機能を追加しています:

  • JWTと参照トークンの両方のサポート
  • 参照トークンのための拡張可能なキャッシング
  • 統一された構成モデル
  • 有効範囲の検証

最も単純なケースでは、ハンドラの設定は上記のスニペットと非常に似ています:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
            .AddIdentityServerAuthentication(options =>
            {
                // base-address of your identityserver
                options.Authority = "https://demo.identityserver.io";

                // name of the API resource
                options.ApiName = "api1";
            });
    }

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
    {
        app.UseAuthentication();
        app.UseMvc();
    }
}

あなたは nuget または github からパッケージを取得することができます。

参照トークンのサポート

受信したトークンがJWTでない場合、ミドルウェアは検出文書にあるイントロスペクションエンドポイントに連絡してトークンを検証します。イントロスペクションエンドポイントでは認証が必要なため、設定済みのAPIシークレットを提供する必要があります。

.AddIdentityServerAuthentication(options =>
{
    // base-address of your identityserver
    options.Authority = "https://demo.identityserver.io";

    // name of the API resource
    options.ApiName = "api1";
    options.ApiSecret = "secret";
})

通常、着信要求ごとにイントロスペクションエンドポイントへのラウンドトリップを実行する必要はありません。ミドルウェアには、次のように有効にできるビルトインキャッシュがあります。

.AddIdentityServerAuthentication(options =>
{
    // base-address of your identityserver
    options.Authority = "https://demo.identityserver.io";

    // name of the API resource
    options.ApiName = "api1";
    options.ApiSecret = "secret";

    options.EnableCaching = true;
    options.CacheDuration = TimeSpan.FromMinutes(10); // that's the default
})

ハンドラは、DIコンテナに登録されている IDistributedCache 実装(たとえば、標準の MemoryDistributedCache )を使用します。

スコープの検証

ApiNameのプロパティをチェックトークンは、一致する視聴者(又はショートがある場合aud)請求項を。

IdentityServerでは、APIを複数のスコープに細分することもできます。細分性が必要な場合は、ASP.NETコア認可ポリシーシステムを使用してスコープを確認できます。

グローバルポリシーの作成:

services
    .AddMvcCore(options =>
    {
        // require scope1 or scope2
        var policy = ScopePolicy.Create("scope1", "scope2");
        options.Filters.Add(new AuthorizeFilter(policy));
    })
    .AddJsonFormatters()
    .AddAuthorization();

スコープポリシーの作成:

services.AddAuthorization(options =>
{
    options.AddPolicy("myPolicy", builder =>
    {
        // require scope1
        builder.RequireScope("scope1");
        // and require scope2 or scope3
        builder.RequireScope("scope2", "scope3");
    });
});

デプロイ

あなたのアイデンティティサーバーがあるだけ IdentityServerミドルウェアを含む、標準的なASP.NET Coreアプリケーション。まずパブリッシュとデプロイメントに関する公式Microsoftのドキュメントをお読みください。

典型的なアーキテクチャ

通常、高可用性のためにIdentityServerの配備を設計します。

_images/deployment.png

IdentityServer自体はステートレスなので、サーバの親和性は必要ありませんが、インスタンス間で共有する必要があるデータがあります。

設定データ

これには、通常、

  • リソース
  • クライアント
  • スタートアップ設定、例えばキーマテリアル、外部プロバイダ設定など

そのデータを格納する方法は、使用環境によって異なります。構成データがほとんど変更されない状況では、メモリ内のストアとコードまたは構成ファイルを使用することをお勧めします。

高度に動的な環境(Saasなど)では、データベースまたは構成サービスを使用して構成を動的にロードすることを推奨します。

IdentityServerは、コード構成と構成ファイル(ここを参照)をそのまま使用できます。データベースの場合は、Entity Framework Coreベースのデータベースをサポートします。

また、実装することで独自の構成ストアを構築することができますIResourceStoreし、IClientStore。

鍵素材

スタートアップコンフィギュレーションのもう一つの重要な部分は、キーマテリアルです。キーマテリアルと暗号の詳細については、ここを参照してください。

運用データ

特定の操作では、IdentityServerに状態を保存するための永続ストアが必要です。これには次のものがあります。

  • 承認コードを発行する
  • 参照およびリフレッシュトークンの発行
  • 同意書を保管する

運用データの保存に従来のデータベースを使用することも、Redisのような永続性機能を備えたキャッシュを使用することもできます。上記のEFコア実装は、運用データもサポートしています。

またIPersistedGrantStore、デフォルトでIdentityServerがメモリ内バージョンをインジェクトするように実装することで、独自のカスタムストレージメカニズムのサポートを実装することもできます。

ASP.NET Coreデータ保護

ASP.NET Core自体には、クッキー、状態文字列などの機密データを保護するための共有キーマテリアルが必要です。 ここの 公式ドキュメントを参照してください。

上記の永続ストアの1つを再利用するか、可能であれば共有ファイルのような単純なものを使用することができます。

Logging

IdentityServerは、ASP.NET Coreが提供する標準のログ機能を使用します。Microsoftのドキュメントには、優れたイントロと組み込みのロギングプロバイダの説明があります。

ログレベルの使用に関するMicrosoftのガイドラインにほぼ従います。

  • Trace 開発者だけが問題をトラブルシューティングするための貴重な情報です。これらのメッセージには、トークンなどの機密性の高いアプリケーションデータが含まれている可能性があり、運用環境で有効にするべきではありません。
  • Debug内部の流れに従い、何らかの決定がなされた理由を理解するため。開発およびデバッグ中に短期間の有用性があります。
  • Informationアプリケーションの一般的な流れを追跡するため。これらのログには通常、長期的な価値があります。
  • Warningアプリケーションフローの異常または予期しないイベントの場合。これらには、アプリケーションの停止を引き起こさないエラーやその他の条件が含まれる場合がありますが、調査が必要な場合があります。
  • Error処理できないエラーや例外について 例:プロトコル要求の検証に失敗しました。
  • Critical直ちに注意が必要な障害の場合。例:不足しているストア実装、無効なキーマテリアル...

Serilogのセットアップ

私たちは個人的にはSerilogが大好きです。試してみる。

ASP.NET Core 2.0+

次の設定では、Serilog.AspNetCoreとSerilog.Sinks.Consoleパッケージが必要です。

public class Program
{
    public static void Main(string[] args)
    {
        Console.Title = "IdentityServer4";

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
            .MinimumLevel.Override("System", LogEventLevel.Warning)
            .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
            .Enrich.FromLogContext()
            .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
            .CreateLogger();

        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args)
    {
        return WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseSerilog()
                .Build();
    }
}

ASP.NET Core 1.0, 1.1

次の設定では、Serilog.Extensions.Logging``と ``Serilog.Sinks.Console パッケージが必要です。

public class Program
{
    public static void Main(string[] args)
    {
        Console.Title = "IdentityServer4";

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
            .MinimumLevel.Override("System", LogEventLevel.Warning)
            .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
            .Enrich.FromLogContext()
            .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
            .CreateLogger();

        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args)
    {
        return WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .ConfigureLogging(builder =>
                {
                    builder.ClearProviders();
                    builder.AddSerilog();
                })
                .Build();
    }
}

イベント

ログはより低レベルの "printf"スタイルですが、イベントはIdentityServerの特定の操作に関するより高いレベルの情報を表します。イベントは構造化されたデータで、イベントID、成功/失敗情報、カテゴリ、詳細が含まれます。これにより、それらを照会および分析し、さらなる処理に使用できる有用な情報を抽出することが容易になります。

イベントは、ELK、Seq、Splunkなどのイベントストアでうまく機能します。

Emitting events

イベントはデフォルトで有効になっていませんが、ConfigureServicesメソッド内でグローバルに設定することができます。例:

services.AddIdentityServer(options =>
{
    options.Events.RaiseSuccessEvents = true;
    options.Events.RaiseFailureEvents = true;
    options.Events.RaiseErrorEvents = true;
});

イベントを発生させるにIEventServiceは、DIコンテナからRaiseAsyncメソッドを呼び出し、メソッドを呼び出します。

public async Task<IActionResult> Login(LoginInputModel model)
{
    if (_users.ValidateCredentials(model.Username, model.Password))
    {
        // issue authentication cookie with subject ID and username
        var user = _users.FindByUsername(model.Username);
        await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username));
    }
    else
    {
        await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
    }
}

カスタムシンク

デフォルトのイベントシンクはイベントクラスをJSONにシリアライズし、ASP.NET Coreロギングシステムに転送します。カスタム・イベント・ストアに接続する場合は、IEventSinkインターフェースを実装し、DIに登録してください。

次の例では、Seqを使用してイベントを発行しています。

 public class SeqEventSink : IEventSink
{
    private readonly Logger _log;

    public SeqEventSink()
    {
        _log = new LoggerConfiguration()
            .WriteTo.Seq("http://localhost:5341")
            .CreateLogger();
    }

    public Task PersistAsync(Event evt)
    {
        if (evt.EventType == EventTypes.Success ||
            evt.EventType == EventTypes.Information)
        {
            _log.Information("{Name} ({Id}), Details: {@details}",
                evt.Name,
                evt.Id,
                evt);
        }
        else
        {
            _log.Error("{Name} ({Id}), Details: {@details}",
                evt.Name,
                evt.Id,
                evt);
        }

        return Task.CompletedTask;
    }
}

Serilog.Sinks.Seq上記のコードを動作させるためにあなたのホストにパッケージを追加してください。

ビルトインイベント

IdentityServerには、次のイベントが定義されています。

ApiAuthenticationFailureEvent & ApiAuthenticationSuccessEvent
イントロスペクションエンドポイントで成功または失敗したAPI認証のために生成されます。
ClientAuthenticationSuccessEvent & ClientAuthenticationFailureEvent
トークンエンドポイントで成功または失敗したクライアント認証のために生成されます。
TokenIssuedSuccessEvent & TokenIssuedFailureEvent
アイデンティティトークン、アクセストークン、リフレッシュトークン、および認証コードを要求する成功/失敗の試みに対して発生します。
TokenIntrospectionSuccessEvent & TokenIntrospectionFailureEvent
成功したトークンイントロスペクション要求に対して発生します。
TokenRevokedSuccessEvent
正常なトークン取り消し要求に対して発生します。
UserLoginSuccessEvent & UserLoginFailureEvent
成功した/失敗したユーザーログインのクイックスタートUIによって発生します。
UserLogoutSuccessEvent
成功したログアウト要求の場合に発生します。
ConsentGrantedEvent & ConsentDeniedEvent
同意UIで発生します。
UnhandledExceptionEvent
未処理の例外に対して発生します。
DeviceAuthorizationFailureEvent & DeviceAuthorizationSuccessEvent
Gets raised for successful/failed device authorization requests.

カスタムイベント

あなた自身のイベントを作成し、私たちのインフラを介してそれらを放出することができます。

Event派生クラスは、アクティビティID、タイムスタンプなどのコンテキスト情報を注入する基本クラスから派生する必要があります。派生クラスは、イベントコンテキストに固有の任意のデータフィールドを追加できます。

public class UserLoginFailureEvent : Event
{
    public UserLoginFailureEvent(string username, string error)
        : base(EventCategories.Authentication,
                "User Login Failure",
                EventTypes.Failure,
                EventIds.UserLoginFailure,
                error)
    {
        Username = username;
    }

    public string Username { get; set; }
}

Cryptography, Keys and HTTPS

IdentityServerは、その仕事をするためにいくつかの暗号化メカニズムに依存しています。

トークンの署名と検証

IdentityServerには、JWTの署名と検証に非対称キーのペアが必要です。この鍵ペアは、証明書/秘密鍵の組み合わせまたは生のRSA鍵にすることができます。どんな場合でも、SHA256でRSAをサポートする必要があります。

署名鍵と対応する検証部分の読み込みは、ISigningCredentialStoreとの実装によって行われますIValidationKeysStore。キーのロードをカスタマイズする場合は、これらのインターフェイスを実装してDIで登録することができます。

DIビルダーの拡張機能には、署名と検証キーを設定する便利な方法がいくつかあります。

署名鍵のロールオーバー

一度に1つの署名キーしか使用できませんが、ディスカバリドキュメントに複数の検証キーを発行できます。キーのロールオーバーに便利です。

ロールオーバは、通常次のように動作します。

  1. 新しい鍵素材をリクエスト/作成する
  2. 現在の検証キーに加えて新しい検証キーを発行します。AddValidationKeysビルダー拡張メソッドを使用することができます。
  3. すべてのクライアントとAPIは、次回ディスカバリドキュメントのローカルコピーを更新したときに、新しいキーについて学習する機会を得ます
  4. 一定の時間(例えば24時間)後に、すべてのクライアントおよびAPIは古いキー材料および新しいキー材料の両方を受け入れるべきである
  5. あなたが好きなだけ古い鍵の素材を保管しておいてください。おそらく、検証が必要な長寿命のトークンがあります
  6. 古い鍵素材が使用されなくなった場合には廃棄する
  7. すべてのクライアントとAPIは、次にディスカバリ文書のローカルコピーを更新したときに古いキーを「忘れる」

これには、クライアントとAPIがディスカバリ文書を使用する必要があります。また、構成を定期的に更新する機能も必要です。

データ保護

ASP.NETコア(またはMVCの偽造防止)のCookie認証は、ASP.NETコアデータ保護機能を使用します。展開シナリオに応じて、追加の設定が必要な場合があります。詳細については、Microsoftのドキュメントを参照してください。

HTTPS

私たちはHTTPSの使用を強制しませんが、プロダクションではIdentityServerとのすべての対話に必須です。

付与タイプ

付与タイプは、クライアントがIdentityServerとやり取りする方法を指定する方法です。OpenID ConnectとOAuth 2の仕様では、以下の付与タイプが定義されています。

  • Implicit
  • Authorization code
  • Hybrid
  • Client credentials
  • Resource owner password
  • Device flow
  • Refresh tokens
  • Extension grants

構成AllowedGrantTypes上のプロパティーを使用して、クライアントが使用できる許可タイプを指定できますClient。

クライアントは、2つ以上の認可タイプを使用するように構成できます(たとえば、ユーザー中心の操作の場合はハイブリッド、サーバー間の通信の場合はクライアント資格情報)。 GrantTypes このクラスは、典型的な補助金型の組み合わせから選択するために使用することができます。

Client.AllowedGrantTypes = GrantTypes.HybridAndClientCredentials;

許可タイプリストを手動で指定することもできます。

Client.AllowedGrantTypes =
{
    GrantType.Hybrid,
    GrantType.ClientCredentials,
    "my_custom_grant_type"
};

ブラウザのチャンネルを介してアクセストークンを送信する場合は、クライアントの設定で明示的に許可する必要があります。

Client.AllowAccessTokensViaBrowser = true;

注釈

セキュリティ上の理由から、すべての許可タイプの組み合わせが許可されるわけではありません。詳細は以下を参照してください。

残りの部分については、助成金の種類について簡単に説明し、使用する時期についても説明します。また、相違点の理解を深めるために、対応する仕様を読むことをお勧めします。

Client credentials

これは最も単純なグラント・タイプであり、サーバー間の通信に使用されます。トークンは、ユーザーではなくクライアントのために常に要求されます。

この許可タイプでは、トークン要求をトークンエンドポイントに送信し、クライアントを表すアクセストークンバックを取得します。クライアントは通常、クライアントIDと秘密情報を使用してトークンエンドポイントで認証する必要があります。

使用方法のサンプルについては、クライアントクレデンシャルのクイックスタートを参照してください。

Resource owner password

リソース所有者のパスワード付与タイプを使用すると、ユーザーの名前とパスワードをトークンエンドポイントに送信することによって、ユーザーの代わりにトークンを要求できます。これは「非対話型」認証と呼ばれ、一般的には推奨されません。

特定のレガシーまたはファーストパーティの統合シナリオには、このグラントタイプが便利な理由があるかもしれませんが、代わりにユーザー認証のために暗黙またはハイブリッドのような対話型フローを使用することが推奨されます。

See the Resource Owner Password Quick Start for a sample how to use it. You also need to provide code for the username/password validation which can be supplied by implementing the IResourceOwnerPasswordValidator interface. You can find more information about this interface here.

Implicit

The implicit grant type is optimized for browser-based applications. Either for user authentication-only (both server-side and JavaScript applications), or authentication and access token requests (JavaScript applications).

In the implicit flow, all tokens are transmitted via the browser, and advanced features like refresh tokens are thus not allowed.

This quickstart shows authentication for service-side web apps, and this shows JavaScript.

Authorization code

Authorization code flow was originally specified by OAuth 2, and provides a way to retrieve tokens on a back-channel as opposed to the browser front-channel. It also support client authentication.

While this grant type is supported on its own, it is generally recommended you combine that with identity tokens which turns it into the so called hybrid flow. Hybrid flow gives you important extra features like signed protocol responses.

Hybrid

Hybrid flow is a combination of the implicit and authorization code flow - it uses combinations of multiple grant types, most typically code id_token.

In hybrid flow the identity token is transmitted via the browser channel and contains the signed protocol response along with signatures for other artifacts like the authorization code. This mitigates a number of attacks that apply to the browser channel. After successful validation of the response, the back-channel is used to retrieve the access and refresh token.

This is the recommended flow for native applications that want to retrieve access tokens (and possibly refresh tokens as well) and is used for server-side web applications and native desktop/mobile applications.

See this quickstart for more information about using hybrid flow with MVC.

Device flow

Device flow is designed for browserless and input constrained devices, where the device is unable to securely capture user credentials. This flow outsources user authentication and consent to an external device (e.g. a smart phone).

This flow is typically used by IoT devices and can request both identity and API resources.

Refresh tokens

Refresh tokens allow gaining long lived access to APIs.

You typically want to keep the lifetime of access tokens as short as possible, but at the same time don't want to bother the user over and over again with doing a front-channel roundtrips to IdentityServer for requesting new ones.

Refresh tokens allow requesting new access tokens without user interaction. Every time the client refreshes a token it needs to make an (authenticated) back-channel call to IdentityServer. This allows checking if the refresh token is still valid, or has been revoked in the meantime.

Refresh tokens are supported in hybrid, authorization code, device flow and resource owner password flows. To request a refresh token, the client needs to include the offline_access scope in the token request (and must be authorized to request for that scope).

Extension grants

Extension grants allow extending the token endpoint with new grant types. See this for more details.

Incompatible grant types

Some grant type combinations are forbidden:

  • Mixing implicit and authorization code or hybrid would allow a downgrade attack from the more secure code based flow to implicit.
  • Same concern exists for allowing both authorization code and hybrid

Secrets

特定の状況では、クライアントはidentityserverで認証する必要があります。

  • トークンエンドポイントでトークンを要求する機密アプリケーション(別称クライアント)
  • イントロスペクションエンドポイントで参照トークンを検証するAPI

その目的のために、秘密のリストをクライアントまたはAPIリソースに割り当てることができます。

秘密の解析と検証は、アイデンティティサーバーの拡張ポイントです。これは、共有秘密をサポートするだけでなく、基本認証ヘッダーまたはPOST本体を介して共有秘密情報を送信することも可能です。

共有秘密の作成

次のコードは、ハッシュ共有秘密を設定します。

var secret = new Secret("secret".Sha256());

このシークレットをa Clientまたはaのいずれかに割り当てることができるようになりましたApiResource。両方が単一のシークレットをサポートするだけでなく、複数のシークレットをサポートすることに注意してください。これは、秘密のロールオーバーとローテーションに便利です。

var client = new Client
{
    ClientId = "client",
    ClientSecrets = new List<Secret> { secret },

    AllowedGrantTypes = GrantTypes.ClientCredentials,
    AllowedScopes = new List<string>
    {
        "api1", "api2"
    }
};

実際には、秘密情報に説明と有効期限を割り当てることもできます。説明はロギング、および秘密のライフタイムを実施するための有効期限に使用されます。

var secret = new Secret(
    "secret".Sha256(),
    "2016 secret",
    new DateTime(2016, 12, 31));

共有秘密を使った認証

POSTボディの一部としてクライアントID /シークレットの組み合わせを送信することもできます。

POST /connect/token

client_id=client1&
client_secret=secret&
...

..または基本認証ヘッダーとして:

POST /connect/token

Authorization: Basic xxxxx

...

次のC#コードを使用して基本認証ヘッダーを手動で作成できます。

var credentials = string.Format("{0}:{1}", clientId, clientSecret);
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);

IdentityModelのライブラリが呼び出されるヘルパークラスを持っているTokenClientし、IntrospectionClientそれは両方の認証プロトコルメッセージをカプセル化します。

共有秘密を越えて

クライアントを認証するには、公開/秘密鍵暗号化などの方法があります。IdentityServerには、秘密鍵JWTクライアントの秘密(RFC 7523を参照)のサポートが含まれています。

秘密の拡張性は、通常、次の3つから構成されます。

  • 秘密の定義
  • 入ってくるリクエストから秘密を引き出す方法を知っている秘密のパーサ
  • 定義に基づいて解析された秘密を検証する方法を知っている秘密のバリデータ

シークレットパーサーとバリデーターは、ISecretParserとISecretValidatorインターフェースの実装です。それらをIdentityServerで使用できるようにするには、それらをDIコンテナに登録する必要があります。

builder.AddSecretParser<JwtBearerClientAssertionSecretParser>()
builder.AddSecretValidator<PrivateKeyJwtSecretValidator>()

私たちのデフォルトの秘密鍵JWT秘密のバリデータは、完全な(リーフ)証明書が秘密の定義のbase64として期待しています。この証明書は、自己署名されたJWTの署名を検証するために使用されます。

var client = new Client
{
    ClientId = "client.jwt",
    ClientSecrets =
    {
        new Secret
        {
            Type = IdentityServerConstants.SecretTypes.X509CertificateBase64,
            Value = "MIIDATCCAe2gAwIBAgIQoHUYAquk9rBJcq8W+F0FAzAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB0RldlJvb3QwHhcNMTAwMTIwMjMwMDAwWhcNMjAwMTIwMjMwMDAwWjARMQ8wDQYDVQQDEwZDbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSaY4x1eXqjHF1iXQcF3pbFrIbmNw19w/IdOQxbavmuPbhY7jX0IORu/GQiHjmhqWt8F4G7KGLhXLC1j7rXdDmxXRyVJBZBTEaSYukuX7zGeUXscdpgODLQVay/0hUGz54aDZPAhtBHaYbog+yH10sCXgV1Mxtzx3dGelA6pPwiAmXwFxjJ1HGsS/hdbt+vgXhdlzud3ZSfyI/TJAnFeKxsmbJUyqMfoBl1zFKG4MOvgHhBjekp+r8gYNGknMYu9JDFr1ue0wylaw9UwG8ZXAkYmYbn2wN/CpJl3gJgX42/9g87uLvtVAmz5L+rZQTlS1ibv54ScR2lcRpGQiQav/LAgMBAAGjXDBaMBMGA1UdJQQMMAoGCCsGAQUFBwMCMEMGA1UdAQQ8MDqAENIWANpX5DZ3bX3WvoDfy0GhFDASMRAwDgYDVQQDEwdEZXZSb290ghAsWTt7E82DjU1E1p427Qj2MAkGBSsOAwIdBQADggEBADLje0qbqGVPaZHINLn+WSM2czZk0b5NG80btp7arjgDYoWBIe2TSOkkApTRhLPfmZTsaiI3Ro/64q+Dk3z3Kt7w+grHqu5nYhsn7xQFAQUf3y2KcJnRdIEk0jrLM4vgIzYdXsoC6YO+9QnlkNqcN36Y8IpSVSTda6gRKvGXiAhu42e2Qey/WNMFOL+YzMXGt/nDHL/qRKsuXBOarIb++43DV3YnxGTx22llhOnPpuZ9/gnNY7KLjODaiEciKhaKqt/b57mTEz4jTF4kIg6BP03MUfDXeVlM1Qf1jB43G2QQ19n5lUiqTpmQkcfLfyci2uBZ8BkOhXr3Vk9HIk/xBXQ="
        }
    },

    AllowedGrantTypes = GrantTypes.ClientCredentials,
    AllowedScopes = { "api1", "api2" }
};

独自の秘密のバリデーターを実装したり、独自のシークレット・バリデーターを実装して、チェーン信頼の検証などを実装することもできます。

Extension Grants

OAuth 2.0はpassword、authorization_codeとのようなトークンエンドポイントの標準認可タイプを定義しますrefresh_token。拡張機能グラントは、トークンの変換、委任、カスタム資格などの非標準トークン発行シナリオのサポートを追加する方法です。

IExtensionGrantValidatorインタフェースを実装することによって、追加の許可タイプのサポートを追加することができます:

public interface IExtensionGrantValidator
{
    /// <summary>
    /// Handles the custom grant request.
    /// </summary>
    /// <param name="request">The validation context.</param>
    Task ValidateAsync(ExtensionGrantValidationContext context);

    /// <summary>
    /// Returns the grant type this validator can deal with
    /// </summary>
    /// <value>
    /// The type of the grant.
    /// </value>
    string GrantType { get; }
}

ExtensionGrantValidationContextオブジェクトは、あなたがにアクセスすることができます:

  • 受信トークン要求(よく知られている検証済みの値)とカスタム値(Rawコレクションを介したもの)
  • 結果 - エラーまたは成功
  • カスタム応答パラメータ

拡張グラントを登録するには、DIに追加します。

builder.AddExtensionGrantValidator<MyExtensionsGrantValidator>();

例:拡張認可を使用する単純な委任

次のシナリオを想像してみましょう。フロントエンドクライアントは、インタラクティブなフロー(例えば、ハイブリッドフロー)で取得したトークンを使用して中間層のAPIを呼び出します。この中間層API(API 1)は、対話ユーザーの代わりにバックエンドAPI(API 2)を呼び出す必要があります。

_images/delegation.png

言い換えると、中間層API(API 1)には、ユーザーの識別情報を含むアクセストークンが必要ですが、バックエンドAPI(API 2)のスコープが必要です。

注釈

フロントエンドからのアクセストークンが単純にバックエンドに転送される、貧しい人の代表団という用語について聞いたことがあります。これにはいくつかの欠点があります。たとえば、API 2がAPI 1スコープを受け入れなければならないため、ユーザーはAPI 2を直接呼び出すことができます。また、トークンにデリゲート固有のクレームをいくつか追加することもできます。たとえば、コールパスがAPI 1経由であるという事実です。

拡張機能の実装

フロントエンドはトークンをAPI 1に送信し、このトークンをIdentityServerでAPI 2の新しいトークンと交換する必要があります。

有線では、交換機のトークンサービスへのコールは次のようになります。

POST /connect/token

grant_type=delegation&
scope=api2&
token=...&
client_id=api1.client
client_secret=secret

着信トークンを検証し、新しいトークンを表す結果を返すことによってその要求を処理するのは、拡張グラントバリデータの仕事です。

public class DelegationGrantValidator : IExtensionGrantValidator
{
    private readonly ITokenValidator _validator;

    public DelegationGrantValidator(ITokenValidator validator)
    {
        _validator = validator;
    }

    public string GrantType => "delegation";

    public async Task ValidateAsync(ExtensionGrantValidationContext context)
    {
        var userToken = context.Request.Raw.Get("token");

        if (string.IsNullOrEmpty(userToken))
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        var result = await _validator.ValidateAccessTokenAsync(userToken);
        if (result.IsError)
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        // get user's identity
        var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;

        context.Result = new GrantValidationResult(sub, GrantType);
        return;
    }
}

DIにバリデーターを登録することを忘れないでください。

委任クライアントの登録

IdentityServerにクライアント登録が必要です。これにより、クライアントは次のような新しい拡張機能を使用できます。

var client = new client
{
    ClientId = "api1.client",
    ClientSecrets = new List<Secret>
    {
        new Secret("secret".Sha256())
    },

    AllowedGrantTypes = { "delegation" },

    AllowedScopes = new List<string>
    {
        "api2"
    }
}

トークンエンドポイントの呼び出し

API 1では、HTTPペイロードを自分で作成することも、IdentityModelヘルパーライブラリを使用することもできます。

public async Task<TokenResponse> DelegateAsync(string userToken)
{
    var payload = new
    {
        token = userToken
    };

    // create token client
    var client = new TokenClient(disco.TokenEndpoint, "api1.client", "secret");

    // send custom grant to token endpoint, return response
    return await client.RequestCustomGrantAsync("delegation", "api2", payload);
}

これでTokenResponse.AccessToken、委任アクセストークンが含まれます。

リソースオーナーのパスワード検証

OAuth 2.0リソースオーナーのパスワード認証情報(別名password)を使用する場合は、IResourceOwnerPasswordValidatorインターフェースを実装して登録する必要があります。

public interface IResourceOwnerPasswordValidator
{
    /// <summary>
    /// Validates the resource owner password credential
    /// </summary>
    /// <param name="context">The context.</param>
    Task ValidateAsync(ResourceOwnerPasswordValidationContext context);
}

コンテキストの中で、あなたは他の入力データを見たいと思っているならば、UserNameとのような、すでに解析されたプロトコルのパラメタが見つかるでしょうPassword。

あなたの仕事はパスワード検証を実装し、それにResult応じてコンテキストを設定します。GrantValidationResultのドキュメントを参照してください。

トークンをリフレッシュする

アクセストークンは寿命が限られているため、リフレッシュトークンによってユーザーの介入なしに新しいアクセストークンを要求できます。

リフレッシュトークンは、認証コード、ハイブリッドおよびリソース所有者のパスワード認証情報フローのためにサポートされています。クライアントは、に設定AllowOfflineAccessすることによってリフレッシュトークンを要求するよう明示的に許可されている必要がありますtrue。

追加のクライアント設定

AbsoluteRefreshTokenLifetime
リフレッシュトークンの最大有効期間(秒単位)。デフォルトは2592000秒/ 30日です。ゼロは、SlidingRefreshTokenLifetimeが渡された後に期限切れでのみ使用されるリフレッシュトークンを許可します。RefreshTokenExpiration = Sliding
SlidingRefreshTokenLifetime
リフレッシュトークンの寿命を数秒でスライドします。デフォルトは1296000秒/ 15日
RefreshTokenUsage

ReUse リフレッシュトークンハンドルは、トークンをリフレッシュするときに同じままになります

OneTime トークンをリフレッシュするとリフレッシュトークンハンドルが更新されます

RefreshTokenExpiration

Absolute リフレッシュ・トークンは、一定の時点(AbsoluteRefreshTokenLifetimeで指定)で期限切れになります。

Slidingトークンをリフレッシュすると、リフレッシュトークンの有効期間が(SlidingRefreshTokenLifetimeで指定された量だけ)更新されます。寿命はAbsoluteRefreshTokenLifetimeを超えません。

UpdateAccessTokenClaimsOnRefresh
アクセストークン(およびその要求)を更新トークン要求で更新する必要があるかどうかを示す値を取得または設定します。

参照トークン

アクセストークンには、自己完結型または参照型の2つの味があります。

JWTトークンは、自己完結型のアクセストークンであり、クレームと有効期限を持つ保護されたデータ構造です。APIがキーマテリアルについて学習すると、発行者と通信することなく自己完結型のトークンを検証できます。これにより、JWTは取り消しが難しくなります。有効期限が切れるまで有効です。

参照トークンを使用する場合、IdentityServerはトークンの内容をデータストアに格納し、このトークンの一意の識別子のみをクライアントに発行します。この参照を受け取ったAPIはIdentityServerへのバックチャネル通信を開き、トークンを検証する必要があります。

_images/reference_tokens.png

次の設定を使用して、クライアントのトークンタイプを切り替えることができます。

client.AccessTokenType = AccessTokenType.Reference;

IdentityServerはOAuth 2.0のイントロスペクション仕様の実装を提供しています。これにより、APIはトークンを間接参照できます。あなたは私たちの専用使用することができますいずれかのイントロスペクションミドルウェアを または使用アイデンティティサーバー認証ミドルウェアの両方JWTsと参照トークンを検証することができます。

イントロスペクションエンドポイントは、認証が必要です。イントロスペクションエンドポイントのクライアントはAPIなので、次のようにシークレットを設定しますApiResource。

var api = new ApiResource("api1")
{
    ApiSecrets = { new Secret("secret".Sha256()) }
}

IdentityServer認証ミドルウェアをAPI用に設定する方法の詳細については、こちらを参照してください。

CORS

IdentityServerの多くのエンドポイントは、JavaScriptベースのクライアントからのAjax呼び出しを介してアクセスされます。IdentityServerは、これらのクライアントとは異なる起点でホストされる可能性が高いため、CORS(Cross-Origin Resource Sharing)を設定する必要があります。

クライアントベースのCORS設定

CORSを構成する1つの方法はAllowedCorsOrigins、クライアント構成上でコレクションを使用することです。クライアントの起点をコレクションに追加するだけで、IdentityServerのデフォルト設定ではこれらの値を参照し、起点からのクロスオリジンコールを許可します。

注釈

CORSを設定するときは、必ずオリジン(URLではなく)を使用してください。例えば、:https://foo:123/はhttps://foo:123原点であるが、URLである。

このデフォルトのCORS実装は、私たちが提供する「メモリ内」またはEFベースのクライアント構成を使用している場合に使用されます。自分自身を定義する場合はIClientStore、独自のカスタムCORSポリシーサービスを実装する必要があります(下記参照)。

カスタムCORSポリシーサービス

IdentityServerを使用すると、ホスティングアプリケーションICorsPolicyServiceはCORSポリシーを完全に制御することができます。

実装する単一の方法は以下の通りです:。原点が許可されていれば返し、そうでなければ返します。Task<bool> IsOriginAllowedAsync(string origin)truefalse

実装したら、実装をDIに登録するだけで、IdentityServerはカスタム実装を使用します。

DefaultCorsPolicyService

許可された起点のセットを単純にハードコーディングしたいのであれば、ICorsPolicyServiceあなたが呼び出すことができる予めビルドされた実装がありますDefaultCorsPolicyService。これは、DI内のシングルトンとして構成され、そのAllowedOriginsコレクションでハードコードされるか、フラグAllowAllをtrueすべての起点を許可するように設定します。たとえば、次のようになりConfigureServicesます。

var cors = new DefaultCorsPolicyService(_loggerFactory.CreateLogger<DefaultCorsPolicyService>())
{
    AllowedOrigins = { "https://foo", "https://bar" }
};
services.AddSingleton<ICorsPolicyService>(cors);

注釈

AllowAll慎重に使用してください。

IdentityServerのCORSポリシーとASP.NET CoreのCORSポリシーを

IdentityServerは、ASP.NET CoreのCORSミドルウェアを使用してCORSの実装を提供します。IdentityServerをホストするアプリケーションで独自のカスタムエンドポイント用のCORSが必要な場合もあります。一般的には、両方とも同じアプリケーションで連携する必要があります。

コードでは、IdentityServerに関係なく、ASP.NET Coreの文書化されたCORS機能を使用する必要があります。つまり、ポリシーを定義し、ミドルウェアを通常どおり登録する必要があります。アプリケーションがポリシーを定義ConfigureServicesしている場合は、CORSミドルウェアを構成する場所またはEnableCorsコントローラコードでMVC 属性を使用する場所と同じ場所で引き続き作業する必要があります。代わりにCORSミドルウェアを使用して(ポリシービルダーのコールバック経由で)インラインポリシーを定義すると、それも正常に機能し続けるはずです。

ASP.NET Core CORSサービスとIdentityServerの使用が競合するシナリオの1つは、カスタムを作成する場合ですICorsPolicyProvider。ASP.NET CoreのCORSサービスとミドルウェアが設計されているため、IdentityServerは独自のカスタムICorsPolicyProviderを実装し、DIシステムに登録します。幸いにも、IdentityServerの実装はICorsPolicyProvider、DIに既に登録されている既存のものをラップするためにデコレータパターンを使用するように設計されています 。つまりICorsPolicyProvider、実装することもできますが、IdentityServerの前にDIで登録する必要があります(例:in ConfigureServices)。

ディスカバリー

この発見文書はhttps://baseaddress/.well-known/openid-configurationにあります。これには、IdentityServerのエンドポイント、主要マテリアルおよび機能に関する情報が含まれています。

デフォルトでは、すべての情報が検出文書に含まれますが、設定オプションを使用することで、個々のセクションを非表示にすることができます。

services.AddIdentityServer(options =>
{
    options.Discovery.ShowIdentityScopes = false;
    options.Discovery.ShowApiScopes = false;
    options.Discovery.ShowClaims = false;
    options.Discovery.ShowExtensionGrantTypes = false;
});

ディスカバリーを拡張する

ディスカバリドキュメントにカスタムエントリを追加することができます。例:

services.AddIdentityServer(options =>
{
    options.Discovery.CustomEntries.Add("my_setting", "foo");
    options.Discovery.CustomEntries.Add("my_complex_setting",
        new
        {
            foo = "foo",
            bar = "bar"
        });
});

〜/で始まるカスタム値を追加すると、IdentityServerのベースアドレス以下の絶対パスに展開されます。

options.Discovery.CustomEntries.Add("my_custom_endpoint", "~/custom");

ディスカバリー(およびjwks)文書のレンダリングを完全に制御したい場合は、IDiscoveryResponseGenerator インターフェースを実装する(またはデフォルトの実装から派生させる)ことができます。

より多くのAPIエンドポイントを追加する

IdentityServer4をホスティングするアプリケーションに、より多くのAPIエンドポイントを追加できます。

通常、これらのAPIは、ホストされているIdentityServerのインスタンスによって保護されます。これは問題ではありません。トークン検証ハンドラをホストに追加するだけです(ここを参照)。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    // details omitted
    services.AddIdentityServer();

    services.AddAuthentication()
        .AddIdentityServerAuthentication("token", isAuth =>
        {
            isAuth.Authority = "base_address_of_identityserver";
            isAuth.ApiName = "name_of_api";
        });
}

APIでは、[Authorize]属性を追加して、使用する認証方式を明示的に参照する必要があります(tokenこの例では、任意の名前を自由に選択できます)。

public class TestController : ControllerBase
{
    [Route("test")]
    [Authorize(AuthenticationSchemes = "token")]
    public IActionResult Get()
    {
        var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToArray();
        return Ok(new { message = "Hello API", claims });
    }
}

ブラウザからそのAPIを呼び出す場合は、さらにCORSを設定する必要があります(こちらを参照)。

発見

また、エンドポイントを検出文書に追加することもできます(例

services.AddIdentityServer(options =>
{
    options.Discovery.CustomEntries.Add("custom_endpoint", "~/api/custom");
})

新しいプロトコルの追加

IdentityServer4では、OpenID ConnectとOAuth 2.0のビルトインサポート以外の他のプロトコルのサポートを追加することができます。

これらの追加のプロトコルエンドポイントをミドルウェアまたはMVCコントローラなどを使用して追加できます。いずれの場合も、ASP.NET Core DIシステムにアクセスすることができ、クライアント定義やキーマテリアルへのアクセスなどの内部サービスを再利用できます。

WS-Federationサポートを追加するためのサンプルがここにあります。

典型的な認証ワークフロー

認証リクエストは通常​​、次のように動作します。

  • 認証要求がプロトコルエンドポイントに到着する
  • プロトコルエンドポイントは入力検証を行います
  • 戻り値がプロトコルエンドポイントに設定されたログインページへのリダイレクト(ユーザーが匿名の場合)
    • 現在のリクエストの詳細へのアクセス IIdentityServerInteractionService
    • ユーザーの認証(ローカルまたは外部認証ミドルウェア経由)
    • ユーザーのサインイン
    • プロトコルエンドポイントにリダイレクトする
  • プロトコル応答の作成(トークンの作成とクライアントへのリダイレクト)

便利なIdentityServerサービス

上記のワークフローを実現するには、IdentityServerとのやりとりのポイントが必要です。

設定へのアクセスとログインページへのリダイレクト

IdentityServerOptions クラスにコードを注入することで、IdentityServer設定にアクセスできます。これは、例えば、ログインページへの設定されたパスを持っています:

var returnUrl = Url.Action("Index");
returnUrl = returnUrl.AddQueryString(Request.QueryString.Value);

var loginUrl = _options.UserInteraction.LoginUrl;
var url = loginUrl.AddQueryString(_options.UserInteraction.LoginReturnUrlParameter, returnUrl);

return Redirect(url);

ログインページと現在のプロトコル要求との間の相互作用

IIdentityServerInteractionServiceパースと検証コンテキストオブジェクトにプロトコルの戻りURLを回すサポート:

var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

デフォルトでは、インタラクションサービスはOpenID Connectプロトコルメッセージのみを認識します。サポートを拡張するには、あなた自身で書くことができますIReturnUrlParser:

public interface IReturnUrlParser
{
    bool IsValidReturnUrl(string returnUrl);
    Task<AuthorizationRequest> ParseAsync(string returnUrl);
}

そしてパーサーをDIに登録してください:

builder.Services.AddTransient<IReturnUrlParser, WsFederationReturnUrlParser>();

これにより、ログインページはクライアントの設定やその他のプロトコルパラメータのような情報にアクセスできます。

プロトコル応答を作成するためのコンフィグレーションとキーマテリアルへのアクセス

IKeyMaterialService をコードに挿入すると、設定された署名資格情報と検証キーにアクセスできます。

var credential = await _keys.GetSigningCredentialsAsync();
var key = credential.Key as Microsoft.IdentityModel.Tokens.X509SecurityKey;

var descriptor = new SecurityTokenDescriptor
{
    AppliesToAddress = result.Client.ClientId,
    Lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddSeconds(result.Client.IdentityTokenLifetime)),
    ReplyToAddress = result.Client.RedirectUris.First(),
    SigningCredentials = new X509SigningCredentials(key.Certificate, result.RelyingParty.SignatureAlgorithm, result.RelyingParty.DigestAlgorithm),
    Subject = outgoingSubject,
    TokenIssuerName = _contextAccessor.HttpContext.GetIdentityServerIssuerUri(),
    TokenType = result.RelyingParty.TokenType
};

ツール

この IdentityServerTools クラスは、IdentityServerの拡張コードを記述する際に必要となる便利な内部ツールの集まりです。それを使用するには、あなたのコードにそれを注入します。例えば、コントローラ

public MyController(IdentityServerTools tools)
{
    _tools = tools;
}

この IssueJwtAsync 方法では、IdentityServerトークン作成エンジンを使用してJWTトークンを作成できます。これ IssueClientJwtAsync は、サーバーからサーバーへの通信用のトークンを作成するための簡単なバージョンです(たとえば、コードからIdentityServerで保護されたAPIを呼び出す必要がある場合)。:

public async Task<IActionResult> MyAction()
{
    var token = await _tools.IssueClientJwtAsync(
        clientId: "client_id",
        lifetime: 3600,
        audiences: new[] { "backend.api" });

    // more code
}

Discovery Endpoint

ディスカバリエンドポイントを使用してIdentityServerに関するメタデータを取得できます。発行者名、キーマテリアル、サポートされているスコープなどの情報が返されます。詳細は 仕様 を参照してください。

検出エンドポイントは、ベースアドレスに対して /.well-known/openid-configuration を介して利用できます。例:

https://demo.identityserver.io/.well-known/openid-configuration

注釈

IdentityModel クライアントライブラリを使用して、.NETコードからディスカバリエンドポイントにプログラムでアクセスできます。詳細については、IdentityModelの ドキュメント を参照してください。

エンドポイントの認証

承認エンドポイントは、ブラウザを介してトークンまたは認証コードを要求するために使用できます。このプロセスは、通常、エンドユーザの認証とオプションで同意する必要があります。

注釈

IdentityServerは、OpenID ConnectおよびOAuth 2.0認証要求パラメータのサブセットをサポートしています。完全なリストについては、こちらを参照してください。

client_id
クライアントの識別子(必須)。
scope
1つまたは複数の登録スコープ(必須)
redirect_uri
そのクライアントの許可されたリダイレクトURIの1つに完全に一致する必要があります(必須)
response_type

id_token アイデンティティトークンを要求します(アイデンティティスコープのみが許可されます)

token アクセストークンを要求します(リソーススコープのみが許可されます)

id_token token アイデンティティトークンとアクセストークンを要求する

code 承認コードを要求する

code id_token 認可コードとアイデンティティトークンを要求する

code id_token token 認証コード、アイデンティティトークン、およびアクセストークンを要求する

response_mode
form_post フラグメントエンコードされたリダイレクト(オプション)ではなく、フォームのポストとしてトークンレスポンスを送信します。
state
identityserverは、トークンレスポンスに状態値をエコーバックします。これは、クライアントとプロバイダ間のラウンドトリップ状態であり、要求と応答とCSRF /再生保護を関連づけます。(推奨)
nonce

identityserverは、IDトークンのnonce値をエコーバックします。これはリプレイ保護用です)

暗黙的な認可を使用してアイデンティティトークンに必要です。

prompt

none要求中にUIは表示されません。これが不可能な場合(ユーザーがサインインまたは同意する必要があるなど)、エラーが返されます

login ユーザーが既にサインインしていて有効なセッションを持っていてもログインUIが表示されます

code_challenge
コードチャレンジをPKCEに送信する
code_challenge_method
plainチャレンジがプレーンテキストを使用していることを示します(推奨されません)。S256チャレンジがSHA256でハッシュされていることを示します
login_hint
ログインページのユーザー名フィールドをあらかじめ入力するために使用できます
ui_locales
ログインUIの表示言語に関するヒントを表示します
max_age
ユーザーのログオンセッションが最大経過時間(秒)を超えた場合、ログインUIが表示されます
acr_values

追加の認証関連情報を渡すことができます - identityserver特別な場合、次の独自のacr_values:

idp:name_of_idp ログイン/ホーム領域の画面をバイパスし、選択したアイデンティティプロバイダに直接ユーザーを転送します(クライアント構成ごとに許可されている場合)

tenant:name_of_tenant テナント名をログインUIに渡すことができます

GET /connect/authorize?
    client_id=client1&
    scope=openid email api1&
    response_type=id_token token&
    redirect_uri=https://myapp/callback&
    state=abc&
    nonce=xyz

(URLエンコードが削除され、読みやすくするため改行が追加されました)

注釈

IdentityModelクライアントライブラリを使用して、認証要求.NETコードをプログラムで作成することができます。詳細については、IdentityModelのドキュメントを参照してください。

トークンエンドポイント

トークンエンドポイントは、プログラムでトークンを要求するために使用できます。それは passwordauthorization_codeclient_credentialsrefresh_token 及び urn:ietf:params:oauth:grant-type:device_code の付与タイプをサポートしています。さらに、トークンエンドポイントは、拡張付与タイプをサポートするように拡張することができます。

注釈

IdentityServerは、OpenID ConnectおよびOAuth 2.0トークン要求パラメータのサブセットをサポートしています。完全なリストについては、こちらを参照してください。

client_id
クライアント識別子(必須)
client_secret
ポスト本体のクライアント秘密か、基本的な認証ヘッダーのどちらかです。オプション。
grant_type
authorization_codeclient_credentialspasswordrefresh_tokenurn:ietf:params:oauth:grant-type:device_code またはカスタム
scope
1つ以上の登録されたスコープ。指定しない場合は、明示的に許可されたすべてのスコープのトークンが発行されます。
redirect_uri
authorization_code付与タイプに必要
code
認可コード(authorization_code認可タイプに必要)
code_verifier
PKCEプルーフキー
username
リソース所有者のユーザー名(password付与タイプに必要)
password
リソース所有者のパスワード(password付与タイプに必要)
acr_values

password認可タイプの追加の認証に関連する情報を渡すことができます- identityserverの特殊なケース次の独自のacr_values:

idp:name_of_idp ログイン/ホーム領域の画面をバイパスし、選択したアイデンティティプロバイダに直接ユーザーを転送します(クライアント構成ごとに許可されている場合)

tenant:name_of_tenant テナント名をトークンエンドポイントに渡すために使用できます

refresh_token
リフレッシュトークン( refresh_token 付与タイプに必要)
device_code
デバイスコード( urn:ietf:params:oauth:grant-type:device_code 付与タイプに必要)

POST /connect/token

    client_id=client1&
    client_secret=secret&
    grant_type=authorization_code&
    code=hdh922&
    redirect_uri=https://myapp.com/callback

(フォームエンコードが削除され、読みやすくするために改行が追加されました)

注釈

IdentityModel クライアントライブラリを使用して、.NETコードからトークンエンドポイントにプログラムでアクセスできます。詳細については、IdentityModelの ドキュメント を参照してください。

UserInfoエンドポイント

UserInfoエンドポイントを使用して、ユーザーに関する識別情報を取得できます(仕様を参照)。

呼び出し元は、ユーザーを表す有効なアクセストークンを送信する必要があります。付与されたスコープに応じて、UserInfoエンドポイントはマップされたクレームを返します(少なくともopenidスコープが必要です)。

GET /connect/userinfo
Authorization: Bearer <access_token>
HTTP/1.1 200 OK
Content-Type: application/json

{
    "sub": "248289761001",
    "name": "Bob Smith",
    "given_name": "Bob",
    "family_name": "Smith",
    "role": [
        "user",
        "admin"
    ]
}

注釈

IdentityModelクライアント・ライブラリーを使用して、.NETコードからuserinfoエンドポイントにプログラムでアクセスできます。詳細については、IdentityModelのドキュメントを参照してください。

デバイス認証エンドポイント

デバイス認証エンドポイントは、デバイスコードとユーザーコードを要求するために使用できます。 このエンドポイントは、デバイスフロー許可プロセスを開始するために使用されます。

注釈

エンドセッションエンドポイントのURLは、 discovery endpoint で利用できます。

クライアントID
クライアント識別子(必須)
client_secret
ポスト本体のクライアント秘密か、基本的な認証ヘッダーのどちらかです。 オプション。
scope
106/5000 1つ以上の登録されたスコープ。 指定しない場合は、明示的に許可されたすべてのスコープのトークンが発行されます。

Example

POST /connect/deviceauthorization

    client_id=client1&
    client_secret=secret&
    scope=openid api1

(フォームエンコードが削除され、読みやすくするために改行が追加されました)

注釈

IdentityModel クライアントライブラリを使用して、.NETコードからデバイス認証エンドポイントにプログラムでアクセスすることができます。 詳細については、IdentityModel ドキュメント を確認してください。

Introspection Endpoint

イントロスペクションエンドポイントは、RFC 7662の実装です。

これは、参照トークン(または消費者が適切なJWTまたは暗号ライブラリをサポートしていない場合はJWT)を検証するために使用できます。イントロスペクションエンドポイントは、認証が必要です。イントロスペクションエンドポイントのクライアントはAPIなので、あなたはシークレットを設定しますApiResource。

POST /connect/introspect
Authorization: Basic xxxyyy

token=<token>

応答が成功すると、ステータスコード200およびアクティブトークンまたは非アクティブトークンが返されます。

{
    "active": true,
    "sub": "123"
}

未知のトークンまたは期限切れのトークンは、非アクティブとしてマークされます。

{
    "active": false,
}

無効なリクエストは400、不正なリクエスト401を返します。

注釈

IdentityModelクライアントライブラリを使用して、.NETコードからイントロスペクションエンドポイントにプログラムでアクセスできます。詳細については、IdentityModelのドキュメントを参照してください。

失効エンドポイント

このエンドポイントによって、アクセストークン(参照トークンのみ)の取り消しとトークンのリフレッシュが可能になります。これは、トークン取り消し仕様(RFC 7009)を実装しています。

token
取り消すトークン(必須)
token_type_hint
いずれか access_token または refresh_token (オプション)

POST /connect/revocation HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

注釈

IdentityModel クライアントライブラリを使用して、.NETコードから取り消しエンドポイントにプログラムでアクセスすることができます。詳細については、IdentityModelの ドキュメント を参照してください。

End Session Endpoint

The end session endpoint can be used to trigger single sign-out (see spec).

To use the end session endpoint a client application will redirect the user's browser to the end session URL. All applications that the user has logged into via the browser during the user's session can participate in the sign-out.

注釈

The URL for the end session endpoint is available via the discovery endpoint.

Parameters

id_token_hint

When the user is redirected to the endpoint, they will be prompted if they really want to sign-out. This prompt can be bypassed by a client sending the original id_token received from authentication. This is passed as a query string parameter called id_token_hint.

post_logout_redirect_uri

If a valid id_token_hint is passed, then the client may also send a post_logout_redirect_uri parameter. This can be used to allow the user to redirect back to the client after sign-out. The value must match one of the client's pre-configured PostLogoutRedirectUris (client docs).

state

If a valid post_logout_redirect_uri is passed, then the client may also send a state parameter. This will be returned back to the client as a query string parameter after the user redirects back to the client. This is typically used by clients to round-trip state across the redirect.

Example

GET /connect/endsession?id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjdlOGFkZmMzMjU1OTEyNzI0ZDY4NWZmYmIwOThjNDEyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE0OTE3NjUzMjEsImV4cCI6MTQ5MTc2NTYyMSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoianNfb2lkYyIsIm5vbmNlIjoiYTQwNGFjN2NjYWEwNGFmNzkzNmJjYTkyNTJkYTRhODUiLCJpYXQiOjE0OTE3NjUzMjEsInNpZCI6IjI2YTYzNWVmOTQ2ZjRiZGU3ZWUzMzQ2ZjFmMWY1NTZjIiwic3ViIjoiODg0MjExMTMiLCJhdXRoX3RpbWUiOjE0OTE3NjUzMTksImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.STzOWoeVYMtZdRAeRT95cMYEmClixWkmGwVH2Yyiks9BETotbSZiSfgE5kRh72kghN78N3-RgCTUmM2edB3bZx4H5ut3wWsBnZtQ2JLfhTwJAjaLE9Ykt68ovNJySbm8hjZhHzPWKh55jzshivQvTX0GdtlbcDoEA1oNONxHkpDIcr3pRoGi6YveEAFsGOeSQwzT76aId-rAALhFPkyKnVc-uB8IHtGNSyRWLFhwVqAdS3fRNO7iIs5hYRxeFSU7a5ZuUqZ6RRi-bcDhI-djKO5uAwiyhfpbpYcaY_TxXWoCmq8N8uAw9zqFsQUwcXymfOAi2UF3eFZt02hBu-shKA&post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A7017%2Findex.html

注釈

You can use the IdentityModel client library to programmatically create end_session requests .NET code. For more information check the IdentityModel docs.

Identity Resource

このクラスはアイデンティティリソースをモデル化します。

Enabled
このリソースが有効であり、要求できるかどうかを示します。デフォルトはtrueです。
Name
IDリソースの一意の名前。これは、クライアントがauthorize要求内のscopeパラメータに使用する値です。
DisplayName
この値は、例えば同意画面で使用されます。
Description
この値は、例えば同意画面で使用されます。
Required
同意画面でスコープの選択を解除できるかどうかを指定します(同意画面でそのような機能を実装したい場合)。デフォルトはfalseです。
Emphasize
同意画面がこの範囲を強調するかどうかを指定します(同意画面でそのような機能を実装したい場合)。この設定は、機密または重要なスコープに使用します。デフォルトはfalseです。
ShowInDiscoveryDocument
このスコープが検出文書に表示されるかどうかを指定します。デフォルトはtrueです。
UserClaims
アイデンティティトークンに含める必要がある、関連するユーザークレームタイプのリスト。

APIリソース

このクラスはAPIリソースをモデル化します。

Enabled
このリソースが有効であり、要求できるかどうかを示します。デフォルトはtrueです。
Name
APIの一意の名前。この値はイントロスペクションでの認証に使用され、発信アクセストークンのオーディエンスに追加されます。
DisplayName
この値は、例えば同意画面で使用できます。
Description
この値は、例えば同意画面で使用できます。
ApiSecrets
イントロスペクションエンドポイントにはAPIシークレットが使用されます。APIは、API名とシークレットを使用してイントロスペクションで認証できます。
UserClaims
アクセストークンに含める必要がある、関連するユーザークレームタイプのリスト。
Scopes
APIには少なくとも1つのスコープが必要です。各スコープは異なる設定を持つことができます。

Scopes

単純なケースでは、APIのスコープは1つだけです。しかし、APIの機能を細かく分割して、異なるクライアントが異なる部分にアクセスできるようにしたい場合があります。

Name
The unique name of the scope. This is the value a client will use for the scope parameter in the authorize/token request.
DisplayName
この値は、例えば同意画面で使用できます。
Description
この値は、例えば同意画面で使用できます。
Required
同意画面でスコープの選択を解除できるかどうかを指定します(同意画面でそのような機能を実装したい場合)。デフォルトはfalseです。
Emphasize
同意画面がこの範囲を強調するかどうかを指定します(同意画面でそのような機能を実装したい場合)。この設定は、機密または重要なスコープに使用します。デフォルトはfalseです。
ShowInDiscoveryDocument
このスコープが検出文書に表示されるかどうかを指定します。デフォルトはtrueです。
UserClaims
List of associated user claim types that should be included in the access token. The claims specified here will be added to the list of claims specified for the API.

コンビニエンスコンストラクタの動作

ApiResourceクラスに提供されたコンストラクタについてのメモ。

のデータを完全に制御するにはApiResource、パラメータなしのデフォルトのコンストラクタを使用します。APIごとに複数のスコープを設定する場合は、この方法を使用します。例えば:

new ApiResource
{
    Name = "api2",

    Scopes =
    {
        new Scope()
        {
            Name = "api2.full_access",
            DisplayName = "Full access to API 2"
        },
        new Scope
        {
            Name = "api2.read_only",
            DisplayName = "Read only access to API 2"
        }
    }
}

APIごとに1つのスコープしか必要としない簡単なシナリオでは、aを受け入れるいくつかの便利なコンストラクタnameが提供されます。例えば:

new ApiResource("api1", "Some API 1")

便利なコンストラクタの使い方は次のようになります:

new ApiResource
{
    Name = "api1",
    DisplayName = "Some API 1",

    Scopes =
    {
        new Scope()
        {
            Name = "api1",
            DisplayName = "Some API 1"
        }
    }
}

クライアント

ClientクラスモデルOpenIDの接続やOAuth 2.0のクライアント-例えばネイティブアプリケーション、WebアプリケーションやJSベースのアプリケーション。

基本

Enabled
クライアントが有効かどうかを指定します。デフォルトはtrueです。
ClientId
クライアントの一意のID
ClientSecrets
クライアントシークレットのリスト - トークンエンドポイントにアクセスするための信任状。
RequireClientSecret
トークンエンドポイントにトークンを要求するためにこのクライアントにシークレットが必要かどうかを指定します(デフォルト値true)。
AllowedGrantTypes
クライアントが使用できる許可タイプを指定します。GrantTypes共通の組み合わせにはクラスを使用します。
RequirePkce
認可コードベースの認可タイプを使用するクライアントがプルーフキーを送信する必要があるかどうかを指定します
AllowPlainTextPkce
PKCEを使用するクライアントがプレーンテキストコードチャレンジを使用できるかどうかを指定します(推奨されていない - デフォルトfalse)
RedirectUris
許可されたURIがトークンまたは認証コードを返すように指定します
AllowedScopes
デフォルトでは、クライアントはリソースへのアクセス権がありません。対応するスコープ名を追加することによって、許可されたリソースを指定します
AllowOfflineAccess
Specifies whether this client can request refresh tokens (be requesting the offline_access scope)
AllowAccessTokensViaBrowser
Specifies whether this client is allowed to receive access tokens via the browser. This is useful to harden flows that allow multiple response types (e.g. by disallowing a hybrid flow client that is supposed to use code id_token to add the token response type and thus leaking the token to the browser.
Properties
Dictionary to hold any custom client-specific values as needed.

Authentication/Logout

PostLogoutRedirectUris
Specifies allowed URIs to redirect to after logout. See the OIDC Connect Session Management spec for more details.
FrontChannelLogoutUri
Specifies logout URI at client for HTTP based front-channel logout. See the OIDC Front-Channel spec for more details.
FrontChannelLogoutSessionRequired
Specifies if the user's session id should be sent to the FrontChannelLogoutUri. Defaults to true.
BackChannelLogoutUri
Specifies logout URI at client for HTTP based back-channel logout. See the OIDC Back-Channel spec for more details.
BackChannelLogoutSessionRequired
Specifies if the user's session id should be sent in the request to the BackChannelLogoutUri. Defaults to true.
EnableLocalLogin
Specifies if this client can use local accounts, or external IdPs only. Defaults to true.
IdentityProviderRestrictions
Specifies which external IdPs can be used with this client (if list is empty all IdPs are allowed). Defaults to empty.
UserSsoLifetime added in 2.3
The maximum duration (in seconds) since the last time the user authenticated. Defaults to null.

Token

IdentityTokenLifetime
Lifetime to identity token in seconds (defaults to 300 seconds / 5 minutes)
AccessTokenLifetime
Lifetime of access token in seconds (defaults to 3600 seconds / 1 hour)
AuthorizationCodeLifetime
Lifetime of authorization code in seconds (defaults to 300 seconds / 5 minutes)
AbsoluteRefreshTokenLifetime
Maximum lifetime of a refresh token in seconds. Defaults to 2592000 seconds / 30 days
SlidingRefreshTokenLifetime
Sliding lifetime of a refresh token in seconds. Defaults to 1296000 seconds / 15 days
RefreshTokenUsage

ReUse the refresh token handle will stay the same when refreshing tokens

OneTime the refresh token handle will be updated when refreshing tokens. This is the default.

RefreshTokenExpiration

Absolute the refresh token will expire on a fixed point in time (specified by the AbsoluteRefreshTokenLifetime)

Sliding when refreshing the token, the lifetime of the refresh token will be renewed (by the amount specified in SlidingRefreshTokenLifetime). The lifetime will not exceed AbsoluteRefreshTokenLifetime.

UpdateAccessTokenClaimsOnRefresh
Gets or sets a value indicating whether the access token (and its claims) should be updated on a refresh token request.
AccessTokenType
Specifies whether the access token is a reference token or a self contained JWT token (defaults to Jwt).
IncludeJwtId
Specifies whether JWT access tokens should have an embedded unique ID (via the jti claim).
AllowedCorsOrigins
If specified, will be used by the default CORS policy service implementations (In-Memory and EF) to build a CORS policy for JavaScript clients.
Claims
Allows settings claims for the client (will be included in the access token).
AlwaysSendClientClaims
If set, the client claims will be sent for every flow. If not, only for client credentials flow (default is false)
AlwaysIncludeUserClaimsInIdToken
When requesting both an id token and access token, should the user claims always be added to the id token instead of requring the client to use the userinfo endpoint. Default is false.
ClientClaimsPrefix
If set, the prefix client claim types will be prefixed with. Defaults to client_. The intent is to make sure they don't accidentally collide with user claims.
PairWiseSubjectSalt
Salt value used in pair-wise subjectId generation for users of this client.

Device flow

UserCodeType
Specifies the type of user code to use for the client. Otherwise falls back to default.
DeviceCodeLifetime
Lifetime to device code in seconds (defaults to 300 seconds / 5 minutes)

GrantValidationResult

このGrantValidationResultクラスは、エクステンショングラントとリソースオーナーのパスワード付与のグラント検証の結果をモデル化します。

最も一般的な使用法は、アイデンティティーを使用して新しいものを作ることです(成功例)。

context.Result = new GrantValidationResult(
    subject: "818727",
    authenticationMethod: "custom",
    claims: optionalClaims);

...またはエラーと説明を使用する(失敗の場合):

context.Result = new GrantValidationResult(
    TokenRequestErrors.InvalidGrant,
    "invalid custom credential");

いずれの場合も、トークンレスポンスに追加される追加のカスタム値を渡すことができます。

プロファイルサービス

IdentityServerでは、トークンを作成するときや、ユーザー情報やイントロスペクションエンドポイントへの要求を処理するときに、ユーザーに関する識別情報が必要になることがよくあります。デフォルトでは、IdentityServerはこのIDデータを取得するための認証クッキーの主張のみを持ちます。

ユーザにとって必要なすべての可能なクレームをクッキーに入れることは実用的ではないので、IdentityServerは、クレームをユーザの必要に応じて動的にロードするための拡張ポイントを定義します。この拡張性のポイントは、IProfileService開発者がこのインターフェイスを実装して、ユーザーのIDデータを含むカスタムデータベースまたはAPIにアクセスすることが一般的です。

IProfileService APIs

GetProfileDataAsync
ユーザーの申し立てを読み込むAPIです。のインスタンスが渡されますProfileDataRequestContext。
IsActiveAsync
ユーザーが現在トークンを取得できるかどうかを示すことが期待されるAPI。のインスタンスが渡されますIsActiveContext。

ProfileDataRequestContext

ユーザーのクレームに対するリクエストをモデル化し、そのクレームを返却する手段です。これには、次のプロパティが含まれます。

Subject
ClaimsPrincipalユーザーのモデリング。
Client
Clientクレームが要求されています。
RequestedClaimTypes
要求されているクレームタイプのコレクション。
Caller
クレームが要求されているコンテキストの識別子(例えば、アイデンティティトークン、アクセストークン、またはユーザー情報エンドポイント)。定数IdentityServerConstants.ProfileDataCallersにはさまざまな定数値が含まれています。
IssuedClaims
Claim返されるリスト。これは、カスタムIProfileService実装によって設定されると予想されます。
AddRequestedClaims
の拡張メソッドは、ProfileDataRequestContextにIssuedClaims基づいてクレームを最初にフィルターに掛けるRequestedClaimTypes。

要求されたスコープとクレームマッピング

クライアントによって要求されたスコープは、トークンでクライアントに返されるユーザークレームを制御します。GetProfileDataAsyncこの方法は、動的に基づいてこれらの請求項を取得する責任があるRequestedClaimTypesのコレクションProfileDataRequestContext。

RequestedClaimTypesコレクションは、上に定義されたユーザの請求に基づいて移入されたリソースのスコープをモデル化します。要求されたスコープがアイデンティティリソースである場合、そのアイデンティティのクレームは、でRequestedClaimTypes定義されたユーザークレームタイプに基づいて設定されますIdentityResource。要求されたスコープである場合、APIリソース、その後に、特許請求の範囲は、RequestedClaimTypesで定義されたユーザ要求の種類に基づいて移入されApiResource、および/またはScope。

IsActiveContext

決定する要求のモデルは、現在ユーザーがトークンを取得できることです。これには、次のプロパティが含まれます。

Subject
ClaimsPrincipalユーザーのモデリング。
Client
Clientクレームが要求されています。
Caller
クレームが要求されているコンテキストの識別子(例えば、アイデンティティトークン、アクセストークン、またはユーザー情報エンドポイント)。定数IdentityServerConstants.ProfileDataCallersにはさまざまな定数値が含まれています。
IsActive
ユーザーがトークンを取得できるかどうかを示すフラグ。これは、カスタムIProfileService実装によって割り当てられることが期待されます。

IdentityServer Interaction Service

このIIdentityServerInteractionServiceインタフェースは、主にユーザ対話に関係するユーザインタフェースがIdentityServerと通信するために使用するサービスを提供することを目的としています。これは依存関係注入システムから利用でき、通常はIdentityServerのユーザーインターフェイス用のMVCコントローラにコンストラクタパラメータとして注入されます。

IIdentityServerInteractionService APIs

GetAuthorizationContextAsync
ログインまたは同意ページに渡された情報にAuthorizationRequest基づいて返しますreturnUrl。
IsValidReturnUrl
returnUrlログインまたは同意の後にリダイレクトの有効なURL かどうかを示します。
GetErrorContextAsync
エラーページに渡されたデータにErrorMessage基づいて返しますerrorId。
GetLogoutContextAsync
ログアウトページに渡された値にLogoutRequest基づいて返しますlogoutId。
CreateLogoutContextAsync
logoutId現在存在しない場合にaを作成するために使用されます。これにより、サインアウトに必要なすべての現在の状態をキャプチャしたCookieが作成logoutIdされ、そのCookie が識別されます。これは通常logoutId、現在のログがないときに使用され、サインアウトのために外部IDプロバイダにリダイレクトする前に、ログアウトページでログアウトに必要な現在のユーザーの状態を取得する必要があります。新しく作成されたものlogoutIdは、サインアウト時に外部IDプロバイダにラウンドトリップされ、通常のログアウトページと同じ方法でサインアウトコールバックページで使用される必要があります。
GrantConsentAsync
ConsentResponseIdentityServerに特定のユーザーの同意を通知するためにa を受け入れAuthorizationRequestます。
GetAllUserConsentsAsync
Consentユーザーのコレクションを返します。
RevokeUserConsentAsync
クライアントに対するすべてのユーザーの同意と付与を取り消します。
RevokeTokensForCurrentSessionAsync
ユーザーが現在のセッション中にサインインしたクライアントに対するユーザーの同意と付与をすべて取り消します。

AuthorizationRequest

ClientId
要求を開始したクライアント識別子。
RedirectUri
The URI to redirect the user to after successful authorization.
DisplayMode
The display mode passed from the authorization request.
UiLocales
The UI locales passed from the authorization request.
IdP
The external identity provider requested. This is used to bypass home realm discovery (HRD). This is provided via the "idp:" prefix to the acr_values parameter on the authorize request.
Tenant
The tenant requested. This is provided via the "tenant:" prefix to the acr_values parameter on the authorize request.
LoginHint
The expected username the user will use to login. This is requested from the client via the login_hint parameter on the authorize request.
PromptMode
The prompt mode requested from the authorization request.
AcrValues
The acr values passed from the authorization request.
ScopesRequested
The scopes requested from the authorization request.
Parameters
The entire parameter collection passed to the authorization request.

ErrorMessage

DisplayMode
The display mode passed from the authorization request.
UiLocales
The UI locales passed from the authorization request.
Error
The error code.
RequestId
The per-request identifier. This can be used to display to the end user and can be used in diagnostics.

LogoutRequest

ClientId
要求を開始したクライアント識別子。
PostLogoutRedirectUri
The URL to redirect the user to after they have logged out.
SessionId
The user's current session id.
SignOutIFrameUrl
The URL to render in an <iframe> on the logged out page to enable single sign-out.
Parameters
The entire parameter collection passed to the end session endpoint.
ShowSignoutPrompt
Indicates if the user should be prompted for signout based upon the parameters passed to the end session endpoint.

ConsentResponse

ScopesConsented
The collection of scopes the user consented to.
RememberConsent
Flag indicating if the user's consent is to be persisted.

Device Flow Interaction Service

IDeviceFlowInteractionService インターフェイスは、デバイスフローの認可中にIdentityServerと通信するためにユーザーインターフェイスが使用するサービスを提供するためのものです。 これは依存関係注入システムから利用でき、通常はIdentityServerのユーザーインターフェイス用のMVCコントローラにコンストラクタパラメータとして注入されます。

IDeviceFlowInteractionService APIs

GetAuthorizationContextAsync
ログインまたは同意ページに渡された userCode に基づいて DeviceFlowAuthorizationRequest を返します。
DeviceFlowInteractionResult
指定された userCode のデバイス認証を完了します。

DeviceFlowAuthorizationRequest

ClientId
要求を開始したクライアント識別子。
ScopesRequested
承認要求から要求されたスコープ。

DeviceFlowInteractionResult

IsError
認可要求がエラーを起こしたかどうかを指定します。
ErrorDescription
障害発生時のエラーの説明。

IdentityServerのオプション

  • IssuerUri
    ディスカバリ文書に表示される発行者名と発行されたJWTトークンを設定します。クライアントが使用するホスト名から発行者名を推測するこのプロパティを設定しないことをお勧めします。
  • PublicOrigin
    このサーバーインスタンスの起点です(例:https : //myorigin.com)。設定されていない場合は、要求元名が推測されます。

Endpoints

token、authorize、userinfoなど、個々のエンドポイントを有効/無効にすることができます。

デフォルトではすべてのエンドポイントが有効になっていますが、必要のないエンドポイントを無効にすることでサーバーをロックダウンすることができます。

Discovery

検出文書のさまざまなセクション(エンドポイント、スコープ、クレーム、グラントタイプなど)の有効化/無効化を許可します。

CustomEntries辞書は、探索ドキュメントへのカスタム要素を追加することができます。

認証

  • CookieLifetime
    認証Cookieの有効期間(IdentityServer提供のCookieハンドラが使用されている場合のみ有効)。
  • CookieSlidingExpiration
    クッキーをスライドさせるかどうかを指定します(IdentityServer提供のCookieハンドラが使用されている場合のみ有効)。
  • RequireAuthenticatedUserForSignOutMessage
    セッションエンドポイントを終了するパラメータを受け入れるためにユーザーを認証する必要があるかどうかを示します。デフォルトはfalseです。
  • CheckSessionCookieName
    チェック・セッション・エンドポイントに使用されるCookieの名前。
  • RequireCspFrameSrcForSignout
    設定されている場合は、フロント・チャネル・サインアウト通知のためにiframeをクライアントにレンダリングするend-sessionコールバック・エンドポイントでframe-src CSPヘッダーを送信する必要があります。デフォルトはtrueです。

Events

ifおよび登録されたイベントシンクに送信するイベントを設定できるようにします。イベントの詳細については、こちらを参照してください。

InputLengthRestrictions

クライアントID、スコープ、リダイレクトURIなどのさまざまなプロトコルパラメータの長さ制限を設定できます。

UserInteraction

  • LoginUrl, LogoutUrl, ConsentUrl, ErrorUrl, DeviceVerificationUrl
    Sets the the URLs for the login, logout, consent, error and device verification pages.
  • LoginReturnUrlParameter
    ログインページに渡される戻りURLパラメータの名前を設定します。デフォルトはreturnUrlです。
  • LogoutIdParameter
    ログアウトページに渡されるログアウトメッセージIDパラメータの名前を設定します。デフォルトはlogoutIdです。
  • ConsentReturnUrlParameter
    同意ページに渡される戻りURLパラメータの名前を設定します。デフォルトはreturnUrlです。
  • ErrorIdParameter
    エラーページに渡されるエラーメッセージIDパラメータの名前を設定します。デフォルトはerrorIdです。
  • CustomRedirectReturnUrlParameter
    承認エンドポイントからのカスタムリダイレクトに渡される戻りURLパラメータの名前を設定します。デフォルトはreturnUrlです。
  • DeviceVerificationUserCodeParameter
    Sets the name of the user code parameter passed to the device verification page. Defaults to userCode.
  • CookieMessageThreshold
    IdentityServerと一部のUIページとの間の特定のやりとりには、状態とコンテキストを渡すためのCookieが必要です(上記のいずれのページにも設定可能な「メッセージID」パラメータがあります)。ブラウザにはCookieの数とそのサイズに制限があるため、この設定はあまりに多くのCookieが作成されないようにするために使用されます。この値は、作成されるすべてのタイプのメッセージCookieの最大数を設定します。限度に達すると、最も古いメッセージCookieがパージされます。これは、IdentityServerを使用するときにユーザーが開くことができるタブの数を効果的に示します。

Caching

これらの設定は、起動時にサービス設定でそれぞれのキャッシングが有効になっている場合にのみ適用されます。

  • ClientStoreExpiration
    クライアントストアからロードされたクライアント構成のキャッシュ期間。
  • ResourceStoreExpiration
    リソースストアからロードされたIDとAPIリソース構成のキャッシュ期間。

CORS

IdentityServerは、そのエンドポイントの一部でCORSをサポートしています。基礎となるCORS実装はASP.NET Coreから提供され、依存関係注入システムに自動的に登録されます。

  • CorsPolicyName
    IdentityServerへのCORS要求に対して評価されるCORSポリシーの名前(デフォルト値"IdentityServer4")。これを処理するポリシープロバイダICorsPolicyServiceは、依存関係注入システムに登録されている点で実装されています。接続が許可されているCORS起点のセットをカスタマイズする場合は、のカスタム実装を提供することをお勧めしますICorsPolicyService。
  • CorsPaths
    CORSがサポートされているIdentityServer内のエンドポイント。デフォルトでは、ディスカバリー、ユーザー情報、トークン、および取り消しエンドポイントが使用されます。
  • PreflightCacheDuration
    プリフライトAccess-Control-Max-Age応答ヘッダーで使用される値を示すNullable <TimeSpan>。応答にキャッシュヘッダーが設定されていないことを示すデフォルトはnullです。

CSP (Content Security Policy)

IdentityServerは、必要に応じて、いくつかの応答に対してCSPヘッダーを発行します。

  • Level
    使用するCSPのレベル。CSPレベル2がデフォルトで使用されますが、古いブラウザをサポートする必要がある場合は、これCspLevel.Oneに合わせてこれを変更してください。
  • AddDeprecatedHeader
    古いX-Content-Security-PolicyCSPヘッダーも(標準ベースのヘッダー値に加えて)発行する必要があるかどうかを示します。デフォルトはtrueです。

Device Flow

  • DefaultUserCodeType
    The user code type to use, unless set at the client level. Defaults to Numeric, a 9-digit code.
  • Interval
    Defines the minimum allowed polling interval on the token endpoint. Defaults to 5.

Entity Framework Support

EntityFrameworkベースの実装は、IdentityServerの構成データと操作上のデータ拡張ポイントに提供されます。EntityFrameworkを使用すると、EFでサポートされているデータベースをこのライブラリで使用できます。

このライブラリのレポはここにあり、NuGetパッケージはここにあります。

このライブラリーが提供する機能は、構成ストアとオペレーティング・ストアの2つの主要な領域に分かれています。これらの2つの異なる領域は、ホスティングアプリケーションのニーズに応じて、単独でまたは一緒に使用できます。

Configuration Store support for Clients, Resources, and CORS settings

クライアント、IDリソース、APIリソース、またはCORSデータを、EFでサポートされているデータベース(インメモリ構成を使用するのではなく)からロードする必要がある場合は、構成ストアを使用できます。このサポートは、実装の提供IClientStore、IResourceStoreおよびICorsPolicyService拡張ポイント。これらの実装では、データベース内のテーブルをモデル化するためにDbContext呼び出される継承クラスを使用ConfigurationDbContextします。

構成ストアサポートを使用するにはAddConfigurationStore、次の呼び出しの後に拡張メソッドを使用しますAddIdentityServer。

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.EntityFramework-2.0.0;trusted_connection=yes;";
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    services.AddIdentityServer()
        // this adds the config data from DB (clients, resources, CORS)
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));
        });
}

構成ストアを構成するConfigurationStoreOptionsには、構成コールバックに渡されたオプションオブジェクトを使用します。

ConfigurationStoreOptions

このオプションクラスには、構成ストアとコンポーネントを制御するプロパティが含まれていますConfigurationDbContext。

ConfigureDbContext
Action<DbContextOptionsBuilder>基底を構成するコールバックとして使用される型のデリゲートConfigurationDbContext。デリゲートはConfigurationDbContext、EFが直接使用されている場合と同じ方法でAddDbContextEFをサポートするデータベースを使用できます。
DefaultSchema
のすべてのテーブルのデフォルトのデータベーススキーマ名を設定できますConfigurationDbContext。

Operational Store support for authorization grants, consents, and tokens (refresh and reference)

認可付与、同意、およびトークン(リフレッシュと参照)をEFサポートデータベース(デフォルトのインメモリデータベースではなく)からロードすることが望まれる場合、運用ストアを使用できます。このサポートは、IPersistedGrantStore拡張ポイントの実装を提供します。この実装では、データベース内のテーブルをモデル化するためにDbContext呼び出さPersistedGrantDbContextれた継承クラスを使用します。

操作可能なストアサポートを使用するにはAddOperationalStore、次の呼び出しの後に拡張メソッドを使用しますAddIdentityServer。

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.EntityFramework-2.0.0;trusted_connection=yes;";
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    services.AddIdentityServer()
        // this adds the operational data from DB (codes, tokens, consents)
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = builder =>
                builder.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));

            // this enables automatic token cleanup. this is optional.
            options.EnableTokenCleanup = true;
            options.TokenCleanupInterval = 30; // interval in seconds
        });
}

運用ストアを設定するOperationalStoreOptionsには、設定コールバックに渡されたオプションオブジェクトを使用します。

OperationalStoreOptions

このオプションクラスには、操作可能なストアと操作を制御するプロパティが含まれていますPersistedGrantDbContext。

ConfigureDbContext
Delegate of type Action<DbContextOptionsBuilder> used as a callback to configure the underlying PersistedGrantDbContext. The delegate can configure the PersistedGrantDbContext in the same way if EF were being used directly with AddDbContext, which allows any EF-supported database to be used.
DefaultSchema
Allows setting the default database schema name for all the tables in the PersistedGrantDbContext.
EnableTokenCleanup
古いエントリがデータベースから自動的にクリーンアップされるかどうかを示します。デフォルトはfalseです。
TokenCleanupInterval
トークンクリーンアップ間隔(秒単位)。デフォルトは3600(1時間)です。

Database creation and schema changes across different versions of IdentityServer

異なるバージョンのIdentityServer(およびEFサポート)では、新しく変化する機能に対応するためにデータベーススキーマが変更される可能性が非常に高いです。

私たちはあなたのデータベースを作成したり、あるバージョンから別のバージョンにデータを移行したりするためのサポートを提供していません。組織が適切と考える方法で、データベースの作成、スキーマの変更、およびデータの移行を管理することが求められます。

EFの移行を使用することがこれに可能なアプローチの1つです。移行を使用する場合は、EFクイックスタートでサンプルを入手してください。または、EF移行に関する Microsoftのマニュアルを参照してください。

現バージョンのデータベーススキーマのサンプルSQLスクリプトも公開しています。

ASP.NET IDのサポート

IdentityServerのユーザーのIDデータベースを管理するためのASP.NET IDベースの実装が提供されています。この実装では、ユーザーがトークンにクレームを発行するためのIDデータをロードするために必要なIdentityServerの拡張ポイントが実装されています。

このサポートのレポはここにあり、NuGetパッケージはここにあります。

このライブラリを使用するには、通常ASP.NET IDを設定します。次にAddAspNetIdentity、次の呼び出しの後に拡張メソッドを使用しますAddIdentityServer。

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddIdentityServer()
        .AddAspNetIdentity<ApplicationUser>();
}

AddAspNetIdentityASP.NET ID(およびAddIdentityASP.NET IDをコンフィグレーションするために渡されたのと同じもの)をモデル化するクラスをジェネリックパラメータとして必要とします。これによりIUserClaimsPrincipalFactory、IdentityServerが、、、IResourceOwnerPasswordValidatorおよびのASP.NET ID実装を使用するように設定されますIProfileService。また、IdentityServerで使用するASP.NETアイデンティティのオプション(クレームタイプの使用や認証Cookie設定など)も設定します。

トレーニング

ASP.NETコアIDとIdentityServer4の詳細については、オンライン、リモート、およびクラスルームのトレーニングオプションをご覧ください。

Identity & Access Control for modern Applications (using ASP.NET Core 2 and IdentityServer4)

それは、私たちが会議、オンサイト、リモートの一環として提供する私たち自身の3日間のフラッグシップコース(広範なハンズオンラボを含む)です。

公的訓練のための議題と日程は ここで 見つけることができます、プライベートワークショップのために私たちに 連絡 してください。

ブログ記事