> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-fix-docs-5528-php-updates.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ASP.NET Coreの実装（Webアプリ + SSO）

> 通常のWebアプリアーキテクチャーシナリオでのシングルサインオン（SSO）のためのASP.NET Coreの実装

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

ASP.NET Coreの実装で使用する全ソースコードは、[こちらのGitHubリポジトリ](https://github.com/auth0-samples/auth0-pnp-webapp-oidc)でご覧いただけます。

## クッキーおよびOIDCミドルウェアを構成する

このガイドの目的のために、シンプルなホスト型ログインを使用します。標準クッキーと、ASP.NET Coreで利用できるOIDCミドルウェアを使用できるため、NuGetパッケージをインストールしてください。

```lines theme={null}
Install-Package Microsoft.AspNetCore.Authentication.Cookies
Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect
```

その後、アプリケーションのミドルウェアパイプライン内でクッキーとOIDCミドルウェアを構成します。

export const codeExample = `public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Add authentication services
        services.AddAuthentication(
            options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);

        // Code omitted for brevity...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<Auth0Settings> auth0Settings)
    {
        // Code omitted for brevity...

        // Add the cookie middleware
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AutomaticAuthenticate = true,
            AutomaticChallenge = true
        });

        // Add the OIDC middleware
        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
        {
            // Set the authority to your Auth0 domain
            Authority = "https://{yourDomain}/",

            // Configure the Auth0 Client ID and Client Secret
            ClientId = {yourClientId},
            ClientSecret = {yourClientSecret},

            // Do not automatically authenticate and challenge
            AutomaticAuthenticate = false,
            AutomaticChallenge = false,

            // Set response type to code
            ResponseType = "code",

            CallbackPath = new PathString("/signin-auth0"),

            // Configure the Claims Issuer to be Auth0
            ClaimsIssuer = "Auth0"
        });

        // Code omitted for brevity...
    }
}`;

<AuthCodeBlock children={codeExample} language="csharp" />

上記のコードでは、2つの異なるタイプの認証ミドルウェアを構成しました。

1つ目は、`UseCookieAuthentication`の呼び出しに登録されたクッキーミドルウェアです。2つ目は、`UseOpenIdConnectAuthentication`の呼び出しで実行されるOIDCミドルウェアです。

ユーザーがOIDCミドルウェアを使用してAuth0にサインインすると、ユーザーの情報はセッションクッキー内に自動的に保存されます。上記の通りにミドルウェアを構成するだけで、ユーザーセッションは管理されます。

<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=openid" tip="OpenID: アプリケーションがログイン情報を収集および保存することなくにユーザーのIDを検証できるようにする認証用のオープン標準。" cta="用語集の表示">OpenID</Tooltip> Connect（OIDC）ミドルウェアはまた、ユーザーが認証されたらAuth0から送信されるIDトークンからクレームすべてを抽出し、それを`ClaimsIdentity`のクレームとして追加します。

## ログアウトを実装する

`AuthenticationManager`クラスの`SignOutAsync`メソッドを使用し、サインアウトしたい認証スキームを伝えて、アプリケーションセッションとAuth0セッションの両方をコントロールできます。

クッキーミドルウェアのサインアウトと、それによるアプリケーションの認証クッキーの消去の例として、以下の呼び出しを作成できます。

```csharp lines theme={null}
await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
```

同様に、`SignOutAsync`メソッドを呼び出し、サインアウトするために認証スキームとして`Auth0`を伝えることで、ユーザーをAuth0からログアウトできます。

```csharp lines theme={null}
await HttpContext.Authentication.SignOutAsync("Auth0");
```

ただし上記が機能するためには、`OnRedirectToIdentityProviderForSignOut`イベントを処理して、OIDCミドルウェアを登録するときに別の構成を追加する必要があります。イベント内で、Auth0クッキーを消去する[Auth0ログアウトエンドポイント](https://auth0.com/docs/api/authentication/reference#logout)にリダイレクトする必要があります。

```csharp lines theme={null}
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
{
    // Some code omitted for brevity
    Events = new OpenIdConnectEvents
    {
        OnRedirectToIdentityProviderForSignOut = context =>
        {
            context.Response.Redirect($"https://{auth0Settings.Value.Domain}/v2/logout?client_id={auth0Settings.Value.ClientId}&returnTo={context.Request.Scheme}://{context.Request.Host}/");
            context.HandleResponse();

            return Task.FromResult(0);
        }
    }
});
```

また、<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=auth0-dashboard" tip="Auth0 Dashboard: サービスを構成するためのAuth0の主製品。" cta="用語集の表示">Auth0 Dashboard</Tooltip>内のアプリケーションのために、アプリケーションのURLを **［Allowed Logout URLs（許可されているログアウトURL）］** に追加する必要があります。詳細については、[ログアウト](https://auth0.com/docs/logout)を参照してください。

## 管理者権限の実装

グループをASP.NET Coreアプリケーションに組み入れる最も簡単な方法は、ASP.NET Coreで利用可能な組み込みの[ロールベースの認可](https://docs.asp.net/en/latest/security/authorization/roles.html)を使用することです。これを達成するには、ユーザーが割り当てられるそれぞれのグループについて、

```lines theme={null}
http://schemas.microsoft.com/ws/2008/06/identity/claims/role
```

上記タイプのクレームを追加する必要があります。

クレームが追加されたら、クレームを`[Authorize(Roles = "Admin")]`属性で装飾することで、簡単に特定のアクションを`Admin`のみに利用可能にできます。また、コントローラー内で`User.IsInRole("Admin")`を呼び出して、ユーザーがコードの特定のロールかどうかを確認できます。

ASP.NET OIDCミドルウェアは、<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-3" href="/docs/ja-jp/glossary?term=json-web-token" tip="JSON Web Token（JWT）: 二者間のクレームを安全に表現するために使用される標準IDトークン形式（および多くの場合、アクセストークン形式）。" cta="用語集の表示">JWT</Tooltip>で返されたすべてのクレームを、クレームとして`ClaimsIdentity`に自動的に追加します。このため、`authorization`クレームから情報を抽出し、クレームのJSONボディーを逆シリアル化して、グループごとに、`http://schemas.microsoft.com/ws/2008/06/identity/claims/role`クレームを`ClaimsIdentity`に追加する必要があります。

```csharp lines theme={null}
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
{
    // Some configuration omitted for brevity

    Events = new OpenIdConnectEvents
    {
        OnTicketReceived = context =>
        {
            var options = context.Options as OpenIdConnectOptions;

            // Get the ClaimsIdentity
            var identity = context.Principal.Identity as ClaimsIdentity;
            if (identity != null)
            {
                // Add the groups as roles
                var authzClaim = context.Principal.FindFirst(c => c.Type == "authorization");
                if (authzClaim != null)
                {
                    var authorization = JsonConvert.DeserializeObject<Auth0Authorization>(authzClaim.Value);
                    if (authorization != null)
                    {
                        foreach (var group in authorization.Groups)
                        {
                            identity.AddClaim(new Claim(ClaimTypes.Role, group, ClaimValueTypes.String, options.Authority));
                        }
                    }
                }
            }

            return Task.FromResult(0);
        }
    }
});
```

その後、管理者にタイムシートの承認を許可するアクションを追加できます。

```csharp lines theme={null}
[Authorize(Roles = "Admin")]
public IActionResult TimesheetApproval()
{          
    return View();
}
```
