예제 #1
0
            public async Task DoesNotMigrateUpToDateClients()
            {
                var upToDateClient = new ClientDataRecordV2 {
                    Id            = "c1",
                    Name          = "Up-to-date client",
                    ClockSkew     = 60,
                    NonceLifetime = 30,
#pragma warning disable 618
                    NonceExpiration = null,
#pragma warning restore 618
                    SignatureAlgorithm = new SignatureAlgorithmDataRecordV2 {
                        Type                 = "HMAC",
                        Parameter            = "s3cr37",
                        HashAlgorithm        = "SHA384",
                        IsParameterEncrypted = false
                    },
                    V = 2,
                    RequestTargetEscaping = "RFC3986",
                    Claims = new[] {
                        ClaimDataRecordV2.FromClaim(new Claim("company", "Dalion"))
                    }
                };

                await _mongoCollection.InsertOneAsync(upToDateClient);

                await _sut.Run();

                var findResult = await _mongoCollection.FindAsync <ClientDataRecordV2>(new ExpressionFilterDefinition <ClientDataRecordV2>(r => r.Id == upToDateClient.Id));

                var loaded = await findResult.SingleAsync();

                loaded.Should().BeEquivalentTo(upToDateClient);
            }
        public async Task Run()
        {
            var collection = _lazyCollection.Value;

            var allClients = await collection.FindAsync(FilterDefinition <ClientDataRecordV2> .Empty).ConfigureAwait(continueOnCapturedContext: false);

            var clientsToMigrate = (await allClients.ToListAsync().ConfigureAwait(continueOnCapturedContext: false))
                                   .Where(c => !c.V.HasValue || c.V.Value < 2)
                                   .ToList();

            foreach (var clientToMigrate in clientsToMigrate)
            {
                // Encrypt parameter, if needed:
                // - Encryption should be enabled
                // - It should not have been encrypted before
                // - Only applicable for HMAC signature algorithms (the only supported symmetric key algorithm)
                if (_mongoDbClientStoreSettings.SharedSecretEncryptionKey != SharedSecretEncryptionKey.Empty &&
                    clientToMigrate.SignatureAlgorithm.Type.Equals("hmac", StringComparison.OrdinalIgnoreCase) &&
                    !clientToMigrate.SignatureAlgorithm.IsParameterEncrypted)
                {
                    var protector = _stringProtectorFactory.CreateSymmetric(_mongoDbClientStoreSettings.SharedSecretEncryptionKey);
                    clientToMigrate.SignatureAlgorithm.Parameter            = protector.Protect(clientToMigrate.SignatureAlgorithm.Parameter);
                    clientToMigrate.SignatureAlgorithm.IsParameterEncrypted = true;
                }

                // Fill in RequestTargetEscaping, if it is missing
                clientToMigrate.RequestTargetEscaping = ClientOptions.Default.RequestTargetEscaping.ToString();

                // Fill in ClockSkew, if it is missing
                clientToMigrate.ClockSkew = clientToMigrate.ClockSkew ?? ClientOptions.Default.ClockSkew.TotalSeconds;

                // Fill in NonceLifetime, if it is missing, and drop obsolete NonceExpiration value
#pragma warning disable 618
                clientToMigrate.NonceLifetime   = clientToMigrate.NonceLifetime ?? clientToMigrate.NonceExpiration ?? ClientOptions.Default.NonceLifetime.TotalSeconds;
                clientToMigrate.NonceExpiration = null;
#pragma warning restore 618

                // Update version
                clientToMigrate.V = ClientDataRecordV2.GetV();

                // Store migrated client
                await collection
                .ReplaceOneAsync(_ => _.Id == clientToMigrate.Id, clientToMigrate, new ReplaceOptions { IsUpsert = false })
                .ConfigureAwait(continueOnCapturedContext: false);
            }
        }
예제 #3
0
            public async Task MigratesApplicableClientsAndEncryptsParameters()
            {
                var upToDateClient = new ClientDataRecordV2 {
                    Id            = "c2",
                    Name          = "Up-to-date client",
                    ClockSkew     = 60,
                    NonceLifetime = 30,
#pragma warning disable 618
                    NonceExpiration = null,
#pragma warning restore 618
                    SignatureAlgorithm = new SignatureAlgorithmDataRecordV2 {
                        Type                 = "HMAC",
                        Parameter            = "s3cr37",
                        HashAlgorithm        = "SHA384",
                        IsParameterEncrypted = false
                    },
                    V = 2,
                    RequestTargetEscaping = "RFC3986",
                    Claims = new[] {
                        ClaimDataRecordV2.FromClaim(new Claim("company", "Dalion"))
                    }
                };
                await _mongoCollection.InsertOneAsync(upToDateClient);

                var bsonCollection = Database.GetCollection <BsonDocument>(_settings.CollectionName);
                var legacyJson     = @"{ 
    ""_id"" : ""c3"", 
    ""Name"" : ""Legacy client"", 
    ""SignatureAlgorithm"" : {
        ""Type"" : ""HMAC"", 
        ""Parameter"" : ""s3cr3t"", 
        ""HashAlgorithm"" : ""SHA384""
    }, 
    ""Claims"" : [
        {
            ""Issuer"" : ""LOCAL AUTHORITY"", 
            ""OriginalIssuer"" : ""LOCAL AUTHORITY"", 
            ""Type"" : ""company"", 
            ""Value"" : ""Dalion"", 
            ""ValueType"" : ""http://www.w3.org/2001/XMLSchema#string""
        }, 
        {
            ""Issuer"" : ""LOCAL AUTHORITY"", 
            ""OriginalIssuer"" : ""LOCAL AUTHORITY"", 
            ""Type"" : ""scope"", 
            ""Value"" : ""HttpMessageSigning"", 
            ""ValueType"" : ""http://www.w3.org/2001/XMLSchema#string""
        }
    ]
}";
                var legacyDocument = BsonSerializer.Deserialize <BsonDocument>(legacyJson);
                await bsonCollection.InsertOneAsync(legacyDocument);

                await _sut.Run();

                var findUpToDateResult = await _mongoCollection.FindAsync <ClientDataRecordV2>(new ExpressionFilterDefinition <ClientDataRecordV2>(r => r.Id == upToDateClient.Id));

                var loadedUpToDate = await findUpToDateResult.SingleAsync();

                loadedUpToDate.Should().BeEquivalentTo(upToDateClient);

                var findLegacyResult = await _mongoCollection.FindAsync <ClientDataRecordV2>(new ExpressionFilterDefinition <ClientDataRecordV2>(r => r.Id == "c3"));

                var loadedLegacy = await findLegacyResult.SingleAsync();

                var expectedMigratedClient = new ClientDataRecordV2 {
                    Id            = "c3",
                    Name          = "Legacy client",
                    ClockSkew     = 60.0,
                    NonceLifetime = 300.0,
#pragma warning disable 618
                    NonceExpiration = null,
#pragma warning restore 618
                    SignatureAlgorithm = new SignatureAlgorithmDataRecordV2 {
                        Type                 = "HMAC",
                        Parameter            = "s3cr3t",
                        HashAlgorithm        = "SHA384",
                        IsParameterEncrypted = true
                    },
                    V = 2,
                    RequestTargetEscaping = "RFC3986",
                    Claims = new[] {
                        ClaimDataRecordV2.FromClaim(new Claim("company", "Dalion")),
                        ClaimDataRecordV2.FromClaim(new Claim("scope", "HttpMessageSigning"))
                    }
                };

                loadedLegacy.Should().BeEquivalentTo(expectedMigratedClient, options => options.Excluding(_ => _.SignatureAlgorithm.Parameter));
                loadedLegacy.SignatureAlgorithm.Parameter.Should().NotBeNull().And.NotBe("s3cr3t");
            }