Integrate authentication into ASP.NET
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:
- You have .NET installed.
- You want to build an app using ASP.NET.
- You want to give access to your application to signed-in users only.
You can find the code of the sample application here.
Install Ory CLI
Follow this guide to install the Ory CLI on your machine.
Why do I Need the Ory CLI?
Ory CLI provides a convenient way to configure and manage projects. Additionally, the CLI contains Ory Tunnel, which exposes Ory APIs under the same top-level domain as your application to ensure that there are no CORS issues. This allows the application that runs on your machine to connect to Ory APIs.
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
Configure the SDK
Add the Ory Client to the template app. Make the following changes to the Program.cs
file:
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", 5001);
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
});
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", 5001);
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 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);
});
app.MapGet("/", () => "Hello World!");
app.Run();
The protected page
Create the
Index
RazorPage page that shows session data to users with a valid session.dotnet new page --name Index --no-pagemodel --output Pages
Add this code to the
Pages/Index.cshtml
file to present the data to the user:Pages/Index.cshtml@page
@{
// 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>";
}
<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>
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", 5001);
opt.ListenAnyIP(port);
});
// add support for RazorPages
builder.Services.AddRazorPages();
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);
});
// configure pipeline to use RazorPages
app.MapRazorPages();
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:
Start the application:
dotnet run
Run Ory Tunnel to mirror the Ory API endpoints on your application's domain (
localhost
):ory tunnel --project playground --dev http://localhost:5001
Open localhost:5001 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.
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.
To see a more advanced example of integrating Ory with ASP.NET Core check out the examples repository.
Go to production
You can use many different approaches to go to production with your application. You can deploy it on Kubernetes, AWS, a VM, a
RaspberryPi - the choice is yours! To connect the application to your Ory project, the app and Ory APIs must be available under
the same common domain, for example https://ory.example.com
and https://www.example.com
.
You can easily connect Ory to your subdomain. To do that, add a Custom Domain to your Ory Network project.
With the custom domain set up, you don't need to use Ory Proxy or Ory Tunnel to interact with Ory APIs. Instead, use the configured custom domain in your SDK calls:
// register a new Ory client with the URL set to the custom domain
var ory = new FrontendApi(new Configuration
{
BasePath = "https://ory.example.org"
});