In an old project we used ASP.NET 4.5 and I would like to use the Framework OpenIdDict in it. It's made vor ASP.NET Core 1 and 2. Can I still use it? What do I have to pay attention to? If I can't use that, which alternatives do you know?
Link to OpenIdDict: https://github.com/openiddict/openiddict-core
OpenIddict is an open source and versatile framework for building standard-compliant OAuth 2.0/OpenID Connect servers in any ASP.NET Core 2.1 (and higher) and legacy ASP.NET 4.6. 1 (and higher) applications. OpenIddict was born in late 2015 and was initially based on AspNet. Security.
. Net Core does not support desktop application development and it rather focuses on the web, windows mobile, and windows store. . Net Framework is used for the development of both desktop and web applications as well as it supports windows forms and WPF applications.
ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern, cloud-enabled, Internet-connected apps. With ASP.NET Core, you can: Build web apps and services, Internet of Things (IoT) apps, and mobile backends. Use your favorite development tools on Windows, macOS, and Linux.
Edit: OpenIddict 3.0 is now natively compatible with OWIN/Katana and can be used in any >= ASP.NET 4.6.1 application without using any adapter. Read these two blog posts for more information:
Technically, it's possible to use middleware designed for ASP.NET Core 1.x/2.x in an ASP.NET 4.x application by using the Microsoft.AspNetCore.Owin
adapter package and some tweaking.
Here's a prototype of an OWIN self-hosted console application (it would be very similar with an ASP.NET 4.x application using the OWIN SystemWeb
host):
using System;
using Microsoft.Owin.Hosting;
namespace OpenIddictOwinDemo
{
public static class Program
{
public static void Main(string[] args)
{
const string address = "http://localhost:12556/";
using (WebApp.Start<Startup>(address))
{
Console.WriteLine($"Server is running on {address}, press CTRL+C to stop.");
Console.ReadLine();
}
}
}
}
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Owin;
namespace OpenIddictOwinDemo
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseBuilder(ConfigureServices(), Configure);
}
IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
// In a real ASP.NET Core application, these services are
// registered by the hosting stack. Since this application
// is actually an OWIN app, they must be registered manually.
var listener = new DiagnosticListener("Microsoft.AspNetCore");
services.AddSingleton<DiagnosticListener>(listener);
services.AddSingleton<DiagnosticSource>(listener);
services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
services.AddDbContext<DbContext>(options =>
{
options.UseInMemoryDatabase("db");
});
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<DbContext>();
})
.AddServer(options =>
{
options.AcceptAnonymousClients();
options.AllowPasswordFlow();
options.EnableTokenEndpoint("/connect/token");
options.DisableHttpsRequirement();
options.UseCustomTokenEndpoint();
});
return services.BuildServiceProvider(validateScopes: true);
}
void Configure(IApplicationBuilder app)
{
// This inline middleware is required to be able to use scoped services.
// In a real ASP.NET Core application, this is done for you by a special
// middleware automatically injected by the default hosting components.
app.Use(next => async context =>
{
var provider = context.RequestServices;
using (var scope = provider.CreateScope())
{
try
{
context.RequestServices = scope.ServiceProvider;
await next(context);
}
finally
{
context.RequestServices = provider;
}
}
});
app.UseDeveloperExceptionPage();
app.UseAuthentication();
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.FileProviders;
using Owin;
namespace OpenIddictOwinDemo
{
using AddMiddleware = Action<Func<
Func<IDictionary<string, object>, Task>,
Func<IDictionary<string, object>, Task>
>>;
using AppFunc = Func<IDictionary<string, object>, Task>;
public static class KatanaExtensions
{
public static IAppBuilder UseBuilder(this IAppBuilder app,
IServiceProvider provider, Action<IApplicationBuilder> configuration)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
if (provider == null)
{
throw new ArgumentNullException(nameof(provider));
}
if (configuration == null)
{
throw new ArgumentNullException(nameof(configuration));
}
AddMiddleware add = middleware =>
{
app.Use(new Func<AppFunc, AppFunc>(next => middleware(next)));
};
add.UseBuilder(configuration, provider);
return app;
}
}
public class HostingEnvironment : IHostingEnvironment
{
public string EnvironmentName { get; set; }
public string ApplicationName { get; set; }
public string WebRootPath { get; set; }
public IFileProvider WebRootFileProvider { get; set; }
public string ContentRootPath { get; set; }
public IFileProvider ContentRootFileProvider { get; set; }
}
}
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Primitives;
using Microsoft.Extensions.DependencyInjection;
using OpenIddict.Server;
namespace OpenIddictOwinDemo
{
public static class CustomOpenIddictServerExtensions
{
public static OpenIddictServerBuilder UseCustomTokenEndpoint(
this OpenIddictServerBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
return builder.AddEventHandler<OpenIddictServerEvents.HandleTokenRequest>(
notification =>
{
var request = notification.Context.Request;
if (!request.IsPasswordGrantType())
{
return Task.CompletedTask;
}
// Validate the user credentials.
// Note: to mitigate brute force attacks, you SHOULD strongly consider
// applying a key derivation function like PBKDF2 to slow down
// the password validation process. You SHOULD also consider
// using a time-constant comparer to prevent timing attacks.
if (request.Username != "[email protected]" ||
request.Password != "P@ssw0rd")
{
notification.Context.Reject(
error: OpenIdConnectConstants.Errors.InvalidGrant,
description: "The specified credentials are invalid.");
return Task.CompletedTask;
}
// Create a new ClaimsIdentity holding the user identity.
var identity = new ClaimsIdentity(
notification.Context.Scheme.Name,
OpenIdConnectConstants.Claims.Name,
OpenIdConnectConstants.Claims.Role);
// Add a "sub" claim containing the user identifier, and attach
// the "access_token" destination to allow OpenIddict to store it
// in the access token, so it can be retrieved from your controllers.
identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
"71346D62-9BA5-4B6D-9ECA-755574D628D8",
OpenIdConnectConstants.Destinations.AccessToken);
identity.AddClaim(OpenIdConnectConstants.Claims.Name, "Alice",
OpenIdConnectConstants.Destinations.AccessToken);
// ... add other claims, if necessary.
var principal = new ClaimsPrincipal(identity);
notification.Context.Validate(principal);
return Task.CompletedTask;
});
}
}
}
In practice, I wouldn't recommend it as it's a bit hackish (the Microsoft.AspNetCore.Owin
adapter hasn't been updated for years). Instead, you may want to adopt a micro-service architecture and move your OpenIddict-based authorization server to a separate ASP.NET Core service.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With