Created
February 15, 2019 22:23
-
-
Save yallie/e912f47042eede8cdbde31d35d45418f to your computer and use it in GitHub Desktop.
Zyan example: two-factor authentication process
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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