import UriInputField from '@/mdx-components/UriInputField';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';
import CustomDomainEndpointNotice from '@/mdx-components/CustomDomainEndpointNotice';

import Checkpoint from '../../fragments/_checkpoint.md';
import RedirectUrisWeb, { defaultRedirectUri, defaultPostSignOutUri } from '../../fragments/_redirect-uris-web.mdx';

<Steps>

<Step title="Get started">

This guide will show you how to use [Blorc.OpenIdConnect](https://github.com/WildGums/Blorc.OpenIdConnect) to add Logto authentication to a Blazor WebAssembly application.

### Installation

```bash
dotnet add package Blorc.OpenIdConnect
```

</Step>

<Step title="Add Blorc.OpenIdConnect to the project">

### Add script references

Include `Blorc.Core/injector.js` the `index.html` file:

```html title="index.html"
<head>
  <!-- ... -->
  <script src="_content/Blorc.Core/injector.js"></script>
  <!-- ... -->
</head>
```

### Register services

Add the following code to the `Program.cs` file:

```csharp title="Program.cs"
using Blorc.OpenIdConnect;
using Blorc.Services;

builder.Services.AddBlorcCore();
builder.Services.AddAuthorizationCore();
builder.Services.AddBlorcOpenIdConnect(
    options =>
    {
        builder.Configuration.Bind("IdentityServer", options);
    });

var webAssemblyHost = builder.Build();

await webAssemblyHost
    .ConfigureDocumentAsync(async documentService =>
    {
        await documentService.InjectBlorcCoreJsAsync();
        await documentService.InjectOpenIdConnectAsync();
    });

await webAssemblyHost.RunAsync();
```

Note: There's no need to use the `Microsoft.AspNetCore.Components.WebAssembly.Authentication` package. The `Blorc.OpenIdConnect` package will take care of the authentication process.

</Step>

<Step title="Configure redirect URIs">

<RedirectUrisWeb />

</Step>

<Step title="Configure application">

Add the following code to the `appsettings.json` file:

<Code className="language-json5" title="appsettings.json">
{`// ...
  IdentityServer: {
    Authority: '${props.endpoint}oidc',
    ClientId: '${props.app.id}',
    RedirectUri: '${props.redirectUris[0] ?? defaultRedirectUri}',
    PostLogoutRedirectUri: '${props.postLogoutRedirectUris[0] ?? defaultPostSignOutUri}',
    ResponseType: 'code',
    Scope: 'openid profile', // Add more scopes if needed
  },
}
`}
  </Code>

<br/>

<CustomDomainEndpointNotice />
</Step>

<Step title="Sign-in and sign-out">

### Add `AuthorizeView` component

In the Razor pages that require authentication, add the `AuthorizeView` component. Let's assume it's the `Home.razor` page:

```cshtml title="Pages/Home.razor"
@using Microsoft.AspNetCore.Components.Authorization
@page "/"

<AuthorizeView>
    <Authorized>
        @* Signed in view *@
        <button @onclick="OnLogoutButtonClickAsync">
            Sign out
        </button>
    </Authorized>
    <NotAuthorized>
        @* Unauthenticated view *@
        <button @onclick="OnLoginButtonClickAsync">
            Sign in
        </button>
    </NotAuthorized>
</AuthorizeView>
```

### Set up authentication

In the `Home.razor.cs` file (create it if it doesn't exist), add the following code:

```csharp title="Pages/Home.razor.cs"
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Blorc.OpenIdConnect;
using Microsoft.AspNetCore.Components.Authorization;

[Authorize]
public partial class Home : ComponentBase
{
    [Inject]
    public required IUserManager UserManager { get; set; }

    public User<Profile>? User { get; set; }

    [CascadingParameter]
    protected Task<AuthenticationState>? AuthenticationStateTask { get; set; }

    protected override async Task OnInitializedAsync()
    {
        User = await UserManager.GetUserAsync<User<Profile>>(AuthenticationStateTask!);
    }

    private async Task OnLoginButtonClickAsync(MouseEventArgs obj)
    {
        await UserManager.SignInRedirectAsync();
    }

    private async Task OnLogoutButtonClickAsync(MouseEventArgs obj)
    {
        await UserManager.SignOutRedirectAsync();
    }
}
```

Once the user is authenticated, the `User` property will be populated with the user information.

</Step>

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

<Checkpoint />

</Step>

<Step title="Display user information">

Here are some examples of how to display user information in the `Home.razor` page:

```cshtml title="Pages/Home.razor"
<AuthorizeView>
    <Authorized>
        @* Signed in view *@
        @* ... *@
        <p>You are signed in as @(@User?.Profile?.Name ?? "(unknown name)").</p>
    </Authorized>
    @* ... *@
</AuthorizeView>
```

For more properties and claims, check the `User` and `Profile` classes in the `Blorc.OpenIdConnect` package.

</Step>

</Steps>
