diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs b/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs
index a0c253ce4..fbafdd8e5 100644
--- a/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs
@@ -179,6 +179,7 @@ public void Configuration(IAppBuilder app)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ ApplicationType = ApplicationTypes.Web,
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
ConsentType = ConsentTypes.Explicit,
@@ -215,6 +216,7 @@ await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ ApplicationType = ApplicationTypes.Native,
ClientId = "postman",
ConsentType = ConsentTypes.Systematic,
DisplayName = "Postman",
diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs
index a7ddd7332..f09047649 100644
--- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs
+++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs
@@ -30,6 +30,9 @@ static async Task RegisterApplicationsAsync(IServiceProvider provider)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ // Note: the application must be registered as a native application to force OpenIddict
+ // to apply a relaxed redirect_uri validation policy that allows specifying a random port.
+ ApplicationType = ApplicationTypes.Native,
ClientId = "console",
ConsentType = ConsentTypes.Systematic,
DisplayName = "Console client application",
@@ -39,17 +42,9 @@ await manager.CreateAsync(new OpenIddictApplicationDescriptor
},
RedirectUris =
{
- new Uri("http://localhost:49152/callback/login/local"),
- new Uri("http://localhost:49153/callback/login/local"),
- new Uri("http://localhost:49154/callback/login/local"),
- new Uri("http://localhost:49155/callback/login/local"),
- new Uri("http://localhost:49156/callback/login/local"),
- new Uri("http://localhost:49157/callback/login/local"),
- new Uri("http://localhost:49158/callback/login/local"),
- new Uri("http://localhost:49159/callback/login/local"),
- new Uri("http://localhost:49160/callback/login/local"),
- new Uri("http://localhost:49161/callback/login/local"),
- new Uri("http://localhost:49162/callback/login/local")
+ // Note: the port must not be explicitly specified as it is selected
+ // dynamically at runtime by the OpenIddict client system integration.
+ new Uri("http://localhost/callback/login/local")
},
Permissions =
{
@@ -76,6 +71,7 @@ await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ ApplicationType = ApplicationTypes.Web,
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
ConsentType = ConsentTypes.Explicit,
@@ -116,6 +112,7 @@ await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ ApplicationType = ApplicationTypes.Native,
ClientId = "winforms",
ConsentType = ConsentTypes.Systematic,
DisplayName = "WinForms client application",
@@ -150,6 +147,7 @@ await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ ApplicationType = ApplicationTypes.Native,
ClientId = "wpf",
ConsentType = ConsentTypes.Systematic,
DisplayName = "WPF client application",
@@ -209,6 +207,7 @@ await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
+ ApplicationType = ApplicationTypes.Native,
ClientId = "postman",
ConsentType = ConsentTypes.Systematic,
DisplayName = "Postman",
diff --git a/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs
index 0399d0f07..76391bbae 100644
--- a/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs
+++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs
@@ -1,4 +1,5 @@
-using System.Globalization;
+using System.ComponentModel;
+using System.Globalization;
using System.Text.Json;
namespace OpenIddict.Abstractions;
@@ -8,6 +9,11 @@ namespace OpenIddict.Abstractions;
///
public class OpenIddictApplicationDescriptor
{
+ ///
+ /// Gets or sets the application type associated with the application.
+ ///
+ public string? ApplicationType { get; set; }
+
///
/// Gets or sets the client identifier associated with the application.
///
@@ -20,6 +26,11 @@ public class OpenIddictApplicationDescriptor
///
public string? ClientSecret { get; set; }
+ ///
+ /// Gets or sets the client type associated with the application.
+ ///
+ public string? ClientType { get; set; }
+
///
/// Gets or sets the consent type associated with the application.
///
@@ -61,7 +72,13 @@ public class OpenIddictApplicationDescriptor
public HashSet Requirements { get; } = new(StringComparer.Ordinal);
///
- /// Gets or sets the application type associated with the application.
+ /// Gets or sets the client type associated with the application.
///
- public string? Type { get; set; }
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete($"This property was replaced by {nameof(ClientType)} and will be removed in a future version.", true)]
+ public string? Type
+ {
+ get => ClientType;
+ set => ClientType = value;
+ }
}
diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs
index 6e184cffe..e167d7d57 100644
--- a/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs
+++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs
@@ -130,6 +130,17 @@ IAsyncEnumerable