public override State Advance(TwoFactorAuth owner) { var validAnswers = new[] { Ui.Answer.Check, Ui.Answer.Resend, Ui.Answer.Email }; var answer = owner._ui.AskToWaitForOob(owner._settings.Devices[_deviceIndex].Name, owner._settings.Email, validAnswers); switch (answer) { case Ui.Answer.Check: return(Check(owner)); case Ui.Answer.Resend: Client.AuthSendPush(owner._clientInfo, owner._settings.Devices[_deviceIndex].Id, owner._settings.TransactionId, owner._rest); return(this); case Ui.Answer.Email: Client.AuthSendEmail(owner._clientInfo, owner._settings.Email, owner._settings.TransactionId, owner._rest); return(new WaitForEmail()); } throw new InternalErrorException($"Invalid answer '{answer}'"); }
public override State Advance(TwoFactorAuth owner) { var names = owner._settings.Devices.Select(i => i.Name).ToArray(); var validAnswers = Enumerable.Range(0, owner._settings.Devices.Length) .Select(i => Ui.Answer.Device0 + i) .Concat(new[] { Ui.Answer.Email }) .ToArray(); var answer = owner._ui.AskToChooseOob(names, owner._settings.Email, validAnswers); if (answer == Ui.Answer.Email) { Client.AuthSendEmail(owner._clientInfo, owner._settings.Email, owner._settings.TransactionId, owner._rest); return(new WaitForEmail()); } var deviceIndex = answer - Ui.Answer.Device0; if (deviceIndex >= 0 && deviceIndex < owner._settings.Devices.Length) { Client.AuthSendPush(owner._clientInfo, owner._settings.Devices[deviceIndex].Id, owner._settings.TransactionId, owner._rest); return(new WaitForOob(deviceIndex)); } throw new InternalErrorException($"Invalid answer '{answer}'"); }
// TODO: Shared code for most states. It's not really good that it's in the base class. protected State Check(TwoFactorAuth owner) { var result = Client.AuthCheck(owner._clientInfo, owner._settings.TransactionId, owner._rest); return(new Done(result)); }
public override State Advance(TwoFactorAuth owner) { Client.AuthSendPush(owner._clientInfo, owner._settings.Devices[_deviceIndex].Id, owner._settings.TransactionId, owner._rest); return(new WaitForOob(_deviceIndex)); }
public override State Advance(TwoFactorAuth owner) { Client.AuthSendEmail(owner._clientInfo, owner._settings.Email, owner._settings.TransactionId, owner._rest); return(new WaitForEmail()); }
// TODO: Shared code for most states. It's not really good that it's in the base class. protected State Check(TwoFactorAuth owner) { var result = Client.AuthCheck(owner._clientInfo, owner._settings.TransactionId, owner._rest); if (result == null) { return(new Failure("Failed")); } return(new Done(result)); }
public override State Advance(TwoFactorAuth owner) => throw new NotImplementedException();
public abstract State Advance(TwoFactorAuth owner);
public virtual State Advance(TwoFactorAuth owner) { throw new InternalErrorException("Unreachable code"); }
public static Account[] OpenVault(string username, string password, Ui ui, ISecureStorage storage, IRestTransport transport) { var rest = new RestClient(transport); // Step 1: Register a new deice or use the existing one from the previous run. var deviceInfo = LoadDeviceInfo(storage) ?? RegisterNewDevice("truekey-sharp", rest); // Step 2: Parse the token to decode OTP information. var otpInfo = Util.ParseClientToken(deviceInfo.Token); // Step 3: Validate the OTP info to make sure it's got only the // things we support at the moment. Util.ValidateOtpInfo(otpInfo); // Store the token and ID for the next time. StoreDeviceInfo(deviceInfo, storage); // Bundle up everything in one place var clientInfo = new ClientInfo(username, "truekey-sharp", deviceInfo, otpInfo); // Step 4: Auth step 1 gives us a transaction id to pass along to the next step. var transactionId = AuthStep1(clientInfo, rest); // Step 5: Auth step 2 gives us the instructions on what to do next. For a new client that // would be some form of second factor auth. For a known client that would be a // pair of OAuth tokens. var whatsNext = AuthStep2(clientInfo, password, transactionId, rest); // The device is trusted if it's already authenticated at this point and // no second factor is needed. var isTrusted = whatsNext.IsAuthenticated; // Step 6: Auth FSM -- walk through all the auth steps until we're done. var oauthToken = TwoFactorAuth.Start(clientInfo, whatsNext, ui, rest); // Step 7: Save this device as trusted not to repeat the two factor dance next times. if (!isTrusted) { SaveDeviceAsTrusted(clientInfo, transactionId, oauthToken, rest); } // Step 8: Get the vault from the server. var encryptedVault = GetVault(oauthToken, rest); // Step 9: Compute the master key. var masterKey = Util.DecryptMasterKey(password, encryptedVault.MasterKeySalt, encryptedVault.EncryptedMasterKey); // Step 10: Decrypt the accounts. var accounts = encryptedVault .EncryptedAccounts .Select(i => new Account(id: i.Id, name: i.Name, username: i.Username, password: Util.Decrypt(masterKey, i.EncryptedPassword).ToUtf8(), url: i.Url, note: Util.Decrypt(masterKey, i.EncryptedNote).ToUtf8())) .ToArray(); return(accounts); }