import UriInputField from '@/mdx-components/UriInputField';
import Tabs from '@mdx/components/Tabs';
import TabItem from '@mdx/components/TabItem';
import InlineNotification from '@/ds-components/InlineNotification';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';

<Steps>

<Step title="Get started">

This tutorial will show you how to use Logto ASP.NET Core authentication middleware to protect your web application.

<ul>
  <li>It assumes your website is hosted on <code>{props.sampleUrls.origin}</code>.</li>
</ul>

### Installation

```bash
dotnet add package Logto.AspNetCore.Authentication
```

</Step>

<Step title="Add Logto authentication">

Open `Startup.cs` (or `Program.cs`) and add the following code to register Logto authentication middleware:

<pre>
  <code className="language-csharp">
{`using Logto.AspNetCore.Authentication;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddLogtoAuthentication(options =>
{
  options.Endpoint = "${props.endpoint}";
  options.AppId = "${props.app.id}";
  options.AppSecret = "${props.app.secret}";
});

app.UseAuthentication();`}
  </code>
</pre>

The `AddLogtoAuthentication` method will do the following things:

- Set the default authentication scheme to `LogtoDefaults.CookieScheme`.
- Set the default challenge scheme to `LogtoDefaults.AuthenticationScheme`.
- Set the default sign-out scheme to `LogtoDefaults.AuthenticationScheme`.
- Add cookie and OpenID Connect authentication handlers to the authentication scheme.

</Step>

<Step title="Sign-in">

<p>
First, let's enter your redirect URI. E.g. <code>{props.sampleUrls.origin + 'Callback'}</code> (replace the endpoint with yours). This is where Logto will redirect users after they sign in.
</p>

<UriInputField name="redirectUris" />

Remember to keep the path `/Callback` in the URI as it's the default value for the Logto authentication middleware.

To sign-in with Logto, you can use the `ChallengeAsync` method:

```csharp
await HttpContext.ChallengeAsync(new AuthenticationProperties
{
  // The URI below is different from the redirect URI you entered above.
  // It's the URI where users will be redirected after successfully signed in.
  // You can change it to any path you want.
  RedirectUri = "/"
});
```

For example, if you are using Razor Pages, you can add the following code to the `Index` page model:

```csharp
public class IndexModel : PageModel
{
  // ...
  public async Task OnPostSignInAsync()
  {
    await HttpContext.ChallengeAsync(new AuthenticationProperties
    {
      RedirectUri = "/"
    });
  }
}
```

And then add the following code to the `Index` page:

```html
<p>Is authenticated: @User.Identity?.IsAuthenticated</p>
<form method="post">
  <button type="submit" asp-page-handler="SignIn">Sign in</button>
</form>
```

</Step>

<Step title="Sign-out">

To clean up both ASP.NET session and Logto session, we can designate a post sign-out redierct URI. This is where Logto will redirect users after they sign out.

<p>
For example, set the URI to <code>{props.sampleUrls.origin + 'SignedOutCallback'}</code> (replace the endpoint with yours):
</p>

<UriInputField name="postLogoutRedirectUris" />

Remember to keep the path `/SignedOutCallback` in the URI as it's the default value for the Logto authentication middleware.

To sign-out with Logto, you can use the `SignOutAsync` method:

```csharp
await HttpContext.SignOutAsync(new AuthenticationProperties
{
  // The URI below is different from the post sign-out redirect URI you entered above.
  // It's the URI where users will be redirected after successfully signed out.
  // You can change it to any path you want.
  RedirectUri = "/"
});
```

The `SignOutAsync` method will clear the authentication cookie and redirect the user to the Logto sign-out page.

For example, if you are using Razor Pages, you can add the following code to the `Index` page model:

```csharp
public class IndexModel : PageModel
{
  // ...
  public async Task OnPostSignOutAsync()
  {
    await HttpContext.SignOutAsync(new AuthenticationProperties
    {
      RedirectUri = "/"
    });
  }
}
```

Then, update the form on your Razor page:

```html
<p>Is authenticated: @User.Identity?.IsAuthenticated</p>
<form method="post">
  @if (User.Identity?.IsAuthenticated == true)
  {
    <button type="submit" asp-page-handler="SignOut">Sign out</button>
  } else {
    <button type="submit" asp-page-handler="SignIn">Sign in</button>
  }
</form>
```

It will show the "Sign in" button if the user is not authenticated, and show the "Sign out" button if the user is authenticated.

</Step>

<Step title="Checkpoint: Test your application">

Now you can run the web application and try to sign in and sign out with Logto:

1. Open the web application in your browser, you should see "Is authenticated: False" and the "Sign in" button.
2. Click the "Sign in" button, and you should be redirected to the Logto sign-in page.
3. After you have signed in, you should be redirected back to the web application, and you should see "Is authenticated: True" and the "Sign out" button.
4. Click the "Sign out" button, and you should be redirected to the Logto sign-out page, and then redirected back to the web application.

</Step>

<Step title="The user object">

To know if the user is authenticated, you can check the `User.Identity?.IsAuthenticated` property.

To get the user profile claims, you can use the `User.Claims` property:

```csharp
var claims = User.Claims;

// Get the user ID
var userId = claims.FirstOrDefault(c => c.Type == LogtoParameters.Claims.Subject)?.Value;
```

See the [full tutorial](https://github.com/logto-io/csharp/tree/HEAD/src/Logto.AspNetCore.Authentication/docs/tutorial.md) for more details.

</Step>

</Steps>
