@ -0,0 +1,96 @@ | |||
namespace DataProtectionExtensions | |||
{ | |||
using System; | |||
using System.Linq; | |||
using System.Security.Cryptography.X509Certificates; | |||
using Microsoft.AspNetCore.DataProtection; | |||
using Microsoft.AspNetCore.DataProtection.Repositories; | |||
using Microsoft.AspNetCore.DataProtection.XmlEncryption; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Logging; | |||
using System.Net; | |||
/// <summary> | |||
/// Extension methods for <see cref="IDataProtectionBuilder"/> for configuring | |||
/// data protection options. | |||
/// </summary> | |||
public static class DataProtectionBuilderExtensions | |||
{ | |||
/// <summary> | |||
/// Sets up data protection to persist session keys in Redis. | |||
/// </summary> | |||
/// <param name="builder">The <see cref="IDataProtectionBuilder"/> used to set up data protection options.</param> | |||
/// <param name="redisConnectionString">The connection string specifying the Redis instance and database for key storage.</param> | |||
/// <returns> | |||
/// The <paramref name="builder" /> for continued configuration. | |||
/// </returns> | |||
/// <exception cref="System.ArgumentNullException"> | |||
/// Thrown if <paramref name="builder" /> or <paramref name="redisConnectionString" /> is <see langword="null" />. | |||
/// </exception> | |||
/// <exception cref="System.ArgumentException"> | |||
/// Thrown if <paramref name="redisConnectionString" /> is empty. | |||
/// </exception> | |||
public static IDataProtectionBuilder PersistKeysToRedis(this IDataProtectionBuilder builder, string redisConnectionString) | |||
{ | |||
if (builder == null) | |||
{ | |||
throw new ArgumentNullException(nameof(builder)); | |||
} | |||
if (redisConnectionString == null) | |||
{ | |||
throw new ArgumentNullException(nameof(redisConnectionString)); | |||
} | |||
if (redisConnectionString.Length == 0) | |||
{ | |||
throw new ArgumentException("Redis connection string may not be empty.", nameof(redisConnectionString)); | |||
} | |||
var ips = Dns.GetHostAddressesAsync(redisConnectionString).Result; | |||
return builder.Use(ServiceDescriptor.Singleton<IXmlRepository>(services => new RedisXmlRepository(ips.First().ToString(), services.GetRequiredService<ILogger<RedisXmlRepository>>()))); | |||
} | |||
/// <summary> | |||
/// Updates an <see cref="IDataProtectionBuilder"/> to use the service of | |||
/// a specific type, removing all other services of that type. | |||
/// </summary> | |||
/// <param name="builder">The <see cref="IDataProtectionBuilder"/> that should use the specified service.</param> | |||
/// <param name="descriptor">The <see cref="ServiceDescriptor"/> with the service the <paramref name="builder" /> should use.</param> | |||
/// <returns> | |||
/// The <paramref name="builder" /> for continued configuration. | |||
/// </returns> | |||
/// <exception cref="System.ArgumentNullException"> | |||
/// Thrown if <paramref name="builder" /> or <paramref name="descriptor" /> is <see langword="null" />. | |||
/// </exception> | |||
public static IDataProtectionBuilder Use(this IDataProtectionBuilder builder, ServiceDescriptor descriptor) | |||
{ | |||
// This algorithm of removing all other services of a specific type | |||
// before adding the new/replacement service is how the base ASP.NET | |||
// DataProtection bits work. Due to some of the differences in how | |||
// that base set of bits handles DI, it's better to follow suit | |||
// and work in the same way than to try and debug weird issues. | |||
if (builder == null) | |||
{ | |||
throw new ArgumentNullException(nameof(builder)); | |||
} | |||
if (descriptor == null) | |||
{ | |||
throw new ArgumentNullException(nameof(descriptor)); | |||
} | |||
for (int i = builder.Services.Count - 1; i >= 0; i--) | |||
{ | |||
if (builder.Services[i]?.ServiceType == descriptor.ServiceType) | |||
{ | |||
builder.Services.RemoveAt(i); | |||
} | |||
} | |||
builder.Services.Add(descriptor); | |||
return builder; | |||
} | |||
} | |||
} |
@ -0,0 +1,214 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics.CodeAnalysis; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Text.RegularExpressions; | |||
using System.Xml.Linq; | |||
using Microsoft.AspNetCore.DataProtection.Repositories; | |||
using Microsoft.Extensions.Logging; | |||
using StackExchange.Redis; | |||
namespace DataProtectionExtensions | |||
{ | |||
/// <summary> | |||
/// Key repository that stores XML encrypted keys in a Redis distributed cache. | |||
/// </summary> | |||
/// <remarks> | |||
/// <para> | |||
/// The values stored in Redis are XML documents that contain encrypted session | |||
/// keys used for the protection of things like session state. The document contents | |||
/// are double-encrypted - first with a changing session key; then by a master key. | |||
/// As such, there's no risk in storing the keys in Redis - even if someone can crack | |||
/// the master key, they still need to also crack the session key. (Other solutions | |||
/// for sharing keys across a farm environment include writing them to files | |||
/// on a file share.) | |||
/// </para> | |||
/// <para> | |||
/// While the repository uses a hash to keep the set of encrypted keys separate, you | |||
/// can further separate these items from other items in Redis by specifying a unique | |||
/// database in the connection string. | |||
/// </para> | |||
/// <para> | |||
/// Consumers of the repository are responsible for caching the XML items as needed. | |||
/// Typically repositories are consumed by things like <see cref="Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider"/> | |||
/// which generates <see cref="Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing"/> | |||
/// values that get cached. The mechanism is already optimized for caching so there's | |||
/// no need to create a redundant cache. | |||
/// </para> | |||
/// </remarks> | |||
/// <seealso cref="Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository" /> | |||
/// <seealso cref="System.IDisposable" /> | |||
public class RedisXmlRepository : IXmlRepository, IDisposable | |||
{ | |||
/// <summary> | |||
/// The root cache key for XML items stored in Redis | |||
/// </summary> | |||
public static readonly string RedisHashKey = "DataProtectionXmlRepository"; | |||
/// <summary> | |||
/// The connection to the Redis backing store. | |||
/// </summary> | |||
private IConnectionMultiplexer _connection; | |||
/// <summary> | |||
/// Flag indicating whether the object has been disposed. | |||
/// </summary> | |||
private bool _disposed = false; | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="RedisXmlRepository"/> class. | |||
/// </summary> | |||
/// <param name="connectionString"> | |||
/// The Redis connection string. | |||
/// </param> | |||
/// <param name="logger"> | |||
/// The <see cref="ILogger{T}"/> used to log diagnostic messages. | |||
/// </param> | |||
/// <exception cref="System.ArgumentNullException"> | |||
/// Thrown if <paramref name="connectionString" /> or <paramref name="logger" /> is <see langword="null" />. | |||
/// </exception> | |||
public RedisXmlRepository(string connectionString, ILogger<RedisXmlRepository> logger) | |||
: this(ConnectionMultiplexer.Connect(connectionString), logger) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="RedisXmlRepository"/> class. | |||
/// </summary> | |||
/// <param name="connection"> | |||
/// The Redis database connection. | |||
/// </param> | |||
/// <param name="logger"> | |||
/// The <see cref="ILogger{T}"/> used to log diagnostic messages. | |||
/// </param> | |||
/// <exception cref="System.ArgumentNullException"> | |||
/// Thrown if <paramref name="connection" /> or <paramref name="logger" /> is <see langword="null" />. | |||
/// </exception> | |||
public RedisXmlRepository(IConnectionMultiplexer connection, ILogger<RedisXmlRepository> logger) | |||
{ | |||
if (connection == null) | |||
{ | |||
throw new ArgumentNullException(nameof(connection)); | |||
} | |||
if (logger == null) | |||
{ | |||
throw new ArgumentNullException(nameof(logger)); | |||
} | |||
this._connection = connection; | |||
this.Logger = logger; | |||
// Mask the password so it doesn't get logged. | |||
var configuration = Regex.Replace(this._connection.Configuration, @"password\s*=\s*[^,]*", "password=****", RegexOptions.IgnoreCase); | |||
this.Logger.LogDebug("Storing data protection keys in Redis: {RedisConfiguration}", configuration); | |||
} | |||
/// <summary> | |||
/// Gets the logger. | |||
/// </summary> | |||
/// <value> | |||
/// The <see cref="ILogger{T}"/> used to log diagnostic messages. | |||
/// </value> | |||
public ILogger<RedisXmlRepository> Logger { get; private set; } | |||
/// <summary> | |||
/// Performs application-defined tasks associated with freeing, releasing, | |||
/// or resetting unmanaged resources. | |||
/// </summary> | |||
public void Dispose() | |||
{ | |||
this.Dispose(true); | |||
} | |||
/// <summary> | |||
/// Gets all top-level XML elements in the repository. | |||
/// </summary> | |||
/// <returns> | |||
/// An <see cref="IReadOnlyCollection{T}"/> with the set of elements | |||
/// stored in the repository. | |||
/// </returns> | |||
public IReadOnlyCollection<XElement> GetAllElements() | |||
{ | |||
var database = this._connection.GetDatabase(); | |||
var hash = database.HashGetAll(RedisHashKey); | |||
var elements = new List<XElement>(); | |||
if (hash == null || hash.Length == 0) | |||
{ | |||
return elements.AsReadOnly(); | |||
} | |||
foreach (var item in hash.ToStringDictionary()) | |||
{ | |||
elements.Add(XElement.Parse(item.Value)); | |||
} | |||
this.Logger.LogDebug("Read {XmlElementCount} XML elements from Redis.", elements.Count); | |||
return elements.AsReadOnly(); | |||
} | |||
/// <summary> | |||
/// Adds a top-level XML element to the repository. | |||
/// </summary> | |||
/// <param name="element">The element to add.</param> | |||
/// <param name="friendlyName"> | |||
/// An optional name to be associated with the XML element. | |||
/// For instance, if this repository stores XML files on disk, the friendly name may | |||
/// be used as part of the file name. Repository implementations are not required to | |||
/// observe this parameter even if it has been provided by the caller. | |||
/// </param> | |||
/// <remarks> | |||
/// The <paramref name="friendlyName" /> parameter must be unique if specified. | |||
/// For instance, it could be the ID of the key being stored. | |||
/// </remarks> | |||
/// <exception cref="System.ArgumentNullException"> | |||
/// Thrown if <paramref name="element" /> is <see langword="null" />. | |||
/// </exception> | |||
public void StoreElement(XElement element, string friendlyName) | |||
{ | |||
if (element == null) | |||
{ | |||
throw new ArgumentNullException(nameof(element)); | |||
} | |||
if (string.IsNullOrEmpty(friendlyName)) | |||
{ | |||
// The framework always passes in a name, but | |||
// the contract indicates this may be null or empty. | |||
friendlyName = Guid.NewGuid().ToString(); | |||
} | |||
this.Logger.LogDebug("Storing XML element with friendly name {XmlElementFriendlyName}.", friendlyName); | |||
this._connection.GetDatabase().HashSet(RedisHashKey, friendlyName, element.ToString()); | |||
} | |||
/// <summary> | |||
/// Releases unmanaged and - optionally - managed resources. | |||
/// </summary> | |||
/// <param name="disposing"> | |||
/// <see langword="true" /> to release both managed and unmanaged resources; | |||
/// <see langword="false" /> to release only unmanaged resources. | |||
/// </param> | |||
protected virtual void Dispose(bool disposing) | |||
{ | |||
if (!this._disposed) | |||
{ | |||
if (disposing) | |||
{ | |||
if (this._connection != null) | |||
{ | |||
this._connection.Close(); | |||
this._connection.Dispose(); | |||
} | |||
} | |||
this._connection = null; | |||
this._disposed = true; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,52 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Infrastructure; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using IdentityServer4.EntityFramework.DbContexts; | |||
namespace Identity.API.Migrations | |||
{ | |||
[DbContext(typeof(PersistedGrantDbContext))] | |||
[Migration("20170604151240_Init-persisted-grant")] | |||
partial class Initpersistedgrant | |||
{ | |||
protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder | |||
.HasAnnotation("ProductVersion", "1.1.2") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => | |||
{ | |||
b.Property<string>("Key") | |||
.HasMaxLength(200); | |||
b.Property<string>("ClientId") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<DateTime>("CreationTime"); | |||
b.Property<string>("Data") | |||
.IsRequired() | |||
.HasMaxLength(50000); | |||
b.Property<DateTime?>("Expiration"); | |||
b.Property<string>("SubjectId") | |||
.HasMaxLength(200); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(50); | |||
b.HasKey("Key"); | |||
b.HasIndex("SubjectId", "ClientId", "Type"); | |||
b.ToTable("PersistedGrants"); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,40 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
namespace Identity.API.Migrations | |||
{ | |||
public partial class Initpersistedgrant : Migration | |||
{ | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.CreateTable( | |||
name: "PersistedGrants", | |||
columns: table => new | |||
{ | |||
Key = table.Column<string>(maxLength: 200, nullable: false), | |||
ClientId = table.Column<string>(maxLength: 200, nullable: false), | |||
CreationTime = table.Column<DateTime>(nullable: false), | |||
Data = table.Column<string>(maxLength: 50000, nullable: false), | |||
Expiration = table.Column<DateTime>(nullable: true), | |||
SubjectId = table.Column<string>(maxLength: 200, nullable: true), | |||
Type = table.Column<string>(maxLength: 50, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_PersistedGrants", x => x.Key); | |||
}); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_PersistedGrants_SubjectId_ClientId_Type", | |||
table: "PersistedGrants", | |||
columns: new[] { "SubjectId", "ClientId", "Type" }); | |||
} | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.DropTable( | |||
name: "PersistedGrants"); | |||
} | |||
} | |||
} |
@ -0,0 +1,539 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Infrastructure; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using IdentityServer4.EntityFramework.DbContexts; | |||
namespace Identity.API.Migrations.ConfigurationDb | |||
{ | |||
[DbContext(typeof(ConfigurationDbContext))] | |||
[Migration("20170604151338_Init-configuration")] | |||
partial class Initconfiguration | |||
{ | |||
protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder | |||
.HasAnnotation("ProductVersion", "1.1.2") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<string>("DisplayName") | |||
.HasMaxLength(200); | |||
b.Property<bool>("Enabled"); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("Name") | |||
.IsUnique(); | |||
b.ToTable("ApiResources"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiResourceId"); | |||
b.ToTable("ApiClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<string>("DisplayName") | |||
.HasMaxLength(200); | |||
b.Property<bool>("Emphasize"); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<bool>("Required"); | |||
b.Property<bool>("ShowInDiscoveryDocument"); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiResourceId"); | |||
b.HasIndex("Name") | |||
.IsUnique(); | |||
b.ToTable("ApiScopes"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiScopeId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiScopeId"); | |||
b.ToTable("ApiScopeClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<DateTime?>("Expiration"); | |||
b.Property<string>("Type") | |||
.HasMaxLength(250); | |||
b.Property<string>("Value") | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiResourceId"); | |||
b.ToTable("ApiSecrets"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int>("AbsoluteRefreshTokenLifetime"); | |||
b.Property<int>("AccessTokenLifetime"); | |||
b.Property<int>("AccessTokenType"); | |||
b.Property<bool>("AllowAccessTokensViaBrowser"); | |||
b.Property<bool>("AllowOfflineAccess"); | |||
b.Property<bool>("AllowPlainTextPkce"); | |||
b.Property<bool>("AllowRememberConsent"); | |||
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken"); | |||
b.Property<bool>("AlwaysSendClientClaims"); | |||
b.Property<int>("AuthorizationCodeLifetime"); | |||
b.Property<string>("ClientId") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<string>("ClientName") | |||
.HasMaxLength(200); | |||
b.Property<string>("ClientUri") | |||
.HasMaxLength(2000); | |||
b.Property<bool>("EnableLocalLogin"); | |||
b.Property<bool>("Enabled"); | |||
b.Property<int>("IdentityTokenLifetime"); | |||
b.Property<bool>("IncludeJwtId"); | |||
b.Property<string>("LogoUri"); | |||
b.Property<bool>("LogoutSessionRequired"); | |||
b.Property<string>("LogoutUri"); | |||
b.Property<bool>("PrefixClientClaims"); | |||
b.Property<string>("ProtocolType") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<int>("RefreshTokenExpiration"); | |||
b.Property<int>("RefreshTokenUsage"); | |||
b.Property<bool>("RequireClientSecret"); | |||
b.Property<bool>("RequireConsent"); | |||
b.Property<bool>("RequirePkce"); | |||
b.Property<int>("SlidingRefreshTokenLifetime"); | |||
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh"); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId") | |||
.IsUnique(); | |||
b.ToTable("Clients"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(250); | |||
b.Property<string>("Value") | |||
.IsRequired() | |||
.HasMaxLength(250); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Origin") | |||
.IsRequired() | |||
.HasMaxLength(150); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientCorsOrigins"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("GrantType") | |||
.IsRequired() | |||
.HasMaxLength(250); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientGrantTypes"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Provider") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientIdPRestrictions"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("PostLogoutRedirectUri") | |||
.IsRequired() | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientPostLogoutRedirectUris"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("RedirectUri") | |||
.IsRequired() | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientRedirectUris"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Scope") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientScopes"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(2000); | |||
b.Property<DateTime?>("Expiration"); | |||
b.Property<string>("Type") | |||
.HasMaxLength(250); | |||
b.Property<string>("Value") | |||
.IsRequired() | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientSecrets"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("IdentityResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("IdentityResourceId"); | |||
b.ToTable("IdentityClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<string>("DisplayName") | |||
.HasMaxLength(200); | |||
b.Property<bool>("Emphasize"); | |||
b.Property<bool>("Enabled"); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<bool>("Required"); | |||
b.Property<bool>("ShowInDiscoveryDocument"); | |||
b.HasKey("Id"); | |||
b.HasIndex("Name") | |||
.IsUnique(); | |||
b.ToTable("IdentityResources"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") | |||
.WithMany("UserClaims") | |||
.HasForeignKey("ApiResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") | |||
.WithMany("Scopes") | |||
.HasForeignKey("ApiResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") | |||
.WithMany("UserClaims") | |||
.HasForeignKey("ApiScopeId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") | |||
.WithMany("Secrets") | |||
.HasForeignKey("ApiResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("Claims") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("AllowedCorsOrigins") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("AllowedGrantTypes") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("IdentityProviderRestrictions") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("PostLogoutRedirectUris") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("RedirectUris") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("AllowedScopes") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("ClientSecrets") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") | |||
.WithMany("UserClaims") | |||
.HasForeignKey("IdentityResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,501 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
namespace Identity.API.Migrations.ConfigurationDb | |||
{ | |||
public partial class Initconfiguration : Migration | |||
{ | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.CreateTable( | |||
name: "ApiResources", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
Description = table.Column<string>(maxLength: 1000, nullable: true), | |||
DisplayName = table.Column<string>(maxLength: 200, nullable: true), | |||
Enabled = table.Column<bool>(nullable: false), | |||
Name = table.Column<string>(maxLength: 200, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ApiResources", x => x.Id); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "Clients", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
AbsoluteRefreshTokenLifetime = table.Column<int>(nullable: false), | |||
AccessTokenLifetime = table.Column<int>(nullable: false), | |||
AccessTokenType = table.Column<int>(nullable: false), | |||
AllowAccessTokensViaBrowser = table.Column<bool>(nullable: false), | |||
AllowOfflineAccess = table.Column<bool>(nullable: false), | |||
AllowPlainTextPkce = table.Column<bool>(nullable: false), | |||
AllowRememberConsent = table.Column<bool>(nullable: false), | |||
AlwaysIncludeUserClaimsInIdToken = table.Column<bool>(nullable: false), | |||
AlwaysSendClientClaims = table.Column<bool>(nullable: false), | |||
AuthorizationCodeLifetime = table.Column<int>(nullable: false), | |||
ClientId = table.Column<string>(maxLength: 200, nullable: false), | |||
ClientName = table.Column<string>(maxLength: 200, nullable: true), | |||
ClientUri = table.Column<string>(maxLength: 2000, nullable: true), | |||
EnableLocalLogin = table.Column<bool>(nullable: false), | |||
Enabled = table.Column<bool>(nullable: false), | |||
IdentityTokenLifetime = table.Column<int>(nullable: false), | |||
IncludeJwtId = table.Column<bool>(nullable: false), | |||
LogoUri = table.Column<string>(nullable: true), | |||
LogoutSessionRequired = table.Column<bool>(nullable: false), | |||
LogoutUri = table.Column<string>(nullable: true), | |||
PrefixClientClaims = table.Column<bool>(nullable: false), | |||
ProtocolType = table.Column<string>(maxLength: 200, nullable: false), | |||
RefreshTokenExpiration = table.Column<int>(nullable: false), | |||
RefreshTokenUsage = table.Column<int>(nullable: false), | |||
RequireClientSecret = table.Column<bool>(nullable: false), | |||
RequireConsent = table.Column<bool>(nullable: false), | |||
RequirePkce = table.Column<bool>(nullable: false), | |||
SlidingRefreshTokenLifetime = table.Column<int>(nullable: false), | |||
UpdateAccessTokenClaimsOnRefresh = table.Column<bool>(nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_Clients", x => x.Id); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "IdentityResources", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
Description = table.Column<string>(maxLength: 1000, nullable: true), | |||
DisplayName = table.Column<string>(maxLength: 200, nullable: true), | |||
Emphasize = table.Column<bool>(nullable: false), | |||
Enabled = table.Column<bool>(nullable: false), | |||
Name = table.Column<string>(maxLength: 200, nullable: false), | |||
Required = table.Column<bool>(nullable: false), | |||
ShowInDiscoveryDocument = table.Column<bool>(nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_IdentityResources", x => x.Id); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ApiClaims", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ApiResourceId = table.Column<int>(nullable: false), | |||
Type = table.Column<string>(maxLength: 200, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ApiClaims", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ApiClaims_ApiResources_ApiResourceId", | |||
column: x => x.ApiResourceId, | |||
principalTable: "ApiResources", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ApiScopes", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ApiResourceId = table.Column<int>(nullable: false), | |||
Description = table.Column<string>(maxLength: 1000, nullable: true), | |||
DisplayName = table.Column<string>(maxLength: 200, nullable: true), | |||
Emphasize = table.Column<bool>(nullable: false), | |||
Name = table.Column<string>(maxLength: 200, nullable: false), | |||
Required = table.Column<bool>(nullable: false), | |||
ShowInDiscoveryDocument = table.Column<bool>(nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ApiScopes", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ApiScopes_ApiResources_ApiResourceId", | |||
column: x => x.ApiResourceId, | |||
principalTable: "ApiResources", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ApiSecrets", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ApiResourceId = table.Column<int>(nullable: false), | |||
Description = table.Column<string>(maxLength: 1000, nullable: true), | |||
Expiration = table.Column<DateTime>(nullable: true), | |||
Type = table.Column<string>(maxLength: 250, nullable: true), | |||
Value = table.Column<string>(maxLength: 2000, nullable: true) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ApiSecrets", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ApiSecrets_ApiResources_ApiResourceId", | |||
column: x => x.ApiResourceId, | |||
principalTable: "ApiResources", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientClaims", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
Type = table.Column<string>(maxLength: 250, nullable: false), | |||
Value = table.Column<string>(maxLength: 250, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientClaims", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientClaims_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientCorsOrigins", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
Origin = table.Column<string>(maxLength: 150, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientCorsOrigins_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientGrantTypes", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
GrantType = table.Column<string>(maxLength: 250, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientGrantTypes_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientIdPRestrictions", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
Provider = table.Column<string>(maxLength: 200, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientIdPRestrictions_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientPostLogoutRedirectUris", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
PostLogoutRedirectUri = table.Column<string>(maxLength: 2000, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientRedirectUris", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
RedirectUri = table.Column<string>(maxLength: 2000, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientRedirectUris_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientScopes", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
Scope = table.Column<string>(maxLength: 200, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientScopes", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientScopes_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ClientSecrets", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ClientId = table.Column<int>(nullable: false), | |||
Description = table.Column<string>(maxLength: 2000, nullable: true), | |||
Expiration = table.Column<DateTime>(nullable: true), | |||
Type = table.Column<string>(maxLength: 250, nullable: true), | |||
Value = table.Column<string>(maxLength: 2000, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ClientSecrets", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ClientSecrets_Clients_ClientId", | |||
column: x => x.ClientId, | |||
principalTable: "Clients", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "IdentityClaims", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
IdentityResourceId = table.Column<int>(nullable: false), | |||
Type = table.Column<string>(maxLength: 200, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_IdentityClaims", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_IdentityClaims_IdentityResources_IdentityResourceId", | |||
column: x => x.IdentityResourceId, | |||
principalTable: "IdentityResources", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateTable( | |||
name: "ApiScopeClaims", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(nullable: false) | |||
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), | |||
ApiScopeId = table.Column<int>(nullable: false), | |||
Type = table.Column<string>(maxLength: 200, nullable: false) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); | |||
table.ForeignKey( | |||
name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId", | |||
column: x => x.ApiScopeId, | |||
principalTable: "ApiScopes", | |||
principalColumn: "Id", | |||
onDelete: ReferentialAction.Cascade); | |||
}); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ApiResources_Name", | |||
table: "ApiResources", | |||
column: "Name", | |||
unique: true); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ApiClaims_ApiResourceId", | |||
table: "ApiClaims", | |||
column: "ApiResourceId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ApiScopes_ApiResourceId", | |||
table: "ApiScopes", | |||
column: "ApiResourceId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ApiScopes_Name", | |||
table: "ApiScopes", | |||
column: "Name", | |||
unique: true); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ApiScopeClaims_ApiScopeId", | |||
table: "ApiScopeClaims", | |||
column: "ApiScopeId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ApiSecrets_ApiResourceId", | |||
table: "ApiSecrets", | |||
column: "ApiResourceId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_Clients_ClientId", | |||
table: "Clients", | |||
column: "ClientId", | |||
unique: true); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientClaims_ClientId", | |||
table: "ClientClaims", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientCorsOrigins_ClientId", | |||
table: "ClientCorsOrigins", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientGrantTypes_ClientId", | |||
table: "ClientGrantTypes", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientIdPRestrictions_ClientId", | |||
table: "ClientIdPRestrictions", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientPostLogoutRedirectUris_ClientId", | |||
table: "ClientPostLogoutRedirectUris", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientRedirectUris_ClientId", | |||
table: "ClientRedirectUris", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientScopes_ClientId", | |||
table: "ClientScopes", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_ClientSecrets_ClientId", | |||
table: "ClientSecrets", | |||
column: "ClientId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_IdentityClaims_IdentityResourceId", | |||
table: "IdentityClaims", | |||
column: "IdentityResourceId"); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_IdentityResources_Name", | |||
table: "IdentityResources", | |||
column: "Name", | |||
unique: true); | |||
} | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.DropTable( | |||
name: "ApiClaims"); | |||
migrationBuilder.DropTable( | |||
name: "ApiScopeClaims"); | |||
migrationBuilder.DropTable( | |||
name: "ApiSecrets"); | |||
migrationBuilder.DropTable( | |||
name: "ClientClaims"); | |||
migrationBuilder.DropTable( | |||
name: "ClientCorsOrigins"); | |||
migrationBuilder.DropTable( | |||
name: "ClientGrantTypes"); | |||
migrationBuilder.DropTable( | |||
name: "ClientIdPRestrictions"); | |||
migrationBuilder.DropTable( | |||
name: "ClientPostLogoutRedirectUris"); | |||
migrationBuilder.DropTable( | |||
name: "ClientRedirectUris"); | |||
migrationBuilder.DropTable( | |||
name: "ClientScopes"); | |||
migrationBuilder.DropTable( | |||
name: "ClientSecrets"); | |||
migrationBuilder.DropTable( | |||
name: "IdentityClaims"); | |||
migrationBuilder.DropTable( | |||
name: "ApiScopes"); | |||
migrationBuilder.DropTable( | |||
name: "Clients"); | |||
migrationBuilder.DropTable( | |||
name: "IdentityResources"); | |||
migrationBuilder.DropTable( | |||
name: "ApiResources"); | |||
} | |||
} | |||
} |
@ -0,0 +1,538 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Infrastructure; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using IdentityServer4.EntityFramework.DbContexts; | |||
namespace Identity.API.Migrations.ConfigurationDb | |||
{ | |||
[DbContext(typeof(ConfigurationDbContext))] | |||
partial class ConfigurationDbContextModelSnapshot : ModelSnapshot | |||
{ | |||
protected override void BuildModel(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder | |||
.HasAnnotation("ProductVersion", "1.1.2") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<string>("DisplayName") | |||
.HasMaxLength(200); | |||
b.Property<bool>("Enabled"); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("Name") | |||
.IsUnique(); | |||
b.ToTable("ApiResources"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiResourceId"); | |||
b.ToTable("ApiClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<string>("DisplayName") | |||
.HasMaxLength(200); | |||
b.Property<bool>("Emphasize"); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<bool>("Required"); | |||
b.Property<bool>("ShowInDiscoveryDocument"); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiResourceId"); | |||
b.HasIndex("Name") | |||
.IsUnique(); | |||
b.ToTable("ApiScopes"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiScopeId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiScopeId"); | |||
b.ToTable("ApiScopeClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ApiResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<DateTime?>("Expiration"); | |||
b.Property<string>("Type") | |||
.HasMaxLength(250); | |||
b.Property<string>("Value") | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ApiResourceId"); | |||
b.ToTable("ApiSecrets"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int>("AbsoluteRefreshTokenLifetime"); | |||
b.Property<int>("AccessTokenLifetime"); | |||
b.Property<int>("AccessTokenType"); | |||
b.Property<bool>("AllowAccessTokensViaBrowser"); | |||
b.Property<bool>("AllowOfflineAccess"); | |||
b.Property<bool>("AllowPlainTextPkce"); | |||
b.Property<bool>("AllowRememberConsent"); | |||
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken"); | |||
b.Property<bool>("AlwaysSendClientClaims"); | |||
b.Property<int>("AuthorizationCodeLifetime"); | |||
b.Property<string>("ClientId") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<string>("ClientName") | |||
.HasMaxLength(200); | |||
b.Property<string>("ClientUri") | |||
.HasMaxLength(2000); | |||
b.Property<bool>("EnableLocalLogin"); | |||
b.Property<bool>("Enabled"); | |||
b.Property<int>("IdentityTokenLifetime"); | |||
b.Property<bool>("IncludeJwtId"); | |||
b.Property<string>("LogoUri"); | |||
b.Property<bool>("LogoutSessionRequired"); | |||
b.Property<string>("LogoutUri"); | |||
b.Property<bool>("PrefixClientClaims"); | |||
b.Property<string>("ProtocolType") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<int>("RefreshTokenExpiration"); | |||
b.Property<int>("RefreshTokenUsage"); | |||
b.Property<bool>("RequireClientSecret"); | |||
b.Property<bool>("RequireConsent"); | |||
b.Property<bool>("RequirePkce"); | |||
b.Property<int>("SlidingRefreshTokenLifetime"); | |||
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh"); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId") | |||
.IsUnique(); | |||
b.ToTable("Clients"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(250); | |||
b.Property<string>("Value") | |||
.IsRequired() | |||
.HasMaxLength(250); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Origin") | |||
.IsRequired() | |||
.HasMaxLength(150); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientCorsOrigins"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("GrantType") | |||
.IsRequired() | |||
.HasMaxLength(250); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientGrantTypes"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Provider") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientIdPRestrictions"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("PostLogoutRedirectUri") | |||
.IsRequired() | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientPostLogoutRedirectUris"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("RedirectUri") | |||
.IsRequired() | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientRedirectUris"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Scope") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientScopes"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("ClientId") | |||
.IsRequired(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(2000); | |||
b.Property<DateTime?>("Expiration"); | |||
b.Property<string>("Type") | |||
.HasMaxLength(250); | |||
b.Property<string>("Value") | |||
.IsRequired() | |||
.HasMaxLength(2000); | |||
b.HasKey("Id"); | |||
b.HasIndex("ClientId"); | |||
b.ToTable("ClientSecrets"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<int?>("IdentityResourceId") | |||
.IsRequired(); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.HasKey("Id"); | |||
b.HasIndex("IdentityResourceId"); | |||
b.ToTable("IdentityClaims"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => | |||
{ | |||
b.Property<int>("Id") | |||
.ValueGeneratedOnAdd(); | |||
b.Property<string>("Description") | |||
.HasMaxLength(1000); | |||
b.Property<string>("DisplayName") | |||
.HasMaxLength(200); | |||
b.Property<bool>("Emphasize"); | |||
b.Property<bool>("Enabled"); | |||
b.Property<string>("Name") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<bool>("Required"); | |||
b.Property<bool>("ShowInDiscoveryDocument"); | |||
b.HasKey("Id"); | |||
b.HasIndex("Name") | |||
.IsUnique(); | |||
b.ToTable("IdentityResources"); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") | |||
.WithMany("UserClaims") | |||
.HasForeignKey("ApiResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") | |||
.WithMany("Scopes") | |||
.HasForeignKey("ApiResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") | |||
.WithMany("UserClaims") | |||
.HasForeignKey("ApiScopeId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") | |||
.WithMany("Secrets") | |||
.HasForeignKey("ApiResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("Claims") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("AllowedCorsOrigins") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("AllowedGrantTypes") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("IdentityProviderRestrictions") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("PostLogoutRedirectUris") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("RedirectUris") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("AllowedScopes") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") | |||
.WithMany("ClientSecrets") | |||
.HasForeignKey("ClientId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => | |||
{ | |||
b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") | |||
.WithMany("UserClaims") | |||
.HasForeignKey("IdentityResourceId") | |||
.OnDelete(DeleteBehavior.Cascade); | |||
}); | |||
} | |||
} | |||
} |
@ -0,0 +1,51 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore.Infrastructure; | |||
using Microsoft.EntityFrameworkCore.Metadata; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
using IdentityServer4.EntityFramework.DbContexts; | |||
namespace Identity.API.Migrations | |||
{ | |||
[DbContext(typeof(PersistedGrantDbContext))] | |||
partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot | |||
{ | |||
protected override void BuildModel(ModelBuilder modelBuilder) | |||
{ | |||
modelBuilder | |||
.HasAnnotation("ProductVersion", "1.1.2") | |||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); | |||
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => | |||
{ | |||
b.Property<string>("Key") | |||
.HasMaxLength(200); | |||
b.Property<string>("ClientId") | |||
.IsRequired() | |||
.HasMaxLength(200); | |||
b.Property<DateTime>("CreationTime"); | |||
b.Property<string>("Data") | |||
.IsRequired() | |||
.HasMaxLength(50000); | |||
b.Property<DateTime?>("Expiration"); | |||
b.Property<string>("SubjectId") | |||
.HasMaxLength(200); | |||
b.Property<string>("Type") | |||
.IsRequired() | |||
.HasMaxLength(50); | |||
b.HasKey("Key"); | |||
b.HasIndex("SubjectId", "ClientId", "Type"); | |||
b.ToTable("PersistedGrants"); | |||
}); | |||
} | |||
} | |||
} |