Skip to content

Latest commit

 

History

History
322 lines (242 loc) · 8.22 KB

File metadata and controls

322 lines (242 loc) · 8.22 KB
id dotnet
title Integrate authentication into ASP.NET
sidebar_label .NET / ASP.NET
displayed_sidebar quickstartsSidebar
import CodeBlock from '@theme/CodeBlock'

This guide shows how to create a simple ASP.NET application and secure it with authentication powered by Ory. You can use this guide with both Ory Network and self-hosted Ory software.

This guide is perfect for you if:

  1. You have .NET installed.
  2. You want to build an app using ASP.NET.
  3. You want to give access to your application to signed-in users only.

:::info

You can find the code of the sample application here.

:::

Create ASP.NET app

Create an empty web template as a starting point for this example. Run these commands:

mkdir your-project
cd your-project

dotnet new web

Install Ory SDK

Run this command to install the Ory SDK:

dotnet add package Ory.Client

Create a new Ory project

import CreateProject from '../_common/create-project.mdx'

<CreateProject />

Install Ory CLI

Follow this guide to install the Ory CLI on your machine.

Why do I need the Ory CLI

import OryCLI from '../_common/ory-cli.mdx'

<OryCLI isTunnel={true} />

Configure the SDK

Add the Ory Client to the template app. Make the following changes to the Program.cs file:

// add-lines-start
using Ory.Client.Api;
using Ory.Client.Client;
// add-lines-end

var builder = WebApplication.CreateBuilder(args);

// add-lines-start
// configure http port explicitly to override generated settings from launchSettings.json
builder.WebHost.ConfigureKestrel(opt => {
	var port = builder.Configuration.GetValue<int>("APP_PORT", 3000);
	opt.ListenAnyIP(port);
});
// add-lines-end

var app = builder.Build();

// add-lines-start
// create a new Ory Client with the BasePath set to the Ory Tunnel enpoint
var oryBasePath = builder.Configuration.GetValue<string>("ORY_BASEPATH") ?? "http://localhost:4000";
var ory = new FrontendApi(new Configuration
{
	BasePath = oryBasePath
});
// add-lines-end

app.MapGet("/", () => "Hello World!");

app.Run();

Validate and login

Next, create middleware that checks if the user has a valid session. The session is considered valid when the user is authenticated.

The middleware passes the request cookies to the Ory Client to check if the session is valid.

If the session is valid, the user is presented with the protected page. When the session is not valid, which means that the user is not authenticated or the session expired, the request is redirected for login using the Ory Account Experience.

using Ory.Client.Api;
using Ory.Client.Client;

var builder = WebApplication.CreateBuilder(args);

// configure http port explicitly to override generated settings from launchSettings.json
builder.WebHost.ConfigureKestrel(opt => {
	var port = builder.Configuration.GetValue<int>("APP_PORT", 3000);
	opt.ListenAnyIP(port);
});

var app = builder.Build();

// create a new Ory Client with the BasePath set to the Ory Tunnel enpoint
var oryBasePath = builder.Configuration.GetValue<string>("ORY_BASEPATH") ?? "http://localhost:4000";
var ory = new FrontendApi(new Configuration
{
	BasePath = oryBasePath
});

// add-lines-start
// add session middleware
app.Use(async (ctx, next) =>
{
	async Task Login()
	{
		// this will redirect the user to the managed Ory Login UI
		var flow = await ory.CreateBrowserLoginFlowAsync() ?? throw new InvalidOperationException("Could not create browser login flow");
		ctx.Response.Redirect(flow.RequestUrl);
	}

	try
	{
		// check if we have a session
		var session = await ory.ToSessionAsync(cookie: ctx.Request.Headers.Cookie, cancellationToken: ctx.RequestAborted);
		if (session?.Active is not true)
		{
			await Login();
			return;
		}

		// add session to HttpContext
		ctx.Items["req.session"] = session;
	}
	catch (ApiException)
	{
		await Login();
		return;
	}

	await next(ctx);
});
// add-lines-end

app.MapGet("/", () => "Hello World!");

app.Run();

The protected page

  1. Create the Index RazorPage page that shows session data to users with a valid session.

    dotnet new page --name Index --no-pagemodel --output Pages
    
  2. Add this code to the Pages/Index.cshtml file to present the data to the user:

    @page
    @{
    // add-lines-start
    // try to retrieve session from HttpContext
    var session = HttpContext.Items.TryGetValue("req.session", out var item) && item is Ory.Client.Model.ClientSession s ? s.ToJson() : "<NO SESSION>";
    // add-lines-end
    }
    
    // add-lines-start
    <html lang="en">
    <head>
       <title>Ory Network secured ASP.NET Core web app</title>
    </head>
    <body>
       <h1>Dashboard</h1>
       <hr />
       <h2>Your Session Data:</h2>
       <pre><code>@session</code></pre>
    </body>
    </html>
    // add-lines-end

Configure application

To configure the app to serve RazorPages, make the following changes in Program.cs. Make sure to replace the app.MapGet("/", () => "Hello World!"); line with app.MapRazorPages();.

using Ory.Client.Api;
using Ory.Client.Client;

var builder = WebApplication.CreateBuilder(args);

// configure http port explicitly to override generated settings from launchSettings.json
builder.WebHost.ConfigureKestrel(opt => {
	var port = builder.Configuration.GetValue<int>("APP_PORT", 3000);
	opt.ListenAnyIP(port);
});

// add-lines-start
// add support for RazorPages
builder.Services.AddRazorPages();
// add-lines-end

var app = builder.Build();

// create a new Ory Client with the BasePath set to the Ory Tunnel enpoint
var oryBasePath = builder.Configuration.GetValue<string>("ORY_BASEPATH") ?? "http://localhost:4000";
var ory = new FrontendApi(new Configuration
{
	BasePath = oryBasePath
});

// add session middleware
app.Use(async (ctx, next) =>
{
	async Task Login()
	{
		// this will redirect the user to the managed Ory Login UI
		var flow = await ory.CreateBrowserLoginFlowAsync() ?? throw new InvalidOperationException("Could not create browser login flow");
		ctx.Response.Redirect(flow.RequestUrl);
	}

	try
	{
		// check if we have a session
		var session = await ory.ToSessionAsync(cookie: ctx.Request.Headers.Cookie, cancellationToken: ctx.RequestAborted);
		if (session?.Active is not true)
		{
			await Login();
			return;
		}

		// add session to HttpContext
		ctx.Items["req.session"] = session;
	}
	catch (ApiException)
	{
		await Login();
		return;
	}

	await next(ctx);
});

// add-lines-start
// configure pipeline to use RazorPages
app.MapRazorPages();
// add-lines-end
// delete-next-line
app.MapGet("/", () => "Hello World!");

app.Run();

Test your application

With all of the pieces in place, it's time to test your application. Follow these steps:

  1. Start the application:

    dotnet run
    
  2. Run Ory Tunnel to mirror the Ory API endpoints on your application's domain (localhost):

    ory tunnel --project playground --dev http://localhost:3000
    
  3. Open localhost:3000 to access the application. As the initial call is made by an unauthenticated user, the middleware doesn't detect a valid session and redirects to the login page of the defined Ory project.

  4. From there, you can create a new account or sign in using an existing identity. When you sign in, the session becomes valid and the application shows the Index page with the session data.

:::tip

To see a more advanced example of integrating Ory with ASP.NET Core check out the examples repository.

:::

Go to production

import ToProd from '../_common/going-to-prod.mdx'

<ToProd />
// register a new Ory client with the URL set to the custom domain
var ory = new FrontendApi(new Configuration
{
	BasePath = "https://ory.example.org"
});