69 changed files with 2936 additions and 2190 deletions
@ -1,57 +0,0 @@ |
|||||
/* |
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|
||||
* the license and the contributors participating to this project. |
|
||||
*/ |
|
||||
|
|
||||
using System; |
|
||||
using JetBrains.Annotations; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
using Microsoft.Extensions.Options; |
|
||||
|
|
||||
namespace OpenIddict.Infrastructure { |
|
||||
/// <summary>
|
|
||||
/// Exposes the common services used by OpenIddict.
|
|
||||
/// </summary>
|
|
||||
public class OpenIddictServices<TApplication, TAuthorization, TScope, TToken> |
|
||||
where TApplication : class where TAuthorization : class |
|
||||
where TScope : class where TToken : class { |
|
||||
public OpenIddictServices([NotNull] IServiceProvider services) { |
|
||||
Services = services; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="OpenIddictApplicationManager{TApplication}"/>.
|
|
||||
/// </summary>
|
|
||||
public virtual OpenIddictApplicationManager<TApplication> Applications => |
|
||||
Services.GetRequiredService<OpenIddictApplicationManager<TApplication>>(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the optional <see cref="HttpContext"/>.
|
|
||||
/// </summary>
|
|
||||
public virtual HttpContext Context => Services.GetService<IHttpContextAccessor>()?.HttpContext; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="ILogger"/>.
|
|
||||
/// </summary>
|
|
||||
public virtual ILogger Logger => |
|
||||
Services.GetRequiredService<ILogger<OpenIddictProvider<TApplication, TAuthorization, TScope, TToken>>>(); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="OpenIddictOptions"/>.
|
|
||||
/// </summary>
|
|
||||
public virtual OpenIddictOptions Options => Services.GetRequiredService<IOptions<OpenIddictOptions>>().Value; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="IServiceProvider"/> used to resolve services.
|
|
||||
/// </summary>
|
|
||||
public virtual IServiceProvider Services { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="OpenIddictTokenManager{TToken}"/>.
|
|
||||
/// </summary>
|
|
||||
public virtual OpenIddictTokenManager<TToken> Tokens => Services.GetRequiredService<OpenIddictTokenManager<TToken>>(); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,40 @@ |
|||||
|
/* |
||||
|
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
* See https://github.com/openiddict/openiddict-core for more information concerning
|
||||
|
* the license and the contributors participating to this project. |
||||
|
*/ |
||||
|
|
||||
|
using System; |
||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using OpenIddict.Models; |
||||
|
|
||||
|
namespace OpenIddict.EntityFramework { |
||||
|
/// <summary>
|
||||
|
/// Represents a model customizer able to register the entity sets
|
||||
|
/// required by the OpenIddict stack in an Entity Framework context.
|
||||
|
/// </summary>
|
||||
|
public class OpenIddictCustomizer<TApplication, TAuthorization, TScope, TToken, TKey> : ModelCustomizer |
||||
|
where TApplication : OpenIddictApplication<TKey, TToken> |
||||
|
where TAuthorization : OpenIddictAuthorization<TKey, TToken> |
||||
|
where TScope : OpenIddictScope<TKey> |
||||
|
where TToken : OpenIddictToken<TKey> |
||||
|
where TKey : IEquatable<TKey> { |
||||
|
public override void Customize([NotNull] ModelBuilder builder, [NotNull] DbContext context) { |
||||
|
if (builder == null) { |
||||
|
throw new ArgumentNullException(nameof(builder)); |
||||
|
} |
||||
|
|
||||
|
if (context == null) { |
||||
|
throw new ArgumentNullException(nameof(context)); |
||||
|
} |
||||
|
|
||||
|
// Register the OpenIddict entity sets.
|
||||
|
builder.UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>(); |
||||
|
|
||||
|
base.Customize(builder, context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,199 +0,0 @@ |
|||||
/* |
|
||||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|
||||
* the license and the contributors participating to this project. |
|
||||
*/ |
|
||||
|
|
||||
using System; |
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; |
|
||||
using Microsoft.EntityFrameworkCore; |
|
||||
|
|
||||
namespace OpenIddict { |
|
||||
/// <summary>
|
|
||||
/// Represents an OpenIddict-powered Entity Framework context.
|
|
||||
/// </summary>
|
|
||||
public class OpenIddictDbContext : OpenIddictDbContext<IdentityUser> { |
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|
||||
/// </summary>
|
|
||||
protected OpenIddictDbContext() { } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context.
|
|
||||
/// </summary>
|
|
||||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|
||||
public OpenIddictDbContext(DbContextOptions options) : base(options) { } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents an OpenIddict-powered Entity Framework context.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|
||||
public class OpenIddictDbContext<TUser> : OpenIddictDbContext<TUser, IdentityRole, OpenIddictApplication, |
|
||||
OpenIddictAuthorization, |
|
||||
OpenIddictScope, |
|
||||
OpenIddictToken, string> |
|
||||
where TUser : IdentityUser { |
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|
||||
/// </summary>
|
|
||||
protected OpenIddictDbContext() { } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context.
|
|
||||
/// </summary>
|
|
||||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|
||||
public OpenIddictDbContext(DbContextOptions options) : base(options) { } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents an OpenIddict-powered Entity Framework context.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|
||||
/// <typeparam name="TRole">The type of the Role entity.</typeparam>
|
|
||||
public class OpenIddictDbContext<TUser, TRole> : OpenIddictDbContext<TUser, TRole, OpenIddictApplication, |
|
||||
OpenIddictAuthorization, |
|
||||
OpenIddictScope, |
|
||||
OpenIddictToken, string> |
|
||||
where TUser : IdentityUser |
|
||||
where TRole : IdentityRole { |
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|
||||
/// </summary>
|
|
||||
protected OpenIddictDbContext() { } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context.
|
|
||||
/// </summary>
|
|
||||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|
||||
public OpenIddictDbContext(DbContextOptions options) : base(options) { } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents an OpenIddict-powered Entity Framework context.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|
||||
/// <typeparam name="TRole">The type of the Role entity.</typeparam>
|
|
||||
/// <typeparam name="TKey">The type of the primary key used by the Identity/OpenIddict entities.</typeparam>
|
|
||||
public class OpenIddictDbContext<TUser, TRole, TKey> : OpenIddictDbContext<TUser, TRole, OpenIddictApplication<TKey>, |
|
||||
OpenIddictAuthorization<TKey>, |
|
||||
OpenIddictScope<TKey>, |
|
||||
OpenIddictToken<TKey>, TKey> |
|
||||
where TUser : IdentityUser<TKey> |
|
||||
where TRole : IdentityRole<TKey> |
|
||||
where TKey : IEquatable<TKey> { |
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|
||||
/// </summary>
|
|
||||
protected OpenIddictDbContext() { } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context.
|
|
||||
/// </summary>
|
|
||||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|
||||
public OpenIddictDbContext(DbContextOptions options) : base(options) { } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Represents an OpenIddict-powered Entity Framework context.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TUser">The type of the User entity.</typeparam>
|
|
||||
/// <typeparam name="TRole">The type of the Role entity.</typeparam>
|
|
||||
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
|
|
||||
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
|
|
||||
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
|
|
||||
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
|
|
||||
/// <typeparam name="TKey">The type of the primary key used by the Identity/OpenIddict entities.</typeparam>
|
|
||||
public class OpenIddictDbContext<TUser, TRole, TApplication, TAuthorization, TScope, TToken, TKey> : IdentityDbContext<TUser, TRole, TKey> |
|
||||
where TUser : IdentityUser<TKey> |
|
||||
where TRole : IdentityRole<TKey> |
|
||||
where TApplication : OpenIddictApplication<TKey, TToken> |
|
||||
where TAuthorization : OpenIddictAuthorization<TKey, TToken> |
|
||||
where TScope : OpenIddictScope<TKey> |
|
||||
where TToken : OpenIddictToken<TKey> |
|
||||
where TKey : IEquatable<TKey> { |
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context without configuring the Entity Framework options.
|
|
||||
/// </summary>
|
|
||||
protected OpenIddictDbContext() { } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new OpenIddict context.
|
|
||||
/// </summary>
|
|
||||
/// <param name="options">The options used to configure the Entity Framework context.</param>
|
|
||||
public OpenIddictDbContext(DbContextOptions options) : base(options) { } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the database set containing the applications.
|
|
||||
/// </summary>
|
|
||||
public DbSet<TApplication> Applications { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the database set containing the authorizations.
|
|
||||
/// </summary>
|
|
||||
public DbSet<TAuthorization> Authorizations { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the database set containing the scopes.
|
|
||||
/// </summary>
|
|
||||
public DbSet<TScope> Scopes { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets the database set containing the tokens.
|
|
||||
/// </summary>
|
|
||||
public DbSet<TToken> Tokens { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Registers the OpenIddict entities in the Entity Framework context.
|
|
||||
/// </summary>
|
|
||||
/// <param name="builder">The model builder used by Entity Framework.</param>
|
|
||||
protected override void OnModelCreating(ModelBuilder builder) { |
|
||||
base.OnModelCreating(builder); |
|
||||
|
|
||||
// Warning: optional foreign keys MUST NOT be added as CLR properties because
|
|
||||
// Entity Framework would throw an exception due to the TKey generic parameter
|
|
||||
// being non-nullable when using value types like short, int, long or Guid.
|
|
||||
|
|
||||
// Configure the TApplication entity.
|
|
||||
builder.Entity<TApplication>(entity => { |
|
||||
entity.HasKey(application => application.Id); |
|
||||
|
|
||||
entity.HasIndex(application => application.ClientId) |
|
||||
.IsUnique(unique: true); |
|
||||
|
|
||||
entity.HasMany(application => application.Tokens) |
|
||||
.WithOne() |
|
||||
.HasForeignKey("ApplicationId") |
|
||||
.IsRequired(required: false); |
|
||||
|
|
||||
entity.ToTable("OpenIddictApplications"); |
|
||||
}); |
|
||||
|
|
||||
// Configure the TAuthorization entity.
|
|
||||
builder.Entity<TAuthorization>(entity => { |
|
||||
entity.HasKey(authorization => authorization.Id); |
|
||||
|
|
||||
entity.HasMany(authorization => authorization.Tokens) |
|
||||
.WithOne() |
|
||||
.HasForeignKey("AuthorizationId") |
|
||||
.IsRequired(required: false); |
|
||||
|
|
||||
entity.ToTable("OpenIddictAuthorizations"); |
|
||||
}); |
|
||||
|
|
||||
// Configure the TScope entity.
|
|
||||
builder.Entity<TScope>(entity => { |
|
||||
entity.HasKey(scope => scope.Id); |
|
||||
|
|
||||
entity.ToTable("OpenIddictScopes"); |
|
||||
}); |
|
||||
|
|
||||
// Configure the TToken entity.
|
|
||||
builder.Entity<TToken>(entity => { |
|
||||
entity.HasKey(token => token.Id); |
|
||||
|
|
||||
entity.ToTable("OpenIddictTokens"); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,27 @@ |
|||||
|
/* |
||||
|
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
* See https://github.com/openiddict/openiddict-core for more information concerning
|
||||
|
* the license and the contributors participating to this project. |
||||
|
*/ |
||||
|
|
||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using OpenIddict.Models; |
||||
|
|
||||
|
namespace OpenIddict.EntityFramework { |
||||
|
public class OpenIddictExtension<TApplication, TAuthorization, TScope, TToken, TKey> : IDbContextOptionsExtension |
||||
|
where TApplication : OpenIddictApplication<TKey, TToken> |
||||
|
where TAuthorization : OpenIddictAuthorization<TKey, TToken> |
||||
|
where TScope : OpenIddictScope<TKey> |
||||
|
where TToken : OpenIddictToken<TKey> |
||||
|
where TKey : IEquatable<TKey> { |
||||
|
public void ApplyServices(IServiceCollection services) { |
||||
|
if (services == null) { |
||||
|
throw new ArgumentNullException(nameof(services)); |
||||
|
} |
||||
|
|
||||
|
services.AddSingleton<IModelCustomizer, OpenIddictCustomizer<TApplication, TAuthorization, TScope, TToken, TKey>>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<PropertyGroup> |
||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
||||
|
<PropertyGroup Label="Globals"> |
||||
|
<ProjectGuid>0102a6cc-41a6-4b34-b49e-65afe95882bb</ProjectGuid> |
||||
|
<RootNamespace>OpenIddict.Models</RootNamespace> |
||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
||||
|
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
||||
|
</Project> |
||||
@ -0,0 +1,43 @@ |
|||||
|
{ |
||||
|
"version": "1.0.0-beta2-*", |
||||
|
|
||||
|
"description": "Provides default entities for OpenIddict, that can be used by the EntityFramework stores.", |
||||
|
"authors": [ "Kévin Chalet" ], |
||||
|
|
||||
|
"packOptions": { |
||||
|
"owners": [ "Kévin Chalet" ], |
||||
|
|
||||
|
"projectUrl": "https://github.com/openiddict/openiddict-core", |
||||
|
"iconUrl": "https://avatars3.githubusercontent.com/u/13908567?s=64", |
||||
|
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html", |
||||
|
|
||||
|
"repository": { |
||||
|
"type": "git", |
||||
|
"url": "git://github.com/openiddict/openiddict-core" |
||||
|
}, |
||||
|
|
||||
|
"tags": [ |
||||
|
"aspnetcore", |
||||
|
"authentication", |
||||
|
"jwt", |
||||
|
"openidconnect", |
||||
|
"openiddict", |
||||
|
"security" |
||||
|
] |
||||
|
}, |
||||
|
|
||||
|
"buildOptions": { |
||||
|
"warningsAsErrors": true, |
||||
|
"nowarn": [ "CS1591" ], |
||||
|
"xmlDoc": true |
||||
|
}, |
||||
|
|
||||
|
"dependencies": { |
||||
|
"System.Collections": "4.0.11", |
||||
|
"System.Runtime": "4.1.0" |
||||
|
}, |
||||
|
|
||||
|
"frameworks": { |
||||
|
"netstandard1.0": { } |
||||
|
} |
||||
|
} |
||||
@ -1,238 +1,56 @@ |
|||||
using System; |
using System; |
||||
using AspNet.Security.OpenIdConnect.Primitives; |
|
||||
using Microsoft.AspNetCore.Builder; |
|
||||
using Microsoft.AspNetCore.Builder.Internal; |
|
||||
using Microsoft.AspNetCore.DataProtection; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.Options; |
using OpenIddict.Models; |
||||
using Moq; |
|
||||
using OpenIddict.Infrastructure; |
|
||||
using Xunit; |
using Xunit; |
||||
|
|
||||
namespace OpenIddict.Core.Tests { |
namespace OpenIddict.Core.Tests { |
||||
public class OpenIddictExtensionsTests { |
public class OpenIddictExtensionsTests { |
||||
[Fact] |
[Theory] |
||||
public void AddOpenIddict_RegistersProvider() { |
[InlineData(typeof(OpenIddictApplicationManager<OpenIddictApplication>))] |
||||
|
[InlineData(typeof(OpenIddictAuthorizationManager<OpenIddictAuthorization>))] |
||||
|
[InlineData(typeof(OpenIddictScopeManager<OpenIddictScope>))] |
||||
|
[InlineData(typeof(OpenIddictTokenManager<OpenIddictToken>))] |
||||
|
public void AddOpenIddict_KeyTypeDefaultsToString(Type type) { |
||||
// Arrange
|
// Arrange
|
||||
var services = new ServiceCollection(); |
var services = new ServiceCollection(); |
||||
|
|
||||
// Act
|
// Act
|
||||
services.AddOpenIddict<object, object, object, object>(); |
services.AddOpenIddict(); |
||||
|
|
||||
var provider = services.BuildServiceProvider(); |
|
||||
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
|
||||
|
|
||||
// Assert
|
// Assert
|
||||
Assert.IsType(typeof(OpenIddictProvider<object, object, object, object>), options.Value.Provider); |
Assert.Contains(services, service => service.ImplementationType == type); |
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[InlineData(typeof(IDataProtectionProvider))] |
[InlineData(typeof(OpenIddictApplicationManager<OpenIddictApplication<Guid, OpenIddictToken<Guid>>>))] |
||||
[InlineData(typeof(OpenIddictApplicationManager<object>))] |
[InlineData(typeof(OpenIddictAuthorizationManager<OpenIddictAuthorization<Guid, OpenIddictToken<Guid>>>))] |
||||
[InlineData(typeof(OpenIddictAuthorizationManager<object>))] |
[InlineData(typeof(OpenIddictScopeManager<OpenIddictScope<Guid>>))] |
||||
[InlineData(typeof(OpenIddictScopeManager<object>))] |
[InlineData(typeof(OpenIddictTokenManager<OpenIddictToken<Guid>>))] |
||||
[InlineData(typeof(OpenIddictTokenManager<object>))] |
public void AddOpenIddict_KeyTypeCanBeOverriden(Type type) { |
||||
[InlineData(typeof(OpenIddictServices<object, object, object, object>))] |
|
||||
public void AddOpenIddict_RegistersCoreServices(Type type) { |
|
||||
// Arrange
|
// Arrange
|
||||
var services = new ServiceCollection(); |
var services = new ServiceCollection(); |
||||
|
|
||||
// Act
|
// Act
|
||||
services.AddOpenIddict<object, object, object, object>(); |
services.AddOpenIddict<Guid>(); |
||||
|
|
||||
// Assert
|
// Assert
|
||||
Assert.Contains(services, service => service.ServiceType == type); |
Assert.Contains(services, service => service.ImplementationType == type); |
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void UseOpenIddict_AnExceptionIsThrownWhenNoDistributedCacheIsRegisteredIfRequestCachingIsEnabled() { |
|
||||
// Arrange
|
|
||||
var services = new ServiceCollection(); |
|
||||
|
|
||||
services.AddOpenIddict<object, object, object, object>() |
|
||||
.EnableRequestCaching(); |
|
||||
|
|
||||
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
|
||||
|
|
||||
// Act and assert
|
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
|
||||
|
|
||||
Assert.Equal("A distributed cache implementation must be registered in the OpenIddict options " + |
|
||||
"or in the dependency injection container when enabling request caching support.", exception.Message); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void UseOpenIddict_AnExceptionIsThrownWhenNoSigningCredentialsIsRegistered() { |
|
||||
// Arrange
|
|
||||
var services = new ServiceCollection(); |
|
||||
services.AddOpenIddict<object, object, object, object>(); |
|
||||
|
|
||||
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
|
||||
|
|
||||
// Act and assert
|
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
|
||||
|
|
||||
Assert.Equal("At least one signing key must be registered. Consider registering a X.509 " + |
|
||||
"certificate using 'services.AddOpenIddict().AddSigningCertificate()' or call " + |
|
||||
"'services.AddOpenIddict().AddEphemeralSigningKey()' to use an ephemeral key.", exception.Message); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void UseOpenIddict_AnExceptionIsThrownWhenNoFlowIsEnabled() { |
|
||||
// Arrange
|
|
||||
var services = new ServiceCollection(); |
|
||||
|
|
||||
services.AddOpenIddict<object, object, object, object>() |
|
||||
.AddEphemeralSigningKey(); |
|
||||
|
|
||||
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
|
||||
|
|
||||
// Act and assert
|
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
|
||||
|
|
||||
Assert.Equal("At least one OAuth2/OpenID Connect flow must be enabled.", exception.Message); |
|
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[InlineData(OpenIdConnectConstants.GrantTypes.AuthorizationCode)] |
[InlineData(typeof(OpenIddictApplicationManager<object>))] |
||||
[InlineData(OpenIdConnectConstants.GrantTypes.Implicit)] |
[InlineData(typeof(OpenIddictAuthorizationManager<object>))] |
||||
public void UseOpenIddict_AnExceptionIsThrownWhenAuthorizationEndpointIsDisabled(string flow) { |
[InlineData(typeof(OpenIddictScopeManager<object>))] |
||||
// Arrange
|
[InlineData(typeof(OpenIddictTokenManager<object>))] |
||||
var services = new ServiceCollection(); |
public void AddOpenIddict_DefaultEntitiesCanBeReplaced(Type type) { |
||||
|
|
||||
services.AddOpenIddict<object, object, object, object>() |
|
||||
.AddEphemeralSigningKey() |
|
||||
.Configure(options => options.GrantTypes.Add(flow)) |
|
||||
.Configure(options => options.AuthorizationEndpointPath = PathString.Empty); |
|
||||
|
|
||||
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
|
||||
|
|
||||
// Act and assert
|
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
|
||||
|
|
||||
Assert.Equal("The authorization endpoint must be enabled to use " + |
|
||||
"the authorization code and implicit flows.", exception.Message); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(OpenIdConnectConstants.GrantTypes.AuthorizationCode)] |
|
||||
[InlineData(OpenIdConnectConstants.GrantTypes.ClientCredentials)] |
|
||||
[InlineData(OpenIdConnectConstants.GrantTypes.Password)] |
|
||||
[InlineData(OpenIdConnectConstants.GrantTypes.RefreshToken)] |
|
||||
public void UseOpenIddict_AnExceptionIsThrownWhenTokenEndpointIsDisabled(string flow) { |
|
||||
// Arrange
|
|
||||
var services = new ServiceCollection(); |
|
||||
|
|
||||
services.AddOpenIddict<object, object, object, object>() |
|
||||
.AddEphemeralSigningKey() |
|
||||
.EnableAuthorizationEndpoint("/connect/authorize") |
|
||||
.Configure(options => options.GrantTypes.Add(flow)) |
|
||||
.Configure(options => options.TokenEndpointPath = PathString.Empty); |
|
||||
|
|
||||
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
|
||||
|
|
||||
// Act and assert
|
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
|
||||
|
|
||||
Assert.Equal("The token endpoint must be enabled to use the authorization code, " + |
|
||||
"client credentials, password and refresh token flows.", exception.Message); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void UseOpenIddict_OpenIdConnectServerMiddlewareIsRegistered() { |
|
||||
// Arrange
|
// Arrange
|
||||
var services = new ServiceCollection(); |
var services = new ServiceCollection(); |
||||
|
|
||||
services.AddOpenIddict<object, object, object, object>() |
|
||||
.AddEphemeralSigningKey() |
|
||||
.AllowImplicitFlow() |
|
||||
.EnableAuthorizationEndpoint("/connect/authorize"); |
|
||||
|
|
||||
var builder = new Mock<IApplicationBuilder>(); |
|
||||
builder.SetupGet(mock => mock.ApplicationServices) |
|
||||
.Returns(services.BuildServiceProvider()); |
|
||||
|
|
||||
// Act
|
// Act
|
||||
builder.Object.UseOpenIddict(); |
services.AddOpenIddict<object, object, object, object>(); |
||||
|
|
||||
// Assert
|
// Assert
|
||||
builder.Verify(mock => mock.Use(It.IsAny<Func<RequestDelegate, RequestDelegate>>()), Times.Once()); |
Assert.Contains(services, service => service.ServiceType == type); |
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(true)] |
|
||||
[InlineData(false)] |
|
||||
public void IsAuthorizationCodeFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
|
||||
// Arrange
|
|
||||
var options = new OpenIddictOptions(); |
|
||||
|
|
||||
if (enabled) { |
|
||||
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.AuthorizationCode); |
|
||||
} |
|
||||
|
|
||||
// Act and assert
|
|
||||
Assert.Equal(enabled, options.IsAuthorizationCodeFlowEnabled()); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(true)] |
|
||||
[InlineData(false)] |
|
||||
public void IsClientCredentialsFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
|
||||
// Arrange
|
|
||||
var options = new OpenIddictOptions(); |
|
||||
|
|
||||
if (enabled) { |
|
||||
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.ClientCredentials); |
|
||||
} |
|
||||
|
|
||||
// Act and assert
|
|
||||
Assert.Equal(enabled, options.IsClientCredentialsFlowEnabled()); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(true)] |
|
||||
[InlineData(false)] |
|
||||
public void IsImplicitFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
|
||||
// Arrange
|
|
||||
var options = new OpenIddictOptions(); |
|
||||
|
|
||||
if (enabled) { |
|
||||
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.Implicit); |
|
||||
} |
|
||||
|
|
||||
// Act and assert
|
|
||||
Assert.Equal(enabled, options.IsImplicitFlowEnabled()); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(true)] |
|
||||
[InlineData(false)] |
|
||||
public void IsPasswordFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
|
||||
// Arrange
|
|
||||
var options = new OpenIddictOptions(); |
|
||||
|
|
||||
if (enabled) { |
|
||||
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.Password); |
|
||||
} |
|
||||
|
|
||||
// Act and assert
|
|
||||
Assert.Equal(enabled, options.IsPasswordFlowEnabled()); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(true)] |
|
||||
[InlineData(false)] |
|
||||
public void IsRefreshTokenFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
|
||||
// Arrange
|
|
||||
var options = new OpenIddictOptions(); |
|
||||
|
|
||||
if (enabled) { |
|
||||
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.RefreshToken); |
|
||||
} |
|
||||
|
|
||||
// Act and assert
|
|
||||
Assert.Equal(enabled, options.IsRefreshTokenFlowEnabled()); |
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,526 @@ |
|||||
|
using System; |
||||
|
using System.IdentityModel.Tokens.Jwt; |
||||
|
using System.Reflection; |
||||
|
using AspNet.Security.OpenIdConnect.Primitives; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.DataProtection; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.IdentityModel.Tokens; |
||||
|
using Moq; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace OpenIddict.Tests { |
||||
|
public class OpenIddictBuilderTests { |
||||
|
[Fact] |
||||
|
public void Configure_OptionsAreCorrectlyAmended() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.Configure(configuration => configuration.Description.DisplayName = "OpenIddict"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("OpenIddict", options.Value.Description.DisplayName); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AddEphemeralSigningKey_SigningKeyIsCorrectlyAdded() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AddEphemeralSigningKey(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(1, options.Value.SigningCredentials.Count); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(SecurityAlgorithms.RsaSha256Signature)] |
||||
|
[InlineData(SecurityAlgorithms.RsaSha384Signature)] |
||||
|
[InlineData(SecurityAlgorithms.RsaSha512Signature)] |
||||
|
#if SUPPORTS_ECDSA
|
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha256Signature)] |
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha384Signature)] |
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha512Signature)] |
||||
|
#endif
|
||||
|
public void AddEphemeralSigningKey_SigningCredentialsUseSpecifiedAlgorithm(string algorithm) { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AddEphemeralSigningKey(algorithm); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
var credentials = options.Value.SigningCredentials[0]; |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(algorithm, credentials.Algorithm); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(SecurityAlgorithms.HmacSha256Signature)] |
||||
|
[InlineData(SecurityAlgorithms.RsaSha256Signature)] |
||||
|
#if SUPPORTS_ECDSA
|
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha256Signature)] |
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha384Signature)] |
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha512Signature)] |
||||
|
#endif
|
||||
|
public void AddSigningKey_SigningKeyIsCorrectlyAdded(string algorithm) { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
var factory = Mock.Of<CryptoProviderFactory>(mock => |
||||
|
mock.IsSupportedAlgorithm(algorithm, It.IsAny<SecurityKey>())); |
||||
|
|
||||
|
var key = Mock.Of<SecurityKey>(mock => mock.CryptoProviderFactory == factory); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AddSigningKey(key); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Same(key, options.Value.SigningCredentials[0].Key); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AddSigningCertificate_SigningKeyIsCorrectlyAdded() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AddSigningCertificate( |
||||
|
assembly: typeof(OpenIddictBuilderTests).GetTypeInfo().Assembly, |
||||
|
resource: "OpenIddict.Tests.Certificate.pfx", |
||||
|
password: "OpenIddict"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.IsType(typeof(X509SecurityKey), options.Value.SigningCredentials[0].Key); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowAuthorizationCodeFlow_CodeFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowAuthorizationCodeFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowClientCredentialsFlow_ClientCredentialsFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowClientCredentialsFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.ClientCredentials, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowCustomFlow_CustomFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowCustomFlow("urn:ietf:params:oauth:grant-type:custom_grant"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains("urn:ietf:params:oauth:grant-type:custom_grant", options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowImplicitFlow_ImplicitFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowImplicitFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.Implicit, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowPasswordFlow_PasswordFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowPasswordFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.Password, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowRefreshTokenFlow_RefreshTokenFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowRefreshTokenFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.RefreshToken, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void DisableConfigurationEndpoint_ConfigurationEndpointIsDisabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.DisableConfigurationEndpoint(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(PathString.Empty, options.Value.ConfigurationEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void DisableCryptographyEndpoint_CryptographyEndpointIsDisabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.DisableCryptographyEndpoint(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(PathString.Empty, options.Value.CryptographyEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableAuthorizationEndpoint_AuthorizationEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableAuthorizationEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.AuthorizationEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableIntrospectionEndpoint_IntrospectionEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableIntrospectionEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.IntrospectionEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableLogoutEndpoint_LogoutEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableLogoutEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.LogoutEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableRequestCaching_RequestCachingIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableRequestCaching(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.True(options.Value.EnableRequestCaching); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableRevocationEndpoint_RevocationEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableRevocationEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.RevocationEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableTokenEndpoint_TokenEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableTokenEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.TokenEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableUserinfoEndpoint_UserinfoEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableUserinfoEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.UserinfoEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void RequireClientIdentification_ClientIdentificationIsEnforced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.RequireClientIdentification(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.True(options.Value.RequireClientIdentification); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetAccessTokenLifetime_DefaultAccessTokenLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetAccessTokenLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.AccessTokenLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetAuthorizationCodeLifetime_DefaultAuthorizationCodeLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.AuthorizationCodeLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetIdentityTokenLifetime_DefaultIdentityTokenLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetIdentityTokenLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.IdentityTokenLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetRefreshTokenLifetime_DefaultRefreshTokenLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetRefreshTokenLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.RefreshTokenLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseDataProtectionProvider_DefaultProviderIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.UseDataProtectionProvider(new EphemeralDataProtectionProvider()); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.IsType(typeof(EphemeralDataProtectionProvider), options.Value.DataProtectionProvider); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseJsonWebTokens_AccessTokenHandlerIsCorrectlySet() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.UseJsonWebTokens(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.IsType(typeof(JwtSecurityTokenHandler), options.Value.AccessTokenHandler); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,60 +1,731 @@ |
|||||
using System; |
using System; |
||||
|
using System.IdentityModel.Tokens.Jwt; |
||||
|
using System.Reflection; |
||||
|
using AspNet.Security.OpenIdConnect.Primitives; |
||||
using Microsoft.AspNetCore.Builder; |
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.Builder.Internal; |
||||
|
using Microsoft.AspNetCore.DataProtection; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
using Microsoft.Extensions.DependencyInjection; |
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.IdentityModel.Tokens; |
||||
|
using Moq; |
||||
using Xunit; |
using Xunit; |
||||
|
|
||||
namespace OpenIddict.Tests { |
namespace OpenIddict.Tests { |
||||
public class OpenIddictExtensionsTests { |
public class OpenIddictExtensionsTests { |
||||
|
[Fact] |
||||
|
public void UseOpenIddict_AnExceptionIsThrownWhenServicesAreNotRegistered() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
|
||||
|
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act and assert
|
||||
|
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
||||
|
|
||||
|
Assert.Equal("The OpenIddict services cannot be resolved from the dependency injection container. " + |
||||
|
"Make sure 'services.AddOpenIddict()' is correctly called from 'ConfigureServices()'.", exception.Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseOpenIddict_AnExceptionIsThrownWhenNoDistributedCacheIsRegisteredIfRequestCachingIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
|
||||
|
services.AddOpenIddict() |
||||
|
.EnableRequestCaching(); |
||||
|
|
||||
|
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act and assert
|
||||
|
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
||||
|
|
||||
|
Assert.Equal("A distributed cache implementation must be registered in the OpenIddict options " + |
||||
|
"or in the dependency injection container when enabling request caching support.", exception.Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseOpenIddict_AnExceptionIsThrownWhenNoSigningCredentialsIsRegistered() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOpenIddict(); |
||||
|
|
||||
|
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act and assert
|
||||
|
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
||||
|
|
||||
|
Assert.Equal("At least one signing key must be registered. Consider registering a X.509 " + |
||||
|
"certificate using 'services.AddOpenIddict().AddSigningCertificate()' or call " + |
||||
|
"'services.AddOpenIddict().AddEphemeralSigningKey()' to use an ephemeral key.", exception.Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseOpenIddict_AnExceptionIsThrownWhenNoFlowIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
|
||||
|
services.AddOpenIddict() |
||||
|
.AddEphemeralSigningKey(); |
||||
|
|
||||
|
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act and assert
|
||||
|
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
||||
|
|
||||
|
Assert.Equal("At least one OAuth2/OpenID Connect flow must be enabled.", exception.Message); |
||||
|
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[InlineData(typeof(OpenIddictApplicationManager<OpenIddictApplication<Guid>>))] |
[InlineData(OpenIdConnectConstants.GrantTypes.AuthorizationCode)] |
||||
[InlineData(typeof(OpenIddictAuthorizationManager<OpenIddictAuthorization<Guid>>))] |
[InlineData(OpenIdConnectConstants.GrantTypes.Implicit)] |
||||
[InlineData(typeof(OpenIddictScopeManager<OpenIddictScope<Guid>>))] |
public void UseOpenIddict_AnExceptionIsThrownWhenAuthorizationEndpointIsDisabled(string flow) { |
||||
[InlineData(typeof(OpenIddictTokenManager<OpenIddictToken<Guid>>))] |
// Arrange
|
||||
public void AddOpenIddict_RegistersCoreManagers(Type type) { |
var services = new ServiceCollection(); |
||||
|
|
||||
|
services.AddOpenIddict() |
||||
|
.AddEphemeralSigningKey() |
||||
|
.Configure(options => options.GrantTypes.Add(flow)) |
||||
|
.Configure(options => options.AuthorizationEndpointPath = PathString.Empty); |
||||
|
|
||||
|
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act and assert
|
||||
|
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
||||
|
|
||||
|
Assert.Equal("The authorization endpoint must be enabled to use " + |
||||
|
"the authorization code and implicit flows.", exception.Message); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(OpenIdConnectConstants.GrantTypes.AuthorizationCode)] |
||||
|
[InlineData(OpenIdConnectConstants.GrantTypes.ClientCredentials)] |
||||
|
[InlineData(OpenIdConnectConstants.GrantTypes.Password)] |
||||
|
[InlineData(OpenIdConnectConstants.GrantTypes.RefreshToken)] |
||||
|
public void UseOpenIddict_AnExceptionIsThrownWhenTokenEndpointIsDisabled(string flow) { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
|
||||
|
services.AddOpenIddict() |
||||
|
.AddEphemeralSigningKey() |
||||
|
.EnableAuthorizationEndpoint("/connect/authorize") |
||||
|
.Configure(options => options.GrantTypes.Add(flow)) |
||||
|
.Configure(options => options.TokenEndpointPath = PathString.Empty); |
||||
|
|
||||
|
var builder = new ApplicationBuilder(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act and assert
|
||||
|
var exception = Assert.Throws<InvalidOperationException>(() => builder.UseOpenIddict()); |
||||
|
|
||||
|
Assert.Equal("The token endpoint must be enabled to use the authorization code, " + |
||||
|
"client credentials, password and refresh token flows.", exception.Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Configure_OptionsAreCorrectlyAmended() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.Configure(configuration => configuration.Description.DisplayName = "OpenIddict"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("OpenIddict", options.Value.Description.DisplayName); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseOpenIddict_OpenIdConnectServerMiddlewareIsRegistered() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
|
||||
|
services.AddOpenIddict() |
||||
|
.AddEphemeralSigningKey() |
||||
|
.AllowImplicitFlow() |
||||
|
.EnableAuthorizationEndpoint("/connect/authorize"); |
||||
|
|
||||
|
var builder = new Mock<IApplicationBuilder>(); |
||||
|
builder.SetupGet(mock => mock.ApplicationServices) |
||||
|
.Returns(services.BuildServiceProvider()); |
||||
|
|
||||
|
// Act
|
||||
|
builder.Object.UseOpenIddict(); |
||||
|
|
||||
|
// Assert
|
||||
|
builder.Verify(mock => mock.Use(It.IsAny<Func<RequestDelegate, RequestDelegate>>()), Times.Once()); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AddEphemeralSigningKey_SigningKeyIsCorrectlyAdded() { |
||||
// Arrange
|
// Arrange
|
||||
var services = new ServiceCollection(); |
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
// Act
|
// Act
|
||||
services.AddOpenIddict<OpenIddictDbContext, Guid>(); |
builder.AddEphemeralSigningKey(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
// Assert
|
// Assert
|
||||
Assert.Contains(services, service => service.ImplementationType == type); |
Assert.Equal(1, options.Value.SigningCredentials.Count); |
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[InlineData(typeof(OpenIddictApplicationStore<OpenIddictApplication<Guid>, OpenIddictToken<Guid>, OpenIddictDbContext, Guid>))] |
[InlineData(SecurityAlgorithms.RsaSha256Signature)] |
||||
[InlineData(typeof(OpenIddictAuthorizationStore<OpenIddictAuthorization<Guid>, OpenIddictToken<Guid>, OpenIddictDbContext, Guid>))] |
[InlineData(SecurityAlgorithms.RsaSha384Signature)] |
||||
[InlineData(typeof(OpenIddictScopeStore<OpenIddictScope<Guid>, OpenIddictDbContext, Guid>))] |
[InlineData(SecurityAlgorithms.RsaSha512Signature)] |
||||
[InlineData(typeof(OpenIddictTokenStore<OpenIddictToken<Guid>, OpenIddictAuthorization<Guid>, OpenIddictDbContext, Guid>))] |
#if SUPPORTS_ECDSA
|
||||
public void AddOpenIddict_RegistersEntityFrameworkStores(Type type) { |
[InlineData(SecurityAlgorithms.EcdsaSha256Signature)] |
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha384Signature)] |
||||
|
[InlineData(SecurityAlgorithms.EcdsaSha512Signature)] |
||||
|
#endif
|
||||
|
public void AddEphemeralSigningKey_SigningCredentialsUseSpecifiedAlgorithm(string algorithm) { |
||||
// Arrange
|
// Arrange
|
||||
var services = new ServiceCollection(); |
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
// Act
|
// Act
|
||||
services.AddOpenIddict<OpenIddictDbContext, Guid>(); |
builder.AddEphemeralSigningKey(algorithm); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
var credentials = options.Value.SigningCredentials[0]; |
||||
|
|
||||
// Assert
|
// Assert
|
||||
Assert.Contains(services, service => service.ImplementationType == type); |
Assert.Equal(algorithm, credentials.Algorithm); |
||||
} |
} |
||||
|
|
||||
[Theory] |
[Theory] |
||||
[InlineData(typeof(OpenIddictApplicationManager<OpenIddictApplication>))] |
[InlineData(SecurityAlgorithms.HmacSha256Signature)] |
||||
[InlineData(typeof(OpenIddictAuthorizationManager<OpenIddictAuthorization>))] |
[InlineData(SecurityAlgorithms.RsaSha256Signature)] |
||||
[InlineData(typeof(OpenIddictScopeManager<OpenIddictScope>))] |
#if SUPPORTS_ECDSA
|
||||
[InlineData(typeof(OpenIddictTokenManager<OpenIddictToken>))] |
[InlineData(SecurityAlgorithms.EcdsaSha256Signature)] |
||||
[InlineData(typeof(OpenIddictApplicationStore<OpenIddictApplication, OpenIddictToken, OpenIddictDbContext, string>))] |
[InlineData(SecurityAlgorithms.EcdsaSha384Signature)] |
||||
[InlineData(typeof(OpenIddictAuthorizationStore<OpenIddictAuthorization, OpenIddictToken, OpenIddictDbContext, string>))] |
[InlineData(SecurityAlgorithms.EcdsaSha512Signature)] |
||||
[InlineData(typeof(OpenIddictScopeStore<OpenIddictScope, OpenIddictDbContext, string>))] |
#endif
|
||||
[InlineData(typeof(OpenIddictTokenStore<OpenIddictToken, OpenIddictAuthorization, OpenIddictDbContext, string>))] |
public void AddSigningKey_SigningKeyIsCorrectlyAdded(string algorithm) { |
||||
public void AddOpenIddict_KeyTypeDefaultsToString(Type type) { |
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
var factory = Mock.Of<CryptoProviderFactory>(mock => |
||||
|
mock.IsSupportedAlgorithm(algorithm, It.IsAny<SecurityKey>())); |
||||
|
|
||||
|
var key = Mock.Of<SecurityKey>(mock => mock.CryptoProviderFactory == factory); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AddSigningKey(key); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Same(key, options.Value.SigningCredentials[0].Key); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AddSigningCertificate_SigningKeyIsCorrectlyAdded() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AddSigningCertificate( |
||||
|
assembly: typeof(OpenIddictBuilderTests).GetTypeInfo().Assembly, |
||||
|
resource: "OpenIddict.Tests.Certificate.pfx", |
||||
|
password: "OpenIddict"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.IsType(typeof(X509SecurityKey), options.Value.SigningCredentials[0].Key); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowAuthorizationCodeFlow_CodeFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowAuthorizationCodeFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowClientCredentialsFlow_ClientCredentialsFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowClientCredentialsFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.ClientCredentials, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowCustomFlow_CustomFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowCustomFlow("urn:ietf:params:oauth:grant-type:custom_grant"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains("urn:ietf:params:oauth:grant-type:custom_grant", options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowImplicitFlow_ImplicitFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowImplicitFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.Implicit, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowPasswordFlow_PasswordFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowPasswordFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.Password, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void AllowRefreshTokenFlow_RefreshTokenFlowIsAddedToGrantTypes() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.AllowRefreshTokenFlow(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Contains(OpenIdConnectConstants.GrantTypes.RefreshToken, options.Value.GrantTypes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void DisableConfigurationEndpoint_ConfigurationEndpointIsDisabled() { |
||||
// Arrange
|
// Arrange
|
||||
var services = new ServiceCollection(); |
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
// Act
|
// Act
|
||||
services.AddOpenIddict<OpenIddictDbContext>(); |
builder.DisableConfigurationEndpoint(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
// Assert
|
// Assert
|
||||
Assert.Contains(services, service => service.ImplementationType == type); |
Assert.Equal(PathString.Empty, options.Value.ConfigurationEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void DisableCryptographyEndpoint_CryptographyEndpointIsDisabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.DisableCryptographyEndpoint(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(PathString.Empty, options.Value.CryptographyEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableAuthorizationEndpoint_AuthorizationEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableAuthorizationEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.AuthorizationEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableIntrospectionEndpoint_IntrospectionEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableIntrospectionEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.IntrospectionEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableLogoutEndpoint_LogoutEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableLogoutEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.LogoutEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableRequestCaching_RequestCachingIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableRequestCaching(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.True(options.Value.EnableRequestCaching); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableRevocationEndpoint_RevocationEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableRevocationEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.RevocationEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableTokenEndpoint_TokenEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableTokenEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.TokenEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void EnableUserinfoEndpoint_UserinfoEndpointIsEnabled() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.EnableUserinfoEndpoint("/endpoint-path"); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal("/endpoint-path", options.Value.UserinfoEndpointPath); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void RequireClientIdentification_ClientIdentificationIsEnforced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.RequireClientIdentification(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.True(options.Value.RequireClientIdentification); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetAccessTokenLifetime_DefaultAccessTokenLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetAccessTokenLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.AccessTokenLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetAuthorizationCodeLifetime_DefaultAuthorizationCodeLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.AuthorizationCodeLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetIdentityTokenLifetime_DefaultIdentityTokenLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetIdentityTokenLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.IdentityTokenLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SetRefreshTokenLifetime_DefaultRefreshTokenLifetimeIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.SetRefreshTokenLifetime(TimeSpan.FromMinutes(42)); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.Equal(TimeSpan.FromMinutes(42), options.Value.RefreshTokenLifetime); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseDataProtectionProvider_DefaultProviderIsReplaced() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.UseDataProtectionProvider(new EphemeralDataProtectionProvider()); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.IsType(typeof(EphemeralDataProtectionProvider), options.Value.DataProtectionProvider); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void UseJsonWebTokens_AccessTokenHandlerIsCorrectlySet() { |
||||
|
// Arrange
|
||||
|
var services = new ServiceCollection(); |
||||
|
services.AddOptions(); |
||||
|
|
||||
|
var builder = new OpenIddictBuilder(services); |
||||
|
|
||||
|
// Act
|
||||
|
builder.UseJsonWebTokens(); |
||||
|
|
||||
|
var provider = services.BuildServiceProvider(); |
||||
|
var options = provider.GetRequiredService<IOptions<OpenIddictOptions>>(); |
||||
|
|
||||
|
// Assert
|
||||
|
Assert.IsType(typeof(JwtSecurityTokenHandler), options.Value.AccessTokenHandler); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(true)] |
||||
|
[InlineData(false)] |
||||
|
public void IsAuthorizationCodeFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
||||
|
// Arrange
|
||||
|
var options = new OpenIddictOptions(); |
||||
|
|
||||
|
if (enabled) { |
||||
|
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.AuthorizationCode); |
||||
|
} |
||||
|
|
||||
|
// Act and assert
|
||||
|
Assert.Equal(enabled, options.IsAuthorizationCodeFlowEnabled()); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(true)] |
||||
|
[InlineData(false)] |
||||
|
public void IsClientCredentialsFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
||||
|
// Arrange
|
||||
|
var options = new OpenIddictOptions(); |
||||
|
|
||||
|
if (enabled) { |
||||
|
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.ClientCredentials); |
||||
|
} |
||||
|
|
||||
|
// Act and assert
|
||||
|
Assert.Equal(enabled, options.IsClientCredentialsFlowEnabled()); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(true)] |
||||
|
[InlineData(false)] |
||||
|
public void IsImplicitFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
||||
|
// Arrange
|
||||
|
var options = new OpenIddictOptions(); |
||||
|
|
||||
|
if (enabled) { |
||||
|
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.Implicit); |
||||
|
} |
||||
|
|
||||
|
// Act and assert
|
||||
|
Assert.Equal(enabled, options.IsImplicitFlowEnabled()); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(true)] |
||||
|
[InlineData(false)] |
||||
|
public void IsPasswordFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
||||
|
// Arrange
|
||||
|
var options = new OpenIddictOptions(); |
||||
|
|
||||
|
if (enabled) { |
||||
|
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.Password); |
||||
|
} |
||||
|
|
||||
|
// Act and assert
|
||||
|
Assert.Equal(enabled, options.IsPasswordFlowEnabled()); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(true)] |
||||
|
[InlineData(false)] |
||||
|
public void IsRefreshTokenFlowEnabled_ReturnsAppropriateResult(bool enabled) { |
||||
|
// Arrange
|
||||
|
var options = new OpenIddictOptions(); |
||||
|
|
||||
|
if (enabled) { |
||||
|
options.GrantTypes.Add(OpenIdConnectConstants.GrantTypes.RefreshToken); |
||||
|
} |
||||
|
|
||||
|
// Act and assert
|
||||
|
Assert.Equal(enabled, options.IsRefreshTokenFlowEnabled()); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue