public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useSpeculativeAuthenticate, [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse( RawBsonDocumentHelper.FromJson("{ conversationId : 1, payload : BinData(0,'cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw'), done : false, ok : 1}")); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,'dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9')," + $" done : {new BsonBoolean(!useLongAuthentication)}, " + @" ok : 1}")); var saslLastStepResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,''), done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var helloResult = (BsonDocument)__descriptionCommandWireProtocol.HelloResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { helloResult.Add("speculativeAuthenticate", ((Type0CommandMessageSection <RawBsonDocument>)saslStartResponse.WrappedMessage.Sections[0]).Document); } connection.Description = new ConnectionDescription(__descriptionCommandWireProtocol.ConnectionId, new HelloResult(helloResult)); BsonDocument helloCommand = null; if (useSpeculativeAuthenticate) { // Call CustomizeInitialHelloCommand so that the authenticator thinks its started to speculatively // authenticate helloCommand = subject.CustomizeInitialHelloCommand(new BsonDocument { { OppressiveLanguageConstants.LegacyHelloCommandName, 1 } }); } else { connection.EnqueueCommandResponseMessage(saslStartResponse); } connection.EnqueueCommandResponseMessage(saslContinueResponse); if (useLongAuthentication) { connection.EnqueueCommandResponseMessage(saslLastStepResponse); } Exception exception; if (async) { exception = Record.Exception( () => subject.AuthenticateAsync(connection, connection.Description, CancellationToken.None) .GetAwaiter().GetResult()); } else { exception = Record.Exception( () => subject.Authenticate(connection, connection.Description, CancellationToken.None)); } exception.Should().BeNull(); var expectedSentMessageCount = 3 - (useLongAuthentication ? 0 : 1) - (useSpeculativeAuthenticate ? 1 : 0); SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse(@$ " {{ opcode : 'opmsg', requestId : {actualRequestIds[0]},
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useSpeculativeAuthenticate, [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator("fyko+d2lbbFgONRv9qkxdawL"); var subject = new ScramSha1Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>( RawBsonDocumentHelper.FromJson("{ conversationId : 1, payload : BinData(0,'cj1meWtvK2QybGJiRmdPTlJ2OXFreGRhd0xIbytWZ2s3cXZVT0tVd3VXTElXZzRsLzlTcmFHTUhFRSxzPXJROVpZM01udEJldVAzRTFURFZDNHc9PSxpPTEwMDAw'), done : false, ok : 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,'dj1VTVdlSTI1SkQxeU5ZWlJNcFo0Vkh2aFo5ZTA9')," + $" done : {new BsonBoolean(!useLongAuthentication)}, " + @" ok : 1}")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1, payload : BinData(0,''), done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var helloResult = (BsonDocument)__descriptionQueryWireProtocol.HelloResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { helloResult.Add("speculativeAuthenticate", saslStartReply.Documents[0].ToBsonDocument()); } /* set buildInfoResult to 3.4 to force authenticator to use Query Message Wire Protocol because MockConnection * does not support OP_MSG */ connection.Description = new ConnectionDescription( __descriptionQueryWireProtocol.ConnectionId, new HelloResult(helloResult), new BuildInfoResult(new BsonDocument("version", "3.4"))); BsonDocument helloCommand = null; if (useSpeculativeAuthenticate) { // Call CustomizeInitialHelloCommand so that the authenticator thinks its started to speculatively // authenticate helloCommand = subject.CustomizeInitialHelloCommand(new BsonDocument { { OppressiveLanguageConstants.LegacyHelloCommandName, 1 } }); } else { connection.EnqueueReplyMessage(saslStartReply); } connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } Exception exception; if (async) { exception = Record.Exception( () => subject.AuthenticateAsync(connection, connection.Description, CancellationToken.None) .GetAwaiter().GetResult()); } else { exception = Record.Exception( () => subject.Authenticate(connection, connection.Description, CancellationToken.None)); } exception.Should().BeNull(); var expectedSentMessageCount = 3 - (useLongAuthentication ? 0 : 1) - (useSpeculativeAuthenticate ? 1 : 0); SpinWait.SpinUntil( () => connection.GetSentMessages().Count >= expectedSentMessageCount, TimeSpan.FromSeconds(5) ).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(expectedSentMessageCount); var actualRequestIds = sentMessages.Select(m => m["requestId"].AsInt32).ToList(); var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {actualRequestIds[0]}, " + @" database : 'source', collection : '$cmd', batchSize : -1, secondaryOk : true, query : { saslStart : 1, mechanism : 'SCRAM-SHA-1'," + $" payload : new BinData(0, 'biwsbj11c2VyLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdM')" + @" options : { skipEmptyExchange: true }}}"); if (!useSpeculativeAuthenticate) { expectedMessages.Add(saslStartMessage); } var saslContinueMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[0] : actualRequestIds[1])}," + @" database : 'source', collection : '$cmd', batchSize : -1, secondaryOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, 'Yz1iaXdzLHI9ZnlrbytkMmxiYkZnT05Sdjlxa3hkYXdMSG8rVmdrN3F2VU9LVXd1V0xJV2c0bC85U3JhR01IRUUscD1NQzJUOEJ2Ym1XUmNrRHc4b1dsNUlWZ2h3Q1k9')}}}}"); expectedMessages.Add(saslContinueMessage); if (useLongAuthentication) { var saslOptionalFinalMessage = BsonDocument.Parse( @"{opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[1] : actualRequestIds[2])}," + @" database : 'source', collection : '$cmd', batchSize : -1, secondaryOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, '')}}}}"); expectedMessages.Add(saslOptionalFinalMessage); } sentMessages.Should().Equal(expectedMessages); if (useSpeculativeAuthenticate) { helloCommand.Should().Contain("speculativeAuthenticate"); var speculativeAuthenticateDocument = helloCommand["speculativeAuthenticate"].AsBsonDocument; var expectedSpeculativeAuthenticateDocument = saslStartMessage["query"].AsBsonDocument.Add("db", __credential.Source); speculativeAuthenticateDocument.Should().Be(expectedSpeculativeAuthenticateDocument); } }