坂本  健一

坂本 健一

1637699460

Auth0認証にC#拡張メソッドを使用する

C#拡張メソッドを使用すると、既存のクラスに新しい機能を簡単に追加できます。それらを活用してASP.NETWebアプリのAuth0構成を簡素化する方法を学びます。

ASP.NETWebアプリとAuth0

ASP.NET WebアプリケーションにAuth0認証を追加するのは非常に簡単で、特定のAuth0SDKは必要ありません。標準のMicrosoft.AspNetCore.Authentication.OpenIdConnectパッケージを使用するだけで、Webアプリケーションがユーザー認証にOpenID Connect(OIDC)プロトコルを使用できるようになります。Auth0で構成された典型的なASP.NETWebアプリがどのように見えるかを見てみましょう。

サンプルアプリの入手

この記事に付属するサンプルアプリケーションには.NETCore 3.1 SDKが必要ですが、プロジェクトのターゲットフレームワークを変更するだけで、.NET5で実行するように簡単に適合させることができます。

最初のステップとして、このGitHubリポジトリの開始点ブランチからプロジェクトをダウンロードします。これを行うには、ターミナルウィンドウで次のコマンドを実行します。

git clone -b starting-point https://github.com/auth0-blog/auth0-dotnet-extension-methods.git

プロジェクトは、ユーザーのプロファイルにアクセスするために認証を必要とする基本的なASP.NETMVCアプリケーションを実装します。これは、Auth0 ASP.NETCoreクイックスタートの結果です。

WebアプリをAuth0に登録する

アプリケーションを実行するには、アプリケーションをAuth0に登録し、いくつかのパラメーターを使用して構成する必要があります。これを行うには、Auth0ダッシュボードにアクセスし、[アプリケーション]セクションに移動します。Auth0アカウントをまだお持ちでない場合は、今すぐ無料のアカウントにサインアップできます。

[アプリケーション]セクションに移動したら、次の手順に従ってアプリケーションをAuth0に登録します。

  1. [アプリケーション作成]ボタンをクリックします
  2. アプリケーションにわかりやすい名前を付け(たとえば、サンプルASP.NET MVCアプリ)、アプリケーションの種類として[通常のWebアプリケーション]を選択します。
  3. 最後に、[作成]ボタンをクリックします

アプリケーションを作成したら、[設定]タブに移動し、Auth0ドメインクライアントID、およびクライアントシークレットをメモします。アプリケーションを構成し、Auth0と通信できるようにするには、これらの値が必要になります。

次に、値を[許可されたコールバックURL]フィールドに割り当て、値を[許可されたログアウトURL]フィールドに割り当てます。最初の値は、ユーザーが認証した後にコールバックするURLをAuth0に指示します。2番目の値は、ユーザーがログアウトした後にリダイレクトするURLをAuth0に指示します。https://localhost:5001/callbackhttps://localhost:5001/

最後に、[変更保存]ボタンをクリックして適用します。

Webアプリの構成

アプリケーションをAuth0に登録した後、ダッシュボードからいくつかのパラメーターを使用してアプリケーションを構成する必要があります。したがって、ASP.NETプロジェクトのルートフォルダーに移動して、ファイルを開きます。その内容は次のようになります。appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Auth0": {
    "Domain": "{DOMAIN}",
    "ClientId": "{CLIENT_ID}",
    "ClientSecret": "{CLIENT_SECRET}"
  }
}

、、およびプレースホルダーをAuth0ダッシュボードの対応する値に置き換えて、ファイルを保存します。{DOMAIN}{CLIENT_ID}{CLIENT_SECRET}

クライアントシークレットをアプリケーションのパスワードと見なします。気をつけて、広めないでください。ここでは、サンプルアプリケーションがサーバー上で実行されることを意図しており、ユーザーがそれにアクセスできないため、クライアントシークレットをファイルに保存しています。appsettings.json

アプリの実行

この時点で、次のコマンドを実行してサンプルアプリケーションを起動できるはずです。

dotnet run

数秒で、アプリケーションが起動します。ブラウザでhttps:// localhost:5001アドレスを指定するとアクセスできます。ブラウザに次のページが表示されます。

サンプルアプリのホームページ

ページの右上隅にある[ログイン]リンクをクリックすると、認証のためにAuth0ユニバーサルログインページにリダイレクトされます。

Auth0ユニバーサルログイン

認証すると、ヘッダーに新しいリンクが表示され、自分のプロファイルを確認できます。

ユーザープロファイルページ

コードを見てください

前に述べたように、ASP.NET MVCアプリケーションとAuth0の統合は、Microsoft.AspNetCore.Authentication.OpenIdConnectパッケージに依存して ます。ファイルを開いてメソッドを分析することで、その使用方法と構成方法を確認できます。Startup.csConfigureServices()

// Startup.cs

// ...other code...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        .AddOpenIdConnect("Auth0", options => {
            options.Authority = $"https://{Configuration["Auth0:Domain"]}";
    
            options.ClientId = Configuration["Auth0:ClientId"];
            options.ClientSecret = Configuration["Auth0:ClientSecret"];
    
            options.ResponseType = OpenIdConnectResponseType.Code;
    
            options.Scope.Clear();
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
    
            options.CallbackPath = new PathString("/callback");
    
            options.ClaimsIssuer = "Auth0";
    
            options.SaveTokens = true;
    
            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name"
            };
    
            options.Events = new OpenIdConnectEvents
            {
                OnRedirectToIdentityProviderForSignOut = (context) =>
                {
                    var logoutUri = $"https://{Configuration["Auth0:Domain"]}/v2/logout?client_id={Configuration["Auth0:ClientId"]}";
    
                    var postLogoutUri = context.Properties.RedirectUri;
                    if (!string.IsNullOrEmpty(postLogoutUri))
                    {
                        if (postLogoutUri.StartsWith("/"))
                        {
                            var request = context.Request;
                            postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                        }
                        logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
                    }
    
                    context.Response.Redirect(logoutUri);
                    context.HandleResponse();
    
                    return Task.CompletedTask;
                }
            };
        });
    
        services.AddControllersWithViews();
    }

// ...other code...

このメソッドは、OIDCプロトコルのサポートをアプリケーションに追加します。ただし、OIDCオプションを設定するアクションデリゲートを渡して構成する必要があります。ご覧のとおり、Auth0でOIDCを正しく使用するには、多くのオプションを設定する必要があります。AddOpenIdConnect()

これらの設定のほとんどは、Auth0構成の一般的なケースでは定数値です。また、メソッドの詳細な構成コードにより、が読みにくくなります。最後に、Auth0を使用してユーザーを認証する新しいアプリケーションごとに、この長い一連の割り当てを繰り返す必要があります。ConfigureServices()

Auth0構成でこのアプローチを単純化する方法はありますか?

C#拡張メソッドを使用することで、この目標をシンプルかつエレガントな方法で達成できます。

このアプリケーションのコードとその実装方法については詳しく説明しません。このサンプルアプリケーションがどのように構築されているかについて詳しく知りたい場合は、Auth0ASP.NETクイックスタートを確認してください。

C#拡張メソッドとは何ですか?

拡張メソッドはC#の機能であり、新しい派生型を作成したり、元の型を変更したりすることなく、既存の型にメソッドを追加できます。これは静的メソッドですが、元のタイプのメソッドであるかのように呼び出すことができます。

例を使用して、拡張メソッドがどのように機能するかを詳しく見てみましょう。文字列内の母音の数を返す新しいメソッドを追加して、クラスを拡張するとします。この新しいメソッドを呼び出しましょう。この拡張機能は、次のコードで実装できます。System.StringVowelsCount()

using System;
using System.Linq; 

namespace MyExtensionMethods
{
    public static class StringExtensions
    {
        public static int VowelsCount(this String inputString)
        {
            return inputString.Count(c => "aeiou".Contains(Char.ToLower(c)));
        }
    }
}

StringExtension上記のクラスのメソッドは、私たちが探している機能を追加します。それは普通のクラスの普通のメソッドのように見えます。ただし、パラメーターのthis前の修飾子inputStringが違いを生みます。このメソッドをStringクラスに追加していることをコンパイラーに通知します。

この実装により、次の例のようにメソッドを呼び出すことができます。VowelsCount()

string sentence = "This is a sample sentence.";

Console.WriteLine(sentence.VowelsCount());

拡張メソッドは素晴らしく、実装が簡単です。これらは、ソースコードが制御できないクラスを拡張する必要がある場合に特に役立ちます。ただし、覚えておくべきいくつかの注意事項があります。元のクラス定義が変更され、拡張メソッドと同じシグネチャを持つ新しいメソッドを取得した場合、拡張メソッドは呼び出されません。したがって、それらを賢く使用してください。

拡張メソッドとしてのAuth0認証

C#拡張メソッド機能を利用して、ASP.NETMVCアプリケーションでのAuth0の一般的な構成を簡素化してみましょう。

最初のステップとして、Authenticationサンプルプロジェクトのルートフォルダーに新しいフォルダーを作成します。この新しいフォルダー内に、次の内容のファイルを作成します。Auth0Defaults.cs

//Authentication/Auth0Defaults.cs

using Microsoft.AspNetCore.Http;

namespace Auth0.NET.Authentication
{
    public class Auth0Defaults
    {
        public const string AuthenticationScheme = "Auth0";
        public const string ClaimsIssuer = "Auth0";

        public static readonly string CallbackPath = new PathString("/callback");
    }
}

このクラスは、1分で使用するいくつかの定数を定義するだけです。

同じフォルダに、という名前の別のファイルを作成し、その内容として次のように設定します。Auth0Options.cs

//Authentication/Auth0Options.cs

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

namespace Auth0.NET.Authentication
{ 
    public class Auth0Options : OpenIdConnectOptions
    {
        public string Domain { get; set; }

        public Auth0Options()
        {
            ResponseType = OpenIdConnectResponseType.Code;
    
            Scope.Clear();
            Scope.Add("openid");
            Scope.Add("profile");
            Scope.Add("email");
    
            CallbackPath = Auth0Defaults.CallbackPath;
            ClaimsIssuer = Auth0Defaults.ClaimsIssuer;
            SaveTokens = true;
    
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name"
            };
        }
    }
}

Auth0Optionsクラスから継承OpenIdConnectOptionsクラスと定義Auth0構成のデフォルトのオプション値。

最後に、実際の拡張子メソッドを含むファイルを作成しましょう。その内容は次のとおりです。Auth0Extensions.cs

//Authentication/Auth0Extensions.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection;

namespace Auth0.NET.Authentication
{
    public static class Auth0Extensions
    {
        public static AuthenticationBuilder AddAuth0(this AuthenticationBuilder builder, Action<Auth0Options> configureOptions)
        {
            return builder.AddAuth0(Auth0Defaults.AuthenticationScheme, configureOptions);
        }
    

        public static AuthenticationBuilder AddAuth0(this AuthenticationBuilder builder, string authenticationScheme, Action<Auth0Options> configureOptions)
        {
            var auth0Options = new Auth0Options();
    
            configureOptions(auth0Options);
    
            return builder.AddOpenIdConnect(authenticationScheme, options =>
            {
                options.Authority = $"https://{auth0Options.Domain}";
                options.ClientId = auth0Options.ClientId;
                options.ClientSecret = auth0Options.ClientSecret;
                options.ResponseType = auth0Options.ResponseType;
    
                options.Scope.Clear();
                foreach(var scope in auth0Options.Scope)
                {
                    options.Scope.Add(scope);
                }
    
                options.CallbackPath = auth0Options.CallbackPath;
                options.ClaimsIssuer = auth0Options.ClaimsIssuer;
                options.SaveTokens = auth0Options.SaveTokens;
    
                options.TokenValidationParameters = auth0Options.TokenValidationParameters;
    
                options.Events = new OpenIdConnectEvents
                {
                    OnRedirectToIdentityProviderForSignOut = (context) =>
                    {
                        var logoutUri = $"{options.Authority}/v2/logout?client_id={options.ClientId}";
    
                        var postLogoutUri = context.Properties.RedirectUri;
                        if (!string.IsNullOrEmpty(postLogoutUri))
                        {
                            if (postLogoutUri.StartsWith("/"))
                            {
                                var request = context.Request;
    
                                postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                            }
    
                            logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
                        }
    
                        context.Response.Redirect(logoutUri);
                        context.HandleResponse();
    
                        return Task.CompletedTask;
                    }
                };
            });
        }
    }
}

このファイルで定義された方法は、内蔵の拡張クラスを。その定義は、基本クラスの標準メソッドに準拠するようにオーバーロードされています。基本的に、デフォルトの認証スキーム名()を使用するか、独自の名前を指定することにより、メソッドを呼び出すことができます。拡張メソッドのロジック全体は最後の定義にあり、メソッドで使用したすべてのオプション設定を見つけることができます。AddAuth0()AuthenticationBuilderAddAuth0()Auth0ConfigureServices()

ただし、メソッドの最初の2つのステートメントを検討してください。AddAuth0()

//Authentication/Auth0Extensions.cs

//...other code...

        public static AuthenticationBuilder AddAuth0(this AuthenticationBuilder builder, string authenticationScheme, Action<Auth0Options> configureOptions)
        {
            var auth0Options = new Auth0Options();
    
            configureOptions(auth0Options);
    
            return builder.AddOpenIdConnect(authenticationScheme, options =>
            {
                //...other code...
            }
        }

//...other code...

最初のステートメントは、Auth0Optionsクラスのインスタンスを作成します。2番目のステートメントは、そのクラスインスタンスでアクションを実行して、外部構成を適用します。これにより、不足している構成パラメーターを追加し、デフォルト設定をオーバーライドできます。configureOption()

Auth0拡張メソッドの使用

前のセクションで実装した拡張メソッドをどのように使用できるかを見てみましょう。サンプルプロジェクトのルートフォルダーにあるファイルを開き、現在のメソッド定義を次のコードに置き換えます。AddAuth0()Startup.csConfigureServices()

// Startup.cs
// ...existing using...
using Auth0.NET.Authentication;  //👈 new addition

// ...existing code...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        //👇 changed code
        .AddAuth0(options => {
            options.Domain = Configuration["Auth0:Domain"];
            options.ClientId = Configuration["Auth0:ClientId"];
            options.ClientSecret = Configuration["Auth0:ClientSecret"];
        });
        //👆 changed code
    
        services.AddControllersWithViews();
    }

// ...other code...

名前空間への参照を追加しました。これにより、拡張メソッドが使用可能になります。次に、すべてのコードを置き換えて、OpenIDConnectをこの単純な呼び出しで構成しました。提供する必要がある設定は、ファイルに追加したAuth0パラメーターのみです。それでおしまい!Auth0.NET.AuthenticationAddAuth0()appsettings.json

これにより、基本的なケースでのAuth0統合が簡素化され、メソッドのコードが読みやすくなります。ConfigureServices()

さらに高度な構成を提供する機能はまだあります。たとえば、別のコールバックページを指定する場合は、次のように実行できます。

// Startup.cs
// ...existing code...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        .AddAuth0(options => {
            options.Domain = Configuration["Auth0:Domain"];
            options.ClientId = Configuration["Auth0:ClientId"];
            options.ClientSecret = Configuration["Auth0:ClientSecret"];
            //👇 new addition
            options.CallbackPath = new PathString("/callback-page");
        });
    
        services.AddControllersWithViews();
    }

// ...other code...

これで、ASP.NETWebアプリケーションでAuth0を構成する簡単な方法ができました。

概要

この記事は、クラスのメソッドで標準のMicrosoft.AspNetCore.Authentication.OpenIdConnectパッケージを使用してAuth0を構成する方法を調べることから始めました。あなたはそれがどれほど冗長であるか、そしてそれがどのように体を読みにくくするかを見てきました。ConfigureServices()StartupConfigureServices()

C#拡張メソッドとは何か、およびそれらがどのように機能するかを学習した後、Auth0構成を分離するためにクラスの拡張メソッドを実装しました。これにより、メソッドで使用されるAuth0構成コードを大幅に簡素化できます。AddAuth0()AuthenticationBuilderConfigureServices()

リンク: https://auth0.com/blog/using-csharp-extension-methods-for-auth0-authentication/

#auth0 #csharp 

What is GEEK

Buddha Community

Auth0認証にC#拡張メソッドを使用する
坂本  健一

坂本 健一

1637699460

Auth0認証にC#拡張メソッドを使用する

C#拡張メソッドを使用すると、既存のクラスに新しい機能を簡単に追加できます。それらを活用してASP.NETWebアプリのAuth0構成を簡素化する方法を学びます。

ASP.NETWebアプリとAuth0

ASP.NET WebアプリケーションにAuth0認証を追加するのは非常に簡単で、特定のAuth0SDKは必要ありません。標準のMicrosoft.AspNetCore.Authentication.OpenIdConnectパッケージを使用するだけで、Webアプリケーションがユーザー認証にOpenID Connect(OIDC)プロトコルを使用できるようになります。Auth0で構成された典型的なASP.NETWebアプリがどのように見えるかを見てみましょう。

サンプルアプリの入手

この記事に付属するサンプルアプリケーションには.NETCore 3.1 SDKが必要ですが、プロジェクトのターゲットフレームワークを変更するだけで、.NET5で実行するように簡単に適合させることができます。

最初のステップとして、このGitHubリポジトリの開始点ブランチからプロジェクトをダウンロードします。これを行うには、ターミナルウィンドウで次のコマンドを実行します。

git clone -b starting-point https://github.com/auth0-blog/auth0-dotnet-extension-methods.git

プロジェクトは、ユーザーのプロファイルにアクセスするために認証を必要とする基本的なASP.NETMVCアプリケーションを実装します。これは、Auth0 ASP.NETCoreクイックスタートの結果です。

WebアプリをAuth0に登録する

アプリケーションを実行するには、アプリケーションをAuth0に登録し、いくつかのパラメーターを使用して構成する必要があります。これを行うには、Auth0ダッシュボードにアクセスし、[アプリケーション]セクションに移動します。Auth0アカウントをまだお持ちでない場合は、今すぐ無料のアカウントにサインアップできます。

[アプリケーション]セクションに移動したら、次の手順に従ってアプリケーションをAuth0に登録します。

  1. [アプリケーション作成]ボタンをクリックします
  2. アプリケーションにわかりやすい名前を付け(たとえば、サンプルASP.NET MVCアプリ)、アプリケーションの種類として[通常のWebアプリケーション]を選択します。
  3. 最後に、[作成]ボタンをクリックします

アプリケーションを作成したら、[設定]タブに移動し、Auth0ドメインクライアントID、およびクライアントシークレットをメモします。アプリケーションを構成し、Auth0と通信できるようにするには、これらの値が必要になります。

次に、値を[許可されたコールバックURL]フィールドに割り当て、値を[許可されたログアウトURL]フィールドに割り当てます。最初の値は、ユーザーが認証した後にコールバックするURLをAuth0に指示します。2番目の値は、ユーザーがログアウトした後にリダイレクトするURLをAuth0に指示します。https://localhost:5001/callbackhttps://localhost:5001/

最後に、[変更保存]ボタンをクリックして適用します。

Webアプリの構成

アプリケーションをAuth0に登録した後、ダッシュボードからいくつかのパラメーターを使用してアプリケーションを構成する必要があります。したがって、ASP.NETプロジェクトのルートフォルダーに移動して、ファイルを開きます。その内容は次のようになります。appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Auth0": {
    "Domain": "{DOMAIN}",
    "ClientId": "{CLIENT_ID}",
    "ClientSecret": "{CLIENT_SECRET}"
  }
}

、、およびプレースホルダーをAuth0ダッシュボードの対応する値に置き換えて、ファイルを保存します。{DOMAIN}{CLIENT_ID}{CLIENT_SECRET}

クライアントシークレットをアプリケーションのパスワードと見なします。気をつけて、広めないでください。ここでは、サンプルアプリケーションがサーバー上で実行されることを意図しており、ユーザーがそれにアクセスできないため、クライアントシークレットをファイルに保存しています。appsettings.json

アプリの実行

この時点で、次のコマンドを実行してサンプルアプリケーションを起動できるはずです。

dotnet run

数秒で、アプリケーションが起動します。ブラウザでhttps:// localhost:5001アドレスを指定するとアクセスできます。ブラウザに次のページが表示されます。

サンプルアプリのホームページ

ページの右上隅にある[ログイン]リンクをクリックすると、認証のためにAuth0ユニバーサルログインページにリダイレクトされます。

Auth0ユニバーサルログイン

認証すると、ヘッダーに新しいリンクが表示され、自分のプロファイルを確認できます。

ユーザープロファイルページ

コードを見てください

前に述べたように、ASP.NET MVCアプリケーションとAuth0の統合は、Microsoft.AspNetCore.Authentication.OpenIdConnectパッケージに依存して ます。ファイルを開いてメソッドを分析することで、その使用方法と構成方法を確認できます。Startup.csConfigureServices()

// Startup.cs

// ...other code...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        .AddOpenIdConnect("Auth0", options => {
            options.Authority = $"https://{Configuration["Auth0:Domain"]}";
    
            options.ClientId = Configuration["Auth0:ClientId"];
            options.ClientSecret = Configuration["Auth0:ClientSecret"];
    
            options.ResponseType = OpenIdConnectResponseType.Code;
    
            options.Scope.Clear();
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
    
            options.CallbackPath = new PathString("/callback");
    
            options.ClaimsIssuer = "Auth0";
    
            options.SaveTokens = true;
    
            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name"
            };
    
            options.Events = new OpenIdConnectEvents
            {
                OnRedirectToIdentityProviderForSignOut = (context) =>
                {
                    var logoutUri = $"https://{Configuration["Auth0:Domain"]}/v2/logout?client_id={Configuration["Auth0:ClientId"]}";
    
                    var postLogoutUri = context.Properties.RedirectUri;
                    if (!string.IsNullOrEmpty(postLogoutUri))
                    {
                        if (postLogoutUri.StartsWith("/"))
                        {
                            var request = context.Request;
                            postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                        }
                        logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
                    }
    
                    context.Response.Redirect(logoutUri);
                    context.HandleResponse();
    
                    return Task.CompletedTask;
                }
            };
        });
    
        services.AddControllersWithViews();
    }

// ...other code...

このメソッドは、OIDCプロトコルのサポートをアプリケーションに追加します。ただし、OIDCオプションを設定するアクションデリゲートを渡して構成する必要があります。ご覧のとおり、Auth0でOIDCを正しく使用するには、多くのオプションを設定する必要があります。AddOpenIdConnect()

これらの設定のほとんどは、Auth0構成の一般的なケースでは定数値です。また、メソッドの詳細な構成コードにより、が読みにくくなります。最後に、Auth0を使用してユーザーを認証する新しいアプリケーションごとに、この長い一連の割り当てを繰り返す必要があります。ConfigureServices()

Auth0構成でこのアプローチを単純化する方法はありますか?

C#拡張メソッドを使用することで、この目標をシンプルかつエレガントな方法で達成できます。

このアプリケーションのコードとその実装方法については詳しく説明しません。このサンプルアプリケーションがどのように構築されているかについて詳しく知りたい場合は、Auth0ASP.NETクイックスタートを確認してください。

C#拡張メソッドとは何ですか?

拡張メソッドはC#の機能であり、新しい派生型を作成したり、元の型を変更したりすることなく、既存の型にメソッドを追加できます。これは静的メソッドですが、元のタイプのメソッドであるかのように呼び出すことができます。

例を使用して、拡張メソッドがどのように機能するかを詳しく見てみましょう。文字列内の母音の数を返す新しいメソッドを追加して、クラスを拡張するとします。この新しいメソッドを呼び出しましょう。この拡張機能は、次のコードで実装できます。System.StringVowelsCount()

using System;
using System.Linq; 

namespace MyExtensionMethods
{
    public static class StringExtensions
    {
        public static int VowelsCount(this String inputString)
        {
            return inputString.Count(c => "aeiou".Contains(Char.ToLower(c)));
        }
    }
}

StringExtension上記のクラスのメソッドは、私たちが探している機能を追加します。それは普通のクラスの普通のメソッドのように見えます。ただし、パラメーターのthis前の修飾子inputStringが違いを生みます。このメソッドをStringクラスに追加していることをコンパイラーに通知します。

この実装により、次の例のようにメソッドを呼び出すことができます。VowelsCount()

string sentence = "This is a sample sentence.";

Console.WriteLine(sentence.VowelsCount());

拡張メソッドは素晴らしく、実装が簡単です。これらは、ソースコードが制御できないクラスを拡張する必要がある場合に特に役立ちます。ただし、覚えておくべきいくつかの注意事項があります。元のクラス定義が変更され、拡張メソッドと同じシグネチャを持つ新しいメソッドを取得した場合、拡張メソッドは呼び出されません。したがって、それらを賢く使用してください。

拡張メソッドとしてのAuth0認証

C#拡張メソッド機能を利用して、ASP.NETMVCアプリケーションでのAuth0の一般的な構成を簡素化してみましょう。

最初のステップとして、Authenticationサンプルプロジェクトのルートフォルダーに新しいフォルダーを作成します。この新しいフォルダー内に、次の内容のファイルを作成します。Auth0Defaults.cs

//Authentication/Auth0Defaults.cs

using Microsoft.AspNetCore.Http;

namespace Auth0.NET.Authentication
{
    public class Auth0Defaults
    {
        public const string AuthenticationScheme = "Auth0";
        public const string ClaimsIssuer = "Auth0";

        public static readonly string CallbackPath = new PathString("/callback");
    }
}

このクラスは、1分で使用するいくつかの定数を定義するだけです。

同じフォルダに、という名前の別のファイルを作成し、その内容として次のように設定します。Auth0Options.cs

//Authentication/Auth0Options.cs

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

namespace Auth0.NET.Authentication
{ 
    public class Auth0Options : OpenIdConnectOptions
    {
        public string Domain { get; set; }

        public Auth0Options()
        {
            ResponseType = OpenIdConnectResponseType.Code;
    
            Scope.Clear();
            Scope.Add("openid");
            Scope.Add("profile");
            Scope.Add("email");
    
            CallbackPath = Auth0Defaults.CallbackPath;
            ClaimsIssuer = Auth0Defaults.ClaimsIssuer;
            SaveTokens = true;
    
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name"
            };
        }
    }
}

Auth0Optionsクラスから継承OpenIdConnectOptionsクラスと定義Auth0構成のデフォルトのオプション値。

最後に、実際の拡張子メソッドを含むファイルを作成しましょう。その内容は次のとおりです。Auth0Extensions.cs

//Authentication/Auth0Extensions.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection;

namespace Auth0.NET.Authentication
{
    public static class Auth0Extensions
    {
        public static AuthenticationBuilder AddAuth0(this AuthenticationBuilder builder, Action<Auth0Options> configureOptions)
        {
            return builder.AddAuth0(Auth0Defaults.AuthenticationScheme, configureOptions);
        }
    

        public static AuthenticationBuilder AddAuth0(this AuthenticationBuilder builder, string authenticationScheme, Action<Auth0Options> configureOptions)
        {
            var auth0Options = new Auth0Options();
    
            configureOptions(auth0Options);
    
            return builder.AddOpenIdConnect(authenticationScheme, options =>
            {
                options.Authority = $"https://{auth0Options.Domain}";
                options.ClientId = auth0Options.ClientId;
                options.ClientSecret = auth0Options.ClientSecret;
                options.ResponseType = auth0Options.ResponseType;
    
                options.Scope.Clear();
                foreach(var scope in auth0Options.Scope)
                {
                    options.Scope.Add(scope);
                }
    
                options.CallbackPath = auth0Options.CallbackPath;
                options.ClaimsIssuer = auth0Options.ClaimsIssuer;
                options.SaveTokens = auth0Options.SaveTokens;
    
                options.TokenValidationParameters = auth0Options.TokenValidationParameters;
    
                options.Events = new OpenIdConnectEvents
                {
                    OnRedirectToIdentityProviderForSignOut = (context) =>
                    {
                        var logoutUri = $"{options.Authority}/v2/logout?client_id={options.ClientId}";
    
                        var postLogoutUri = context.Properties.RedirectUri;
                        if (!string.IsNullOrEmpty(postLogoutUri))
                        {
                            if (postLogoutUri.StartsWith("/"))
                            {
                                var request = context.Request;
    
                                postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                            }
    
                            logoutUri += $"&returnTo={ Uri.EscapeDataString(postLogoutUri)}";
                        }
    
                        context.Response.Redirect(logoutUri);
                        context.HandleResponse();
    
                        return Task.CompletedTask;
                    }
                };
            });
        }
    }
}

このファイルで定義された方法は、内蔵の拡張クラスを。その定義は、基本クラスの標準メソッドに準拠するようにオーバーロードされています。基本的に、デフォルトの認証スキーム名()を使用するか、独自の名前を指定することにより、メソッドを呼び出すことができます。拡張メソッドのロジック全体は最後の定義にあり、メソッドで使用したすべてのオプション設定を見つけることができます。AddAuth0()AuthenticationBuilderAddAuth0()Auth0ConfigureServices()

ただし、メソッドの最初の2つのステートメントを検討してください。AddAuth0()

//Authentication/Auth0Extensions.cs

//...other code...

        public static AuthenticationBuilder AddAuth0(this AuthenticationBuilder builder, string authenticationScheme, Action<Auth0Options> configureOptions)
        {
            var auth0Options = new Auth0Options();
    
            configureOptions(auth0Options);
    
            return builder.AddOpenIdConnect(authenticationScheme, options =>
            {
                //...other code...
            }
        }

//...other code...

最初のステートメントは、Auth0Optionsクラスのインスタンスを作成します。2番目のステートメントは、そのクラスインスタンスでアクションを実行して、外部構成を適用します。これにより、不足している構成パラメーターを追加し、デフォルト設定をオーバーライドできます。configureOption()

Auth0拡張メソッドの使用

前のセクションで実装した拡張メソッドをどのように使用できるかを見てみましょう。サンプルプロジェクトのルートフォルダーにあるファイルを開き、現在のメソッド定義を次のコードに置き換えます。AddAuth0()Startup.csConfigureServices()

// Startup.cs
// ...existing using...
using Auth0.NET.Authentication;  //👈 new addition

// ...existing code...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        //👇 changed code
        .AddAuth0(options => {
            options.Domain = Configuration["Auth0:Domain"];
            options.ClientId = Configuration["Auth0:ClientId"];
            options.ClientSecret = Configuration["Auth0:ClientSecret"];
        });
        //👆 changed code
    
        services.AddControllersWithViews();
    }

// ...other code...

名前空間への参照を追加しました。これにより、拡張メソッドが使用可能になります。次に、すべてのコードを置き換えて、OpenIDConnectをこの単純な呼び出しで構成しました。提供する必要がある設定は、ファイルに追加したAuth0パラメーターのみです。それでおしまい!Auth0.NET.AuthenticationAddAuth0()appsettings.json

これにより、基本的なケースでのAuth0統合が簡素化され、メソッドのコードが読みやすくなります。ConfigureServices()

さらに高度な構成を提供する機能はまだあります。たとえば、別のコールバックページを指定する場合は、次のように実行できます。

// Startup.cs
// ...existing code...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie()
        .AddAuth0(options => {
            options.Domain = Configuration["Auth0:Domain"];
            options.ClientId = Configuration["Auth0:ClientId"];
            options.ClientSecret = Configuration["Auth0:ClientSecret"];
            //👇 new addition
            options.CallbackPath = new PathString("/callback-page");
        });
    
        services.AddControllersWithViews();
    }

// ...other code...

これで、ASP.NETWebアプリケーションでAuth0を構成する簡単な方法ができました。

概要

この記事は、クラスのメソッドで標準のMicrosoft.AspNetCore.Authentication.OpenIdConnectパッケージを使用してAuth0を構成する方法を調べることから始めました。あなたはそれがどれほど冗長であるか、そしてそれがどのように体を読みにくくするかを見てきました。ConfigureServices()StartupConfigureServices()

C#拡張メソッドとは何か、およびそれらがどのように機能するかを学習した後、Auth0構成を分離するためにクラスの拡張メソッドを実装しました。これにより、メソッドで使用されるAuth0構成コードを大幅に簡素化できます。AddAuth0()AuthenticationBuilderConfigureServices()

リンク: https://auth0.com/blog/using-csharp-extension-methods-for-auth0-authentication/

#auth0 #csharp