mirror of https://github.com/Squidex/squidex.git
9 changed files with 216 additions and 101 deletions
@ -0,0 +1,23 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
|
|||
namespace Squidex.Domain.Users.MongoDb |
|||
{ |
|||
public sealed class MongoKey |
|||
{ |
|||
[BsonId] |
|||
public string Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
public string Key { get; set; } |
|||
|
|||
[BsonElement] |
|||
public MongoKeyParameters Parameters { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Security.Cryptography; |
|||
|
|||
#pragma warning disable IDE0017 // Simplify object initialization
|
|||
|
|||
namespace Squidex.Domain.Users.MongoDb |
|||
{ |
|||
public sealed class MongoKeyParameters |
|||
{ |
|||
public byte[] D { get; set; } |
|||
|
|||
public byte[] DP { get; set; } |
|||
|
|||
public byte[] DQ { get; set; } |
|||
|
|||
public byte[] Exponent { get; set; } |
|||
|
|||
public byte[] InverseQ { get; set; } |
|||
|
|||
public byte[] Modulus { get; set; } |
|||
|
|||
public byte[] P { get; set; } |
|||
|
|||
public byte[] Q { get; set; } |
|||
|
|||
public static MongoKeyParameters Create(RSAParameters source) |
|||
{ |
|||
var mongoParameters = new MongoKeyParameters(); |
|||
|
|||
mongoParameters.D = source.D; |
|||
mongoParameters.DP = source.DP; |
|||
mongoParameters.DQ = source.DQ; |
|||
mongoParameters.Exponent = source.Exponent; |
|||
mongoParameters.InverseQ = source.InverseQ; |
|||
mongoParameters.Modulus = source.Modulus; |
|||
mongoParameters.P = source.P; |
|||
mongoParameters.Q = source.Q; |
|||
|
|||
return mongoParameters; |
|||
} |
|||
|
|||
public RSAParameters ToParameters() |
|||
{ |
|||
var parameters = default(RSAParameters); |
|||
|
|||
parameters.D = D; |
|||
parameters.DP = DP; |
|||
parameters.DQ = DQ; |
|||
parameters.Exponent = Exponent; |
|||
parameters.InverseQ = InverseQ; |
|||
parameters.Modulus = Modulus; |
|||
parameters.P = P; |
|||
parameters.Q = Q; |
|||
|
|||
return parameters; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Cryptography; |
|||
using System.Threading.Tasks; |
|||
using IdentityModel; |
|||
using IdentityServer4.Models; |
|||
using IdentityServer4.Stores; |
|||
using Microsoft.IdentityModel.Tokens; |
|||
using MongoDB.Driver; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Users.MongoDb |
|||
{ |
|||
public sealed class MongoKeyStore : MongoRepositoryBase<MongoKey>, ISigningCredentialStore, IValidationKeysStore |
|||
{ |
|||
private SigningCredentials? cachedKey; |
|||
private SecurityKeyInfo[]? cachedKeyInfo; |
|||
|
|||
public MongoKeyStore(IMongoDatabase database, bool setup = false) |
|||
: base(database, setup) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "Key"; |
|||
} |
|||
|
|||
public async Task<SigningCredentials> GetSigningCredentialsAsync() |
|||
{ |
|||
var (_, key) = await GetOrCreateKeyAsync(); |
|||
|
|||
return key; |
|||
} |
|||
|
|||
public async Task<IEnumerable<SecurityKeyInfo>> GetValidationKeysAsync() |
|||
{ |
|||
var (info, _) = await GetOrCreateKeyAsync(); |
|||
|
|||
return info; |
|||
} |
|||
|
|||
private async Task<(SecurityKeyInfo[], SigningCredentials)> GetOrCreateKeyAsync() |
|||
{ |
|||
if (cachedKey != null && cachedKeyInfo != null) |
|||
{ |
|||
return (cachedKeyInfo, cachedKey); |
|||
} |
|||
|
|||
var key = await Collection.Find(x => x.Id == "Default").FirstOrDefaultAsync(); |
|||
|
|||
RsaSecurityKey securityKey; |
|||
|
|||
if (key == null) |
|||
{ |
|||
securityKey = new RsaSecurityKey(RSA.Create(2048)) |
|||
{ |
|||
KeyId = CryptoRandom.CreateUniqueId(16) |
|||
}; |
|||
|
|||
key = new MongoKey { Id = "Default", Key = securityKey.KeyId }; |
|||
|
|||
if (securityKey.Rsa != null) |
|||
{ |
|||
var parameters = securityKey.Rsa.ExportParameters(includePrivateParameters: true); |
|||
|
|||
key.Parameters = MongoKeyParameters.Create(parameters); |
|||
} |
|||
else |
|||
{ |
|||
key.Parameters = MongoKeyParameters.Create(securityKey.Parameters); |
|||
} |
|||
|
|||
try |
|||
{ |
|||
await Collection.InsertOneAsync(key); |
|||
|
|||
return CreateCredentialsPair(securityKey); |
|||
} |
|||
catch (MongoWriteException ex) |
|||
{ |
|||
if (ex.WriteError?.Category == ServerErrorCategory.DuplicateKey) |
|||
{ |
|||
key = await Collection.Find(x => x.Id == "Default").FirstOrDefaultAsync(); |
|||
} |
|||
else |
|||
{ |
|||
throw ex; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (key == null) |
|||
{ |
|||
throw new InvalidOperationException("Cannot read key."); |
|||
} |
|||
|
|||
securityKey = new RsaSecurityKey(key.Parameters.ToParameters()) |
|||
{ |
|||
KeyId = key.Key |
|||
}; |
|||
|
|||
return CreateCredentialsPair(securityKey); |
|||
} |
|||
|
|||
private (SecurityKeyInfo[], SigningCredentials) CreateCredentialsPair(RsaSecurityKey securityKey) |
|||
{ |
|||
cachedKey = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256); |
|||
|
|||
cachedKeyInfo = new[] |
|||
{ |
|||
new SecurityKeyInfo { Key = cachedKey.Key, SigningAlgorithm = cachedKey.Algorithm } |
|||
}; |
|||
|
|||
return (cachedKeyInfo, cachedKey); |
|||
} |
|||
} |
|||
} |
|||
@ -1,29 +0,0 @@ |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIFCzCCAvOgAwIBAgIULb5or4cjujSTMg9dZOFJtUU0h2MwDQYJKoZIhvcNAQEL |
|||
BQAwFTETMBEGA1UEAwwKc3F1aWRleC5pbzAeFw0xOTEwMjUxODAwMzJaFw0yOTEw |
|||
MjIxODAwMzJaMBUxEzARBgNVBAMMCnNxdWlkZXguaW8wggIiMA0GCSqGSIb3DQEB |
|||
AQUAA4ICDwAwggIKAoICAQDkCBwdntYhthsvwj7TobnKplejrvZvkMT79SGx4tXe |
|||
5eFDpuMGqljMUzZoUaaQsy4mRe/4c9bMmMlpRmIPpJfYAYDxGzSm9N0FjUZqGJPq |
|||
kRNTNKqTPeFwl7vdn+MuveLWyOc+mSYWkPWg9WURdN5yNtDi1IUrcj+XsUqH0AQi |
|||
eEiiQJlSUF8NkdvviGv906uOG/59NwpvCsyHwV3dOR2GFHvi2RIg/M+4d8Vz2AVm |
|||
KvXVoQtxySweXRXNKvoAeKdvQ4prHc0oHo57vhW/nDV++WUGZ7LOnpr4OgIyrvM/ |
|||
0LFfSIdgJ2rK/+yKNQLJKZbq0DD942PvQapEC9Xfuuqw1S6wHXgf3CzPuoNX4sDI |
|||
2rIw84AjH0gB7IuwC0DVqcbI++Xv6H3HzpD0i1ONaHztmp5tCx9v6dkJ0ctX6vzC |
|||
SwMxdUerB9XELifOF9CqnSjUzOiAuQ9yTE0iqb6jRu5JTGeKTtmFQ6T0YUuqiPip |
|||
H3zblloGKo3mQbVumvfELb0wTs3Ay0jaczjD0aM3fRKav+6b6Qu+tDnlxL/yPde2 |
|||
SMxDwIKIH8eCAa3+8OU9VSZ0+2DS/pu1vXdsXqa5EXJJ7Ej/NyQe+nKjOG/TfeYG |
|||
u+GAO5/pJYE4lWq77hZd9ylm21dbs+X4X3uZFOsGb0BCoQADi/QFwexcz+hOmQuX |
|||
BwIDAQABo1MwUTAdBgNVHQ4EFgQUuLxsPj+ueDfckXVeG6aRFM0KVc0wHwYDVR0j |
|||
BBgwFoAUuLxsPj+ueDfckXVeG6aRFM0KVc0wDwYDVR0TAQH/BAUwAwEB/zANBgkq |
|||
hkiG9w0BAQsFAAOCAgEA0ePG4Xp29yWkDHO2Zp6dG/uVy15sEVpG25VlwEuXzdnb |
|||
VDN1++spoTLZT0HWGs9OZtCkXF2wfFL3C/az5sSn40uXy5UzoHtldEjTchSFX2tN |
|||
ulVbSiEUyxp2xEzbELIPaELhecPUyJMKUTHOLfrLaKWFC26KQK+R5E4mdx0nIZ73 |
|||
9GZFDA7okfzqkl3CeLhHfkKrPy/dLcz9doBkca4scSmgJcMQvS2sC7wVrcTtfcsh |
|||
cefQ8hMR4vfVQHl0mU7cHUJR1U7sSrXh/pOjrzX/0k/VGO+pQtDVnT8YZXRx+w0S |
|||
4nRz60nUxIDbad/xld71YV6L3rWYy2/7MIbCb71mszc6SdQtV/+lc3yJJdvNmNtc |
|||
xlpirsI1vr3yfPcuYuS8i0dqPlh7Rn+wlrqFNlu6pgpB5uhVCHXfkf3TATGJpyi3 |
|||
lN/f98Du6ZDvsIFk6loWJ/SkRAgX4un3mVEeonDMSaWAHwfPdoMXE5ViCgKLPo+B |
|||
HHM5bmZmUk25mgFoiRYx/jnw2Ym+Vsyw6SI0+kQLLoAfP/pP39rWe+MbSIhhDXC6 |
|||
5lP5IebfzEI10PAg9UrgSDShAT2E4fFaMx0mRi0dwhRgBJEW/EEjjXd8+QjXPuPF |
|||
GqU6YTf/rcDQB4cT/GaBkUar3qanmBESAabMoabZ0EDVprwrrfbqx9bDsOz4J9k= |
|||
-----END CERTIFICATE----- |
|||
@ -1,52 +0,0 @@ |
|||
-----BEGIN PRIVATE KEY----- |
|||
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 |
|||
4VvGnkGGbUe3PWfxA+yBJqdyprlXbaY= |
|||
-----END PRIVATE KEY----- |
|||
Binary file not shown.
Loading…
Reference in new issue