mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(console): add asp.net core tutorial
This commit is contained in:
parent
2d111bd39b
commit
d90b4e7f65
8 changed files with 214 additions and 11 deletions
5
.changeset/purple-clouds-jog.md
Normal file
5
.changeset/purple-clouds-jog.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@logto/console": minor
|
||||
---
|
||||
|
||||
add asp.net core tutorial
|
|
@ -12,6 +12,7 @@ import spaReact from './spa-react/index';
|
|||
import spaVanilla from './spa-vanilla/index';
|
||||
import spaVue from './spa-vue/index';
|
||||
import { type Guide } from './types';
|
||||
import webAspNetCore from './web-asp-net-core/index';
|
||||
import webExpress from './web-express/index';
|
||||
import webGo from './web-go/index';
|
||||
import webGptPlugin from './web-gpt-plugin/index';
|
||||
|
@ -65,6 +66,12 @@ const guides: Readonly<Guide[]> = Object.freeze([
|
|||
Component: lazy(async () => import('./web-remix/README.mdx')),
|
||||
metadata: webRemix,
|
||||
},
|
||||
{
|
||||
id: 'web-asp-net-core',
|
||||
Logo: lazy(async () => import('./web-asp-net-core/logo.svg')),
|
||||
Component: lazy(async () => import('./web-asp-net-core/README.mdx')),
|
||||
metadata: webAspNetCore,
|
||||
},
|
||||
{
|
||||
id: 'web-outline',
|
||||
Logo: lazy(async () => import('./web-outline/logo.svg')),
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
import UriInputField from '@/mdx-components-v2/UriInputField';
|
||||
import Tabs from '@mdx/components/Tabs';
|
||||
import TabItem from '@mdx/components/TabItem';
|
||||
import InlineNotification from '@/ds-components/InlineNotification';
|
||||
import { buildIdGenerator } from '@logto/shared/universal';
|
||||
import Steps from '@/mdx-components-v2/Steps';
|
||||
import Step from '@/mdx-components-v2/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}";${props.alternativeEndpoint ? ' // or "${props.alternativeEndpoint}"' : ''}
|
||||
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>
|
|
@ -3,10 +3,14 @@ import { ApplicationType } from '@logto/schemas';
|
|||
import { type GuideMetadata } from '../types';
|
||||
|
||||
const metadata: Readonly<GuideMetadata> = Object.freeze({
|
||||
name: 'C#',
|
||||
name: 'ASP.NET Core',
|
||||
description:
|
||||
'C# is a general-purpose, object-oriented programming language developed by Microsoft.',
|
||||
'ASP.NET Core is a cross-platform and open-source framework for building modern applications.',
|
||||
target: ApplicationType.Traditional,
|
||||
sample: {
|
||||
repo: 'csharp',
|
||||
path: 'sample',
|
||||
},
|
||||
});
|
||||
|
||||
export default metadata;
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><defs><style>.cls-1{fill:#5c2d91;}.cls-2,.cls-3{fill:#fff;}.cls-2{opacity:0.1;}.cls-4{fill:#f2f2f2;}</style></defs><title>logo_NETcore</title><circle class="cls-1" cx="32" cy="32" r="32"/><path class="cls-2" d="M9.82,9A32,32,0,1,0,55,54.18Z"/><path class="cls-3" d="M7.4,37.25a1.35,1.35,0,0,1-1-.42,1.38,1.38,0,0,1-.41-1,1.4,1.4,0,0,1,.41-1,1.34,1.34,0,0,1,1-.43,1.37,1.37,0,0,1,1,.43,1.39,1.39,0,0,1,.42,1,1.37,1.37,0,0,1-.42,1A1.38,1.38,0,0,1,7.4,37.25Z"/><path class="cls-3" d="M27.27,37H24.65L15.28,22.46a6,6,0,0,1-.58-1.14h-.08a18.72,18.72,0,0,1,.1,2.5V37H12.59V18.77h2.77l9.12,14.28q.57.89.74,1.22h.05a19.28,19.28,0,0,1-.13-2.68V18.77h2.13Z"/><path class="cls-3" d="M41.69,37H32V18.77h9.24V20.7H34.18v6.06h6.58v1.92H34.18V35h7.52Z"/><path class="cls-3" d="M56,20.7H50.7V37H48.57V20.7H43.33V18.77H56Z"/><path class="cls-4" d="M26.12,49.4a4.93,4.93,0,0,1-2.32.49,3.74,3.74,0,0,1-2.87-1.15,4.26,4.26,0,0,1-1.08-3,4.46,4.46,0,0,1,1.21-3.26,4.12,4.12,0,0,1,3.08-1.24,4.93,4.93,0,0,1,2,.35v1a4,4,0,0,0-2-.5,3.06,3.06,0,0,0-2.35,1,3.64,3.64,0,0,0-.9,2.58,3.47,3.47,0,0,0,.84,2.45,2.86,2.86,0,0,0,2.21.91,4.14,4.14,0,0,0,2.19-.56Z"/><path class="cls-4" d="M30.21,49.89A2.78,2.78,0,0,1,28.08,49a3.11,3.11,0,0,1-.79-2.23,3.24,3.24,0,0,1,.83-2.36,3,3,0,0,1,2.23-.85,2.69,2.69,0,0,1,2.09.83,3.28,3.28,0,0,1,.75,2.29,3.22,3.22,0,0,1-.81,2.3A2.84,2.84,0,0,1,30.21,49.89Zm.07-5.47a1.83,1.83,0,0,0-1.46.63,2.59,2.59,0,0,0-.54,1.74,2.45,2.45,0,0,0,.54,1.68,1.85,1.85,0,0,0,1.46.62,1.76,1.76,0,0,0,1.43-.6,2.62,2.62,0,0,0,.5-1.72,2.66,2.66,0,0,0-.5-1.73A1.75,1.75,0,0,0,30.28,44.42Z"/><path class="cls-4" d="M37.86,44.72a1.18,1.18,0,0,0-.73-.19,1.23,1.23,0,0,0-1,.58,2.68,2.68,0,0,0-.41,1.58v3.06h-1v-6h1V45h0a2.1,2.1,0,0,1,.63-1,1.43,1.43,0,0,1,.94-.35,1.57,1.57,0,0,1,.57.08Z"/><path class="cls-4" d="M43.72,47H39.49A2.24,2.24,0,0,0,40,48.54a1.86,1.86,0,0,0,1.42.54,3,3,0,0,0,1.86-.67v.9a3.48,3.48,0,0,1-2.09.57,2.54,2.54,0,0,1-2-.82,3.35,3.35,0,0,1-.73-2.3,3.28,3.28,0,0,1,.79-2.28,2.55,2.55,0,0,1,2-.88,2.26,2.26,0,0,1,1.82.76,3.18,3.18,0,0,1,.64,2.12Zm-1-.81a2,2,0,0,0-.4-1.29,1.37,1.37,0,0,0-1.1-.46,1.55,1.55,0,0,0-1.15.49,2.21,2.21,0,0,0-.59,1.27Z"/></svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -1 +0,0 @@
|
|||
## Replace this with actual guide
|
|
@ -1,7 +0,0 @@
|
|||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M39.8578 16.6581C39.8575 16.0587 39.7293 15.529 39.4701 15.0745C39.2154 14.6274 38.8341 14.2527 38.3225 13.9565C34.0999 11.5217 29.8731 9.0943 25.6518 6.65702C24.5138 6.00001 23.4104 6.02409 22.2808 6.69053C20.6001 7.68162 12.1852 12.5027 9.67765 13.9551C8.64498 14.553 8.14249 15.4679 8.14224 16.657C8.14062 21.5535 8.14224 26.45 8.14062 31.3465C8.14062 31.9328 8.26361 32.4523 8.51145 32.9C8.76623 33.3605 9.15294 33.7455 9.67629 34.0484C12.1839 35.5008 20.5999 40.3215 22.2803 41.313C23.4104 41.9798 24.5138 42.0036 25.6522 41.3465C29.8736 38.9091 34.1006 36.4817 38.3239 34.0469C38.8472 33.7441 39.2339 33.3589 39.4887 32.8987C39.7362 32.4509 39.8594 31.9316 39.8594 31.3452C39.8594 31.3452 39.8594 21.5547 39.8578 16.6581Z" fill="#A179DC"/>
|
||||
<path d="M24.0483 23.954L8.51123 32.9C8.76602 33.3605 9.15272 33.7455 9.67607 34.0484C12.1837 35.5008 20.5997 40.3215 22.2801 41.313C23.4102 41.9798 24.5136 42.0036 25.652 41.3465C29.8734 38.9091 34.1004 36.4817 38.3236 34.0469C38.847 33.7441 39.2337 33.3589 39.4885 32.8987L24.0483 23.954Z" fill="#280068"/>
|
||||
<path d="M39.8576 16.6581C39.8573 16.0587 39.7291 15.529 39.4699 15.0745L24.0483 23.9542L39.4885 32.8987C39.736 32.451 39.859 31.9316 39.8592 31.3452C39.8592 31.3452 39.8592 21.5547 39.8576 16.6581Z" fill="#390091"/>
|
||||
<path d="M33.1961 20.6097V22.2819H34.8683V20.6097H35.7044V22.2819H37.3766V23.1179H35.7044V24.79H37.3766V25.6261H35.7044V27.2983H34.8683V25.6261H33.1961V27.2983H32.36V25.6261H30.688V24.79H32.36V23.1179H30.688V22.2819H32.36V20.6097H33.1961ZM34.8683 23.1178H33.1961V24.79H34.8683V23.1178Z" fill="white"/>
|
||||
<path d="M24.0825 12.2119C28.444 12.2119 32.2519 14.5806 34.2915 18.1014L34.2717 18.0675L29.14 21.0222C28.129 19.3104 26.2757 18.1551 24.1494 18.1313L24.0824 18.1309C20.8402 18.1309 18.2116 20.7595 18.2116 24.0017C18.2106 25.0236 18.4775 26.0279 18.9859 26.9144C19.9979 28.681 21.9002 29.8726 24.0825 29.8726C26.2783 29.8726 28.1915 28.6659 29.1982 26.8804L29.1737 26.9232L34.2976 29.8915C32.2803 33.3826 28.5246 35.7439 24.2138 35.791L24.0825 35.7917C19.7072 35.7917 15.8885 33.4084 13.854 29.869C12.8608 28.1411 12.2925 26.1379 12.2925 24.0017C12.2925 17.4904 17.5709 12.2118 24.0824 12.2118L24.0825 12.2119Z" fill="white"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.3 KiB |
|
@ -1 +0,0 @@
|
|||
## Replace this with actual guide
|
Loading…
Reference in a new issue