public void Authenticate_should_throw_when_server_provides_invalid_r_value( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator); var poisonedSaslStart = PoisonSaslMessage(message: __clientRequest1, poison: "bluePill"); var poisonedSaslStartReply = CreateSaslStartReply(poisonedSaslStart, _serverNonce, _serverSalt, _iterationCount); var poisonedSaslStartReplyMessage = MessageHelper.BuildReply(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, " + $" payload: BinData(0,\"{ToUtf8Base64(poisonedSaslStartReply)}\")," + @" done: false, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(poisonedSaslStartReplyMessage); var act = async ? () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult() : (Action)(() => subject.Authenticate(connection, __description, CancellationToken.None)); var exception = Record.Exception(act); exception.Should().BeOfType <MongoAuthenticationException>(); }
public void Authenticate_should_throw_an_AuthenticationException_when_authentication_fails( [Values("MongoConnectionException", "MongoNotPrimaryException")] string exceptionName, [Values(false, true)] bool async) { var subject = new ScramSha256Authenticator(__credential, serverApi: null); var responseException = CoreExceptionHelper.CreateException(exceptionName); var connection = new MockConnection(__serverId); connection.EnqueueCommandResponseMessage(responseException); connection.Description = __descriptionCommandWireProtocol; Exception exception; if (async) { exception = Record.Exception(() => subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None).GetAwaiter().GetResult()); } else { exception = Record.Exception(() => subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None)); } exception.Should().BeOfType <MongoAuthenticationException>(); }
public void Authenticate_should_send_serverApi_with_command_wire_protocol_if_serverApi_is_provided( [Values(false, true)] bool useServerApi, [Values(false, true)] bool async) { var serverApi = useServerApi ? new ServerApi(ServerApiVersion.V1, true, true) : null; var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi); var connection = new MockConnection(__serverId); var saslStartReply = RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}'), done : false, ok : 1 }}"); var saslContinueReply = RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}'), done : true, ok : 1}}"); if (useServerApi) { connection.EnqueueCommandResponseMessage(MessageHelper.BuildCommandResponse(saslStartReply)); connection.EnqueueCommandResponseMessage(MessageHelper.BuildCommandResponse(saslContinueReply)); } else { connection.EnqueueReplyMessage(MessageHelper.BuildReply(saslStartReply)); connection.EnqueueReplyMessage(MessageHelper.BuildReply(saslContinueReply)); } connection.Description = __descriptionQueryWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionQueryWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { subject.Authenticate(connection, __descriptionQueryWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; if (useServerApi) { sentMessages[0].Should().Be($"{{opcode : \"opmsg\", requestId : {actualRequestId0}, responseTo : 0, sections : [{{ payloadType : 0, document : {{ saslStart : 1, mechanism : \"SCRAM-SHA-256\", payload : new BinData(0, \"biwsbj11c2VyLHI9ck9wck5HZndFYmVSV2diTkVrcU8=\"), options : {{ skipEmptyExchange : true }}, \"$db\" : \"source\", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true }} }}]}}"); sentMessages[1].Should().Be($"{{opcode : \"opmsg\", requestId : {actualRequestId1}, responseTo : 0, sections : [{{ payloadType : 0, document : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"Yz1iaXdzLHI9ck9wck5HZndFYmVSV2diTkVrcU8laHZZRHBXVWEyUmFUQ0FmdXhGSWxqKWhObEYkazAscD1kSHpiWmFwV0lrNGpVaE4rVXRlOXl0YWc5empmTUhnc3FtbWl6N0FuZFZRPQ==\"), \"$db\" : \"source\", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true }} }}]}}"); } else { sentMessages[0].Should().Be($"{{ opcode : \"query\", requestId : {actualRequestId0}, database : \"source\", collection : \"$cmd\", batchSize : -1, slaveOk : true, query : {{ saslStart : 1, mechanism : \"SCRAM-SHA-256\", payload : new BinData(0, \"{ToUtf8Base64(__clientRequest1)}\"), options : {{ \"skipEmptyExchange\" : true }} }} }}"); sentMessages[1].Should().Be($"{{ opcode : \"query\", requestId : {actualRequestId1}, database : \"source\", collection : \"$cmd\", batchSize : -1, slaveOk : true, query : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\") }} }}"); } }
private static void Authenticate( ScramSha256Authenticator authenticator, IConnection connection, ConnectionDescription description, bool async) { if (async) { authenticator.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } authenticator.Authenticate(connection, __description, CancellationToken.None); }
private static void Authenticate( ScramSha256Authenticator authenticator, IConnection connection, bool async) { if (async) { authenticator .AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None) .GetAwaiter() .GetResult(); } else { authenticator.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } }
public void Authenticate_should_throw_an_AuthenticationException_when_authentication_fails( [Values(false, true)] bool async) { var subject = new ScramSha256Authenticator(__credential); var reply = MessageHelper.BuildNoDocumentsReturnedReply <RawBsonDocument>(); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(reply); var act = async ? () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult() : (Action)(() => subject.Authenticate(connection, __description, CancellationToken.None)); var exception = Record.Exception(act); exception.Should().BeOfType <MongoAuthenticationException>(); }
public void Authenticate_should_use_cache( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse1)}\")," + @" done: false, ok: 1}")); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse2)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueCommandResponseMessage(saslStartResponse); connection.EnqueueCommandResponseMessage(saslContinueResponse); connection.Description = __descriptionCommandWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None) .GetAwaiter() .GetResult(); } else { subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)) .Should() .BeTrue(); subject._cache().Should().NotBe(null); subject._cache()._cacheKey().Should().NotBe(null); subject._cache()._cachedEntry().Should().NotBe(null); }
public void Authenticate_should_send_serverApi_with_command_wire_protocol( [Values(false, true)] bool useServerApi, [Values(false, true)] bool async) { var serverApi = useServerApi ? new ServerApi(ServerApiVersion.V1, true, true) : null; var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi); var connection = new MockConnection(__serverId); var saslStartResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}'), done : false, ok : 1 }}")); connection.EnqueueCommandResponseMessage(saslStartResponse); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson($"{{ conversationId : 1, payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}'), done : true, ok : 1}}")); connection.EnqueueCommandResponseMessage(saslContinueResponse); connection.Description = __descriptionCommandWireProtocol; if (async) { subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; var expectedServerApiString = useServerApi ? ", apiVersion : \"1\", apiStrict : true, apiDeprecationErrors : true" : ""; sentMessages[0].Should().Be($"{{ opcode : \"opmsg\", requestId : {actualRequestId0}, responseTo : 0, sections : [ {{ payloadType : 0, document : {{ saslStart : 1, mechanism : \"SCRAM-SHA-256\", payload : new BinData(0, \"{ToUtf8Base64(__clientRequest1)}\"), options : {{ \"skipEmptyExchange\" : true }}, $db : \"source\"{expectedServerApiString} }} }} ] }}"); sentMessages[1].Should().Be($"{{ opcode : \"opmsg\", requestId : {actualRequestId1}, responseTo : 0, sections : [ {{ payloadType : 0, document : {{ saslContinue : 1, conversationId : 1, payload : new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\"), $db : \"source\"{expectedServerApiString} }} }} ] }}"); }
public void Authenticate_should_throw_when_server_provides_invalid_serverSignature( [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartReply = CreateSaslStartReply(__clientRequest1, _serverNonce, _serverSalt, _iterationCount); var poisonedSaslContinueReply = PoisonSaslMessage(message: __serverResponse2, poison: "redApple"); var saslStartResponseMessage = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, " + $" payload: BinData(0,\"{ToUtf8Base64(saslStartReply)}\")," + @" done: false, ok: 1}")); var poisonedSaslContinueResponseMessage = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{conversationId: 1, " + $" payload: BinData(0,\"{ToUtf8Base64(poisonedSaslContinueReply)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueCommandResponseMessage(saslStartResponseMessage); connection.EnqueueCommandResponseMessage(poisonedSaslContinueResponseMessage); connection.Description = __descriptionCommandWireProtocol; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __descriptionCommandWireProtocol, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __descriptionCommandWireProtocol, CancellationToken.None); } var exception = Record.Exception(act); exception.Should().BeOfType <MongoAuthenticationException>(); }
public void Authenticate_should_not_throw_when_authentication_succeeds( [Values(false, true)] bool useLongAuthentication, [Values(false, true)] bool async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse1)}\")," + @" done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverResponse2)}\")," + $" done: {new BsonBoolean(!useLongAuthentication)}," + @" ok: 1}")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(__serverOptionalFinalResponse)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __description, CancellationToken.None); } var exception = Record.Exception(act); exception.Should().BeNull(); var expectedSentMessageCount = useLongAuthentication ? 3 : 2; 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(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } sentMessages[0].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[0]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslStart: 1, mechanism: ""SCRAM-SHA-256""," + $" payload: new BinData(0, \"{ToUtf8Base64(__clientRequest1)}\")" + @" options: { skipEmptyExchange: true }}}"); sentMessages[1].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[1]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\")}}}}"); if (useLongAuthentication) { sentMessages[2].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestIds[2]}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"{ToUtf8Base64(__clientOptionalFinalRequest)}\")}}}}"); } }
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(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}')," + @" done : false, ok : 1 }")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}')," + $" done : {new BsonBoolean(!useLongAuthentication)}," + @" ok : 1 }")); var saslLastStepReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverOptionalFinalResponse)}')," + @" done : true, ok : 1 }")); var connection = new MockConnection(__serverId); var isMasterResult = (BsonDocument)__descriptionQueryWireProtocol.IsMasterResult.Wrapped.Clone(); if (useSpeculativeAuthenticate) { isMasterResult.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 IsMasterResult(isMasterResult), new BuildInfoResult(new BsonDocument("version", "3.4"))); BsonDocument isMasterCommand = null; if (useSpeculativeAuthenticate) { // We must call CustomizeIsMasterCommand so that the authenticator thinks its started to speculatively // authenticate isMasterCommand = subject.CustomizeInitialIsMasterCommand(new BsonDocument { { "isMaster", 1 } }); } else { connection.EnqueueReplyMessage(saslStartReply); } connection.EnqueueReplyMessage(saslContinueReply); if (useLongAuthentication) { connection.EnqueueReplyMessage(saslLastStepReply); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; 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(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } var expectedMessages = new List <BsonDocument>(); var saslStartMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {actualRequestIds[0]}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslStart : 1, mechanism : 'SCRAM-SHA-256'," + $" payload : new BinData(0, '{ToUtf8Base64(__clientRequest1)}')" + @" 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, slaveOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, \"{ToUtf8Base64(__clientRequest2)}\")}}}}"); expectedMessages.Add(saslContinueMessage); if (useLongAuthentication) { var saslOptionalFinalMessage = BsonDocument.Parse( @"{ opcode : 'query'," + $" requestId : {(useSpeculativeAuthenticate ? actualRequestIds[1] : actualRequestIds[2])}," + @" database : 'source', collection : '$cmd', batchSize : -1, slaveOk : true, query : { saslContinue : 1, conversationId : 1, " + $" payload : new BinData(0, '{ToUtf8Base64(__clientOptionalFinalRequest)}')}}}}"); expectedMessages.Add(saslOptionalFinalMessage); } sentMessages.Should().Equal(expectedMessages); if (useSpeculativeAuthenticate) { isMasterCommand.Should().Contain("speculativeAuthenticate"); var speculativeAuthenticateDocument = isMasterCommand["speculativeAuthenticate"].AsBsonDocument; var expectedSpeculativeAuthenticateDocument = saslStartMessage["query"].AsBsonDocument.Add("db", __credential.Source); speculativeAuthenticateDocument.Should().Be(expectedSpeculativeAuthenticateDocument); } }
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(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator, serverApi: null); var saslStartResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse1)}')," + @" done : false, ok : 1 }")); var saslContinueResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverResponse2)}')," + $" done : {new BsonBoolean(!useLongAuthentication)}," + @" ok : 1 }")); var saslLastStepResponse = MessageHelper.BuildCommandResponse(RawBsonDocumentHelper.FromJson( @"{ conversationId : 1," + $" payload : BinData(0,'{ToUtf8Base64(__serverOptionalFinalResponse)}')," + @" 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) { // We must 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); } var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; 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(); for (var i = 0; i != actualRequestIds.Count; ++i) { actualRequestIds[i].Should().BeInRange(expectedRequestId + i, expectedRequestId + 10 + i); } 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 async) { var randomStringGenerator = new ConstantRandomStringGenerator(_clientNonce); var subject = new ScramSha256Authenticator(__credential, randomStringGenerator); var saslStartReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(_serverResponse1)}\")," + @" done: false, ok: 1}")); var saslContinueReply = MessageHelper.BuildReply <RawBsonDocument>(RawBsonDocumentHelper.FromJson( @"{conversationId: 1," + $" payload: BinData(0,\"{ToUtf8Base64(_serverReponse2)}\")," + @" done: true, ok: 1}")); var connection = new MockConnection(__serverId); connection.EnqueueReplyMessage(saslStartReply); connection.EnqueueReplyMessage(saslContinueReply); var expectedRequestId = RequestMessage.CurrentGlobalRequestId + 1; Action act; if (async) { act = () => subject.AuthenticateAsync(connection, __description, CancellationToken.None).GetAwaiter().GetResult(); } else { act = () => subject.Authenticate(connection, __description, CancellationToken.None); } var exception = Record.Exception(act); exception.Should().BeNull(); SpinWait.SpinUntil(() => connection.GetSentMessages().Count >= 2, TimeSpan.FromSeconds(5)).Should().BeTrue(); var sentMessages = MessageHelper.TranslateMessagesToBsonDocuments(connection.GetSentMessages()); sentMessages.Count.Should().Be(2); var actualRequestId0 = sentMessages[0]["requestId"].AsInt32; var actualRequestId1 = sentMessages[1]["requestId"].AsInt32; actualRequestId0.Should().BeInRange(expectedRequestId, expectedRequestId + 10); actualRequestId1.Should().BeInRange(actualRequestId0 + 1, actualRequestId0 + 11); sentMessages[0].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestId0}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslStart: 1, mechanism: ""SCRAM-SHA-256""," + $" payload: new BinData(0, \"{ToUtf8Base64(_clientRequest1)}\")}}}}"); sentMessages[1].Should().Be( @"{opcode: ""query""," + $" requestId: {actualRequestId1}," + @" database: ""source"", collection: ""$cmd"", batchSize: -1, slaveOk: true, query: {saslContinue: 1, conversationId: 1, " + $" payload: new BinData(0, \"{ToUtf8Base64(_clientRequest2)}\")}}}}"); }