Skip to content

Instantly share code, notes, and snippets.

@yallie
Created February 15, 2019 22:23
Show Gist options
  • Save yallie/e912f47042eede8cdbde31d35d45418f to your computer and use it in GitHub Desktop.
Save yallie/e912f47042eede8cdbde31d35d45418f to your computer and use it in GitHub Desktop.
Zyan example: two-factor authentication process
// csc test.cs /r:Zyan.Communication.dll /debug
using System;
using System.Runtime.Serialization;
using System.Security;
using System.Text;
using System.Threading;
using Zyan.Communication;
using Zyan.Communication.Protocols.Tcp;
using Zyan.Communication.Security;
using Zyan.Communication.Security.Exceptions;
class Program
{
static void Main(string[] args)
{
try
{
RunServer();
}
catch // port already taken
{
RunClient();
}
}
static void RunClient()
{
// prepare credentials
var credentials = new MyCredentials();
Console.Write("User name: ");
credentials.UserName = Console.ReadLine();
Console.Write("Password: ");
credentials.Password = Console.ReadLine();
// establish connection
var protocol = new TcpDuplexClientProtocolSetup(true);
using (var conn = new ZyanConnection("tcpex://localhost:1234/RandomStringGenerator", protocol, credentials, true, true))
{
Console.WriteLine("\nConnected!\nPress Ctrl+C to exit.\n");
var proxy = conn.CreateProxy<ISampleService>();
while (true)
{
Console.WriteLine("Server sends: {0}", proxy.GetRandomString());
}
}
}
static void RunServer()
{
var auth = new MyAuthProvider();
var protocol = new TcpDuplexServerProtocolSetup(1234, auth, true);
using (var host = new ZyanComponentHost("RandomStringGenerator", protocol))
{
host.RegisterComponent<ISampleService, SampleService>();
Console.WriteLine("Server started. Press Enter to exit.");
Console.ReadLine();
}
}
}
public interface ISampleService
{
string GetRandomString();
}
class MyCredentials : AuthCredentials
{
public override void Authenticate(Guid sessionId, IZyanDispatcher dispatcher)
{
const int MAX_RETRIES = 3;
for (var i = 0; i < MAX_RETRIES; i++)
{
// ask for 2fa code
Console.Write("SMS code: ");
CredentialsHashtable["Code"] = Console.ReadLine();
// try to log on
var response = dispatcher.Logon(sessionId, CredentialsHashtable);
if (response.Completed && response.Success)
{
return;
}
}
throw new Exception("Too bad, wrong code was specified");
}
}
class MyAuthProvider : IAuthenticationProvider
{
public AuthResponseMessage Authenticate(AuthRequestMessage authRequest)
{
var login = authRequest.Credentials[AuthRequestMessage.CREDENTIAL_USERNAME] as string;
var password = authRequest.Credentials[AuthRequestMessage.CREDENTIAL_PASSWORD] as string;
var code = authRequest.Credentials["Code"] as string;
if (code == null)
{
return HandleStep1(login, password);
}
return HandleStep2(login, password, code);
}
private AuthResponseMessage HandleStep1(string login, string password)
{
if (login == "hacker" && password == "secret")
{
// TODO: generate 2fa code, save it, send SMS to a user, etc
return new AuthResponseMessage
{
Success = true,
Completed = false // second step is pending
};
}
return new AuthResponseMessage
{
Success = false,
Exception = new AccountNotFoundException()
};
}
private AuthResponseMessage HandleStep2(string login, string password, string code)
{
if (login == "hacker" && password == "secret")
{
return new AuthResponseMessage
{
Success = true,
Completed = code == "1234"
};
}
return new AuthResponseMessage
{
Success = false,
Exception = new AccountNotFoundException()
};
}
}
public class SampleService : ISampleService
{
Random rnd = new Random();
const string AvailableChars = "abcdefghijklmnopqrstuvwxyz0123456789";
public string GetRandomString()
{
var count = 3 + rnd.Next(10);
var sb = new StringBuilder();
for (var i = 0; i < count; i++)
{
var c = AvailableChars[rnd.Next(AvailableChars.Length)];
sb.Append(c);
}
Thread.Sleep(rnd.Next(1000));
return sb.ToString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment