1
0
mirror of https://github.com/bitwarden/directory-connector synced 2025-12-15 07:43:27 +00:00

login, logout, setting fixes

This commit is contained in:
Kyle Spearrin
2017-05-12 12:29:39 -04:00
parent 87eeaf2ae7
commit 711e91045b
3 changed files with 131 additions and 85 deletions

View File

@@ -1,4 +1,5 @@
using System; using Bit.Core.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security; using System.Security;
@@ -38,6 +39,7 @@ namespace Bit.Console
Con.WriteLine("Main Menu"); Con.WriteLine("Main Menu");
Con.WriteLine("================================="); Con.WriteLine("=================================");
Con.WriteLine("1. Log in to bitwarden"); Con.WriteLine("1. Log in to bitwarden");
Con.WriteLine("2. Log out");
Con.WriteLine("2. Configure directory connection"); Con.WriteLine("2. Configure directory connection");
Con.WriteLine("3. Sync directory"); Con.WriteLine("3. Sync directory");
Con.WriteLine("4. Start/stop background service"); Con.WriteLine("4. Start/stop background service");
@@ -56,20 +58,21 @@ namespace Bit.Console
await LogInAsync(); await LogInAsync();
break; break;
case "2": case "2":
case "logout":
case "signout":
await LogOutAsync();
break;
case "dir": case "dir":
case "directory": case "directory":
await DirectoryAsync();
break; break;
case "3":
case "sync": case "sync":
break; break;
case "4":
case "svc": case "svc":
case "service": case "service":
break; break;
case "5":
case "exit": case "exit":
case "quit": case "quit":
case "q": case "q":
@@ -96,20 +99,28 @@ namespace Bit.Console
private static async Task LogInAsync() private static async Task LogInAsync()
{ {
if(Core.Services.AuthService.Instance.Authenticated)
{
Con.WriteLine("You are already logged in as {0}.", Core.Services.TokenService.Instance.AccessTokenEmail);
return;
}
string email = null; string email = null;
string masterPassword = null; string masterPassword = null;
string token = null;
if(_usingArgs) if(_usingArgs)
{ {
if(_args.Length != 3) var parameters = ParseParameters();
if(parameters.Count >= 2 && parameters.ContainsKey("e") && parameters.ContainsKey("p"))
{ {
Con.ForegroundColor = ConsoleColor.Red; email = parameters["e"];
Con.WriteLine("Invalid arguments."); masterPassword = parameters["p"];
Con.ResetColor(); }
if(parameters.Count == 3 && parameters.ContainsKey("t"))
{
token = parameters["t"];
} }
email = _args[1];
masterPassword = _args[2];
} }
else else
{ {
@@ -119,15 +130,33 @@ namespace Bit.Console
masterPassword = ReadSecureLine(); masterPassword = ReadSecureLine();
} }
var result = await Core.Services.AuthService.Instance.LogInAsync(email, masterPassword); if(string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(masterPassword))
{
Con.WriteLine();
Con.WriteLine();
Con.ForegroundColor = ConsoleColor.Red;
Con.WriteLine("Invalid input parameters.");
Con.ResetColor();
return;
}
if(result.TwoFactorRequired) LoginResult result = null;
if(string.IsNullOrWhiteSpace(token))
{
result = await Core.Services.AuthService.Instance.LogInAsync(email, masterPassword);
}
else
{
result = await Core.Services.AuthService.Instance.LogInTwoFactorAsync(email, masterPassword, token);
}
if(string.IsNullOrWhiteSpace(token) && result.TwoFactorRequired)
{ {
Con.WriteLine(); Con.WriteLine();
Con.WriteLine(); Con.WriteLine();
Con.WriteLine("Two-step login is enabled on this account. Please enter your verification code."); Con.WriteLine("Two-step login is enabled on this account. Please enter your verification code.");
Con.Write("Verification code: "); Con.Write("Verification code: ");
var token = Con.ReadLine().Trim(); token = Con.ReadLine().Trim();
result = await Core.Services.AuthService.Instance.LogInTwoFactorAsync(token, email, result.MasterPasswordHash); result = await Core.Services.AuthService.Instance.LogInTwoFactorAsync(token, email, result.MasterPasswordHash);
} }
@@ -149,6 +178,25 @@ namespace Bit.Console
masterPassword = null; masterPassword = null;
} }
private static Task LogOutAsync()
{
if(Core.Services.AuthService.Instance.Authenticated)
{
Core.Services.AuthService.Instance.LogOut();
Con.WriteLine("You have successfully logged out!");
}
else
{
Con.WriteLine("You are not logged in.");
}
return Task.FromResult(0);
}
private static async Task DirectoryAsync()
{
}
private static string ReadSecureLine() private static string ReadSecureLine()
{ {
var input = string.Empty; var input = string.Empty;
@@ -175,5 +223,21 @@ namespace Bit.Console
} }
return input; return input;
} }
private static IDictionary<string, string> ParseParameters()
{
var dict = new Dictionary<string, string>();
for(int i = 1; i < _args.Length; i = i + 2)
{
if(!_args[i].StartsWith("-"))
{
continue;
}
dict.Add(_args[i].Substring(1), _args[i + 1]);
}
return dict;
}
} }
} }

View File

@@ -29,6 +29,12 @@ namespace Bit.Core.Services
public bool Authenticated => !string.IsNullOrWhiteSpace(TokenService.Instance.AccessToken); public bool Authenticated => !string.IsNullOrWhiteSpace(TokenService.Instance.AccessToken);
public void LogOut()
{
TokenService.Instance.AccessToken = null;
TokenService.Instance.RefreshToken = null;
}
public async Task<LoginResult> LogInAsync(string email, string masterPassword) public async Task<LoginResult> LogInAsync(string email, string masterPassword)
{ {
var normalizedEmail = email.Trim().ToLower(); var normalizedEmail = email.Trim().ToLower();
@@ -65,7 +71,21 @@ namespace Bit.Core.Services
return result; return result;
} }
public async Task<LoginResult> LogInTwoFactorAsync(string token, string email, string masterPasswordHash) public async Task<LoginResult> LogInTwoFactorAsync(string token, string email, string masterPassword)
{
var normalizedEmail = email.Trim().ToLower();
var key = CryptoService.Instance.MakeKeyFromPassword(masterPassword, normalizedEmail);
var result = await LogInTwoFactorWithHashAsync(token, email,
CryptoService.Instance.HashPasswordBase64(key, masterPassword));
key = null;
masterPassword = null;
return result;
}
public async Task<LoginResult> LogInTwoFactorWithHashAsync(string token, string email, string masterPasswordHash)
{ {
var request = new TokenRequest var request = new TokenRequest
{ {

View File

@@ -18,7 +18,7 @@ namespace Bit.Core.Services
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"\\bitwarden\\DirectoryConnector"); "\\bitwarden\\DirectoryConnector");
private IDictionary<string, object> _settings; private SettingsModel _settings;
private SettingsService() { } private SettingsService() { }
@@ -35,7 +35,7 @@ namespace Bit.Core.Services
} }
} }
public IDictionary<string, object> Settings public SettingsModel Settings
{ {
get get
{ {
@@ -47,83 +47,44 @@ namespace Bit.Core.Services
using(var sr = new StreamReader(s, Encoding.UTF8)) using(var sr = new StreamReader(s, Encoding.UTF8))
using(var jsonTextReader = new JsonTextReader(sr)) using(var jsonTextReader = new JsonTextReader(sr))
{ {
_settings = serializer.Deserialize<IDictionary<string, object>>(jsonTextReader); _settings = serializer.Deserialize<SettingsModel>(jsonTextReader);
} }
} }
return _settings == null ? new Dictionary<string, object>() : _settings; return _settings == null ? new SettingsModel() : _settings;
} }
set }
private void SaveSettings()
{
lock(_locker)
{ {
lock(_locker) if(!Directory.Exists(_baseStoragePath))
{ {
if(!Directory.Exists(_baseStoragePath)) Directory.CreateDirectory(_baseStoragePath);
{ }
Directory.CreateDirectory(_baseStoragePath);
}
_settings = value; _settings = Settings;
var filePath = $"{_baseStoragePath}\\settings.json"; var filePath = $"{_baseStoragePath}\\settings.json";
using(var s = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read)) using(var s = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read))
using(var sw = new StreamWriter(s, Encoding.UTF8)) using(var sw = new StreamWriter(s, Encoding.UTF8))
{ {
var json = JsonConvert.SerializeObject(_settings); var json = JsonConvert.SerializeObject(_settings, Formatting.Indented);
sw.Write(json); sw.Write(json);
}
} }
} }
} }
public void Set(string key, object value)
{
if(Contains(key))
{
Settings[key] = value;
}
else
{
Settings.Add(key, value);
}
Settings = Settings;
}
public void Remove(string key)
{
Settings.Remove(key);
Settings = Settings;
}
public bool Contains(string key)
{
return Settings.ContainsKey(key);
}
public T Get<T>(string key)
{
if(Settings.ContainsKey(key))
{
return (T)Settings[key];
}
return default(T);
}
public EncryptedData AccessToken public EncryptedData AccessToken
{ {
get get
{ {
return Get<EncryptedData>("AccessToken"); return Settings.AccessToken;
} }
set set
{ {
if(value == null) Settings.AccessToken = value;
{ SaveSettings();
Remove("AccessTolen");
return;
}
Set("AccessToken", value);
} }
} }
@@ -131,18 +92,19 @@ namespace Bit.Core.Services
{ {
get get
{ {
return Get<EncryptedData>("RefreshToken"); return Settings.RefreshToken;
} }
set set
{ {
if(value == null) Settings.RefreshToken = value;
{ SaveSettings();
Remove("RefreshToken");
return;
}
Set("RefreshToken", value);
} }
} }
public class SettingsModel
{
public EncryptedData AccessToken { get; set; }
public EncryptedData RefreshToken { get; set; }
}
} }
} }