Skip to content

Commit

Permalink
Merge pull request #14 from DuendeSoftware/features/ef_key_mgmt
Browse files Browse the repository at this point in the history
Add EF support for key mgmt
  • Loading branch information
brockallen authored Nov 23, 2020
2 parents eeee84b + 34860cb commit cf942f2
Show file tree
Hide file tree
Showing 17 changed files with 278 additions and 15 deletions.
10 changes: 5 additions & 5 deletions clean_cache.ps1
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Remove-Item $env:USERPROFILE\.nuget\packages\identityserver4\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\identityserver4.storage\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\identityserver4.entityframework\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\identityserver4.entityframework.storage\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\identityserver4.aspnetidentity\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\duende.identityserver\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\duende.identityserver.storage\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\duende.identityserver.entityframework\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\duende.identityserver.entityframework.storage\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\duende.identityserver.aspnetidentity\ -Recurse -ErrorAction SilentlyContinue

Remove-Item $env:USERPROFILE\.nuget\packages\identitymodel\ -Recurse -ErrorAction SilentlyContinue
Remove-Item $env:USERPROFILE\.nuget\packages\IdentityModel.AspNetCore.OAuth2Introspection\ -Recurse -ErrorAction SilentlyContinue
Expand Down
4 changes: 2 additions & 2 deletions src/EntityFramework.Storage/host/ConsoleHost/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Duende Software. All rights reserved.
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.


Expand All @@ -14,7 +14,7 @@ class Program
{
static void Main(string[] args)
{
var connectionString = "server=(localdb)\\mssqllocaldb;database=IdentityServer4.EntityFramework-4.0.0;trusted_connection=yes;";
var connectionString = "server=(localdb)\\mssqllocaldb;database=Duende.EntityFramework-5.0.0;trusted_connection=yes;";

var services = new ServiceCollection();
services.AddLogging(b => b.AddConsole().SetMinimumLevel(LogLevel.Trace));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ CREATE UNIQUE INDEX [IX_IdentityResources_Name] ON [IdentityResources] ([Name]);
GO

INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20201012150100_Configuration', N'3.1.0');
VALUES (N'20201123190954_Configuration', N'3.1.0');

GO

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ CREATE TABLE [DeviceCodes] (

GO

CREATE TABLE [Keys] (
[Id] nvarchar(450) NOT NULL,
[Version] int NOT NULL,
[Created] datetime2 NOT NULL,
[Algorithm] nvarchar(100) NOT NULL,
[IsX509Certificate] bit NOT NULL,
[DataProtected] bit NOT NULL,
[Data] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Keys] PRIMARY KEY ([Id])
);

GO

CREATE TABLE [PersistedGrants] (
[Key] nvarchar(200) NOT NULL,
[Type] nvarchar(50) NOT NULL,
Expand Down Expand Up @@ -61,7 +74,7 @@ CREATE INDEX [IX_PersistedGrants_SubjectId_SessionId_Type] ON [PersistedGrants]
GO

INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20201012150055_Grants', N'3.1.0');
VALUES (N'20201123190949_Grants', N'3.1.0');

GO

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,23 @@ protected override void Up(MigrationBuilder migrationBuilder)
table.PrimaryKey("PK_DeviceCodes", x => x.UserCode);
});

migrationBuilder.CreateTable(
name: "Keys",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Version = table.Column<int>(nullable: false),
Created = table.Column<DateTime>(nullable: false),
Algorithm = table.Column<string>(maxLength: 100, nullable: false),
IsX509Certificate = table.Column<bool>(nullable: false),
DataProtected = table.Column<bool>(nullable: false),
Data = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Keys", x => x.Id);
});

migrationBuilder.CreateTable(
name: "PersistedGrants",
columns: table => new
Expand Down Expand Up @@ -78,6 +95,9 @@ protected override void Down(MigrationBuilder migrationBuilder)
migrationBuilder.DropTable(
name: "DeviceCodes");

migrationBuilder.DropTable(
name: "Keys");

migrationBuilder.DropTable(
name: "PersistedGrants");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,37 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("DeviceCodes");
});

modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("Algorithm")
.IsRequired()
.HasColumnType("nvarchar(100)")
.HasMaxLength(100);
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("DataProtected")
.HasColumnType("bit");
b.Property<bool>("IsX509Certificate")
.HasColumnType("bit");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Keys");
});

modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b =>
{
b.Property<string>("Key")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Duende Software. All rights reserved.
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.


Expand Down Expand Up @@ -70,6 +70,14 @@ public PersistedGrantDbContext(DbContextOptions options, OperationalStoreOptions
/// </value>
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }

/// <summary>
/// Gets or sets the keys.
/// </summary>
/// <value>
/// The keys.
/// </value>
public DbSet<Key> Keys { get; set; }

/// <summary>
/// Saves the changes.
/// </summary>
Expand Down
23 changes: 23 additions & 0 deletions src/EntityFramework.Storage/src/Entities/Key.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.

#pragma warning disable 1591

using System;

namespace Duende.IdentityServer.EntityFramework.Entities
{
/// <summary>
/// Models storage for keys.
/// </summary>
public class Key
{
public string Id { get; set; }
public int Version { get; set; }
public DateTime Created { get; set; }
public string Algorithm { get; set; }
public bool IsX509Certificate { get; set; }
public bool DataProtected { get; set; }
public string Data { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Duende Software. All rights reserved.
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.


Expand Down Expand Up @@ -171,6 +171,13 @@ public static void ConfigurePersistedGrantContext(this ModelBuilder modelBuilder
codes.HasIndex(x => x.DeviceCode).IsUnique();
codes.HasIndex(x => x.Expiration);
});

modelBuilder.Entity<Key>(entity =>
{
entity.HasKey(x => x.Id);
entity.Property(x => x.Algorithm).HasMaxLength(100).IsRequired();
entity.Property(x => x.Data).IsRequired();
});
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Duende Software. All rights reserved.
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.


Expand Down Expand Up @@ -31,6 +31,16 @@ public interface IPersistedGrantDbContext : IDisposable
/// </value>
DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }


/// <summary>
/// Gets or sets the keys.
/// </summary>
/// <value>
/// The keys.
/// </value>
DbSet<Key> Keys { get; set; }


/// <summary>
/// Saves the changes.
/// </summary>
Expand Down
110 changes: 110 additions & 0 deletions src/EntityFramework.Storage/src/Stores/SigningKeyStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Duende.IdentityServer.EntityFramework.DbContexts;
using Duende.IdentityServer.EntityFramework.Entities;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Stores;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace Duende.IdentityServer.EntityFramework.Stores
{
/// <summary>
/// Implementation of ISigningKeyStore thats uses EF.
/// </summary>
/// <seealso cref="ISigningKeyStore" />
public class SigningKeyStore : ISigningKeyStore
{
/// <summary>
/// The DbContext.
/// </summary>
protected readonly PersistedGrantDbContext Context;

/// <summary>
/// The logger.
/// </summary>
protected readonly ILogger<SigningKeyStore> Logger;

/// <summary>
/// Initializes a new instance of the <see cref="SigningKeyStore"/> class.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="logger">The logger.</param>
/// <exception cref="ArgumentNullException">context</exception>
public SigningKeyStore(PersistedGrantDbContext context, ILogger<SigningKeyStore> logger)
{
Context = context ?? throw new ArgumentNullException(nameof(context));
Logger = logger;
}

/// <summary>
/// Loads all keys from store.
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<SerializedKey>> LoadKeysAsync()
{
var entities = await Context.Keys.ToArrayAsync();
return entities.Select(key => new SerializedKey
{
Id = key.Id,
Created = key.Created,
Version = key.Version,
Algorithm = key.Algorithm,
Data = key.Data,
DataProtected = key.DataProtected,
IsX509Certificate = key.IsX509Certificate
});
}

/// <summary>
/// Persists new key in store.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Task StoreKeyAsync(SerializedKey key)
{
var entity = new Key
{
Id = key.Id,
Created = key.Created,
Version = key.Version,
Algorithm = key.Algorithm,
Data = key.Data,
DataProtected = key.DataProtected,
IsX509Certificate = key.IsX509Certificate
};
Context.Keys.Add(entity);
return Context.SaveChangesAsync();
}

/// <summary>
/// Deletes key from storage.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task DeleteKeyAsync(string id)
{
var item = await Context.Keys.FirstOrDefaultAsync(x => x.Id == id);
if (item != null)
{
try
{
Context.Keys.Remove(item);
await Context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
Context.Entry(item).State = EntityState.Detached;
// already deleted, so we can eat this exception
Logger.LogDebug("Concurrency exception caught deleting key id {kid}", id);
}
}
}
}
}
Loading

0 comments on commit cf942f2

Please sign in to comment.