Skip to content

Commit 32aaae4

Browse files
committed
Add DataProtection to the AuthenticationManager to store user and password in secure way
#95
1 parent 3d652c8 commit 32aaae4

3 files changed

Lines changed: 97 additions & 8 deletions

File tree

src/FlowCtl.Infrastructure/Extensions/ServiceCollectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public static class ServiceCollectionExtensions
1515
{
1616
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
1717
{
18+
services.AddDataProtection();
1819
services
1920
.AddSingleton(new GitHubClient(new ProductHeaderValue("flowsynx")))
2021
.AddSingleton<IGitHubReleaseManager, GitHubReleaseManager>()

src/FlowCtl.Infrastructure/FlowCtl.Infrastructure.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
</ItemGroup>
1818

1919
<ItemGroup>
20-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.3" />
20+
<PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="9.0.4" />
21+
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="9.0.4" />
22+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
2123
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
2224
<PackageReference Include="Octokit" Version="14.0.0" />
2325
<PackageReference Include="SharpCompress" Version="0.39.0" />

src/FlowCtl.Infrastructure/Services/Authentication/AuthenticationManager.cs

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using FlowCtl.Core.Serialization;
22
using FlowCtl.Core.Services.Authentication;
3+
using Microsoft.AspNetCore.DataProtection;
34

45
namespace FlowCtl.Infrastructure.Services.Authentication;
56

@@ -8,27 +9,32 @@ public class AuthenticationManager : IAuthenticationManager
89
private const string ConfigPath = "config.json";
910
private readonly IJsonSerializer _jsonSerializer;
1011
private readonly IJsonDeserializer _jsonDeserializer;
12+
private readonly IDataProtector _protector;
1113

12-
public AuthenticationManager(IJsonSerializer jsonSerializer, IJsonDeserializer jsonDeserializer)
14+
public AuthenticationManager(
15+
IJsonSerializer jsonSerializer,
16+
IJsonDeserializer jsonDeserializer,
17+
IDataProtectionProvider dataProtectionProvider)
1318
{
1419
_jsonSerializer = jsonSerializer;
1520
_jsonDeserializer = jsonDeserializer;
21+
_protector = dataProtectionProvider.CreateProtector("AuthenticationManager.Protector");
1622
}
1723

1824
public bool IsLoggedIn => File.Exists(ConfigPath) && Load() is { } data && (
1925
data.Type == AuthenticationType.Basic || data.Expiry is null || data.Expiry > DateTime.UtcNow
2026
);
2127

22-
public bool IsBasicAuthenticationUsed => File.Exists(ConfigPath) && Load() is { } data &&
28+
public bool IsBasicAuthenticationUsed => File.Exists(ConfigPath) && Load() is { } data &&
2329
data.Type == AuthenticationType.Basic;
2430

2531
public AuthenticationData LoginBasic(string username, string password)
2632
{
2733
var data = new AuthenticationData
2834
{
2935
Type = AuthenticationType.Basic,
30-
Username = username,
31-
Password = password
36+
Username = _protector.Protect(username),
37+
Password = _protector.Protect(password) // Encrypt password
3238
};
3339
Save(data);
3440
return data;
@@ -39,7 +45,7 @@ public AuthenticationData LoginBearer(string token)
3945
var data = new AuthenticationData
4046
{
4147
Type = AuthenticationType.Bearer,
42-
AccessToken = token,
48+
AccessToken = _protector.Protect(token), // Encrypt token
4349
Expiry = DateTime.UtcNow.AddHours(1)
4450
};
4551
Save(data);
@@ -48,7 +54,21 @@ public AuthenticationData LoginBearer(string token)
4854

4955
public AuthenticationData? GetData()
5056
{
51-
return Load();
57+
var data = Load();
58+
59+
if (data != null)
60+
{
61+
if (data.Username != null)
62+
data.Username = _protector.Unprotect(data.Username);
63+
64+
if (data?.Type == AuthenticationType.Basic && data.Password != null)
65+
data.Password = _protector.Unprotect(data.Password);
66+
67+
if (data?.Type == AuthenticationType.Bearer && data.AccessToken != null)
68+
data.AccessToken = _protector.Unprotect(data.AccessToken);
69+
}
70+
71+
return data;
5272
}
5373

5474
public void Logout()
@@ -66,4 +86,70 @@ private void Save(AuthenticationData data)
6686
{
6787
File.WriteAllText(ConfigPath, _jsonSerializer.Serialize(data));
6888
}
69-
}
89+
}
90+
91+
92+
//public class AuthenticationManager : IAuthenticationManager
93+
//{
94+
// private const string ConfigPath = "config.json";
95+
// private readonly IJsonSerializer _jsonSerializer;
96+
// private readonly IJsonDeserializer _jsonDeserializer;
97+
98+
// public AuthenticationManager(IJsonSerializer jsonSerializer, IJsonDeserializer jsonDeserializer)
99+
// {
100+
// _jsonSerializer = jsonSerializer;
101+
// _jsonDeserializer = jsonDeserializer;
102+
// }
103+
104+
// public bool IsLoggedIn => File.Exists(ConfigPath) && Load() is { } data && (
105+
// data.Type == AuthenticationType.Basic || data.Expiry is null || data.Expiry > DateTime.UtcNow
106+
// );
107+
108+
// public bool IsBasicAuthenticationUsed => File.Exists(ConfigPath) && Load() is { } data &&
109+
// data.Type == AuthenticationType.Basic;
110+
111+
// public AuthenticationData LoginBasic(string username, string password)
112+
// {
113+
// var data = new AuthenticationData
114+
// {
115+
// Type = AuthenticationType.Basic,
116+
// Username = username,
117+
// Password = password
118+
// };
119+
// Save(data);
120+
// return data;
121+
// }
122+
123+
// public AuthenticationData LoginBearer(string token)
124+
// {
125+
// var data = new AuthenticationData
126+
// {
127+
// Type = AuthenticationType.Bearer,
128+
// AccessToken = token,
129+
// Expiry = DateTime.UtcNow.AddHours(1)
130+
// };
131+
// Save(data);
132+
// return data;
133+
// }
134+
135+
// public AuthenticationData? GetData()
136+
// {
137+
// return Load();
138+
// }
139+
140+
// public void Logout()
141+
// {
142+
// if (File.Exists(ConfigPath)) File.Delete(ConfigPath);
143+
// }
144+
145+
// private AuthenticationData? Load()
146+
// {
147+
// if (!File.Exists(ConfigPath)) return null;
148+
// return _jsonDeserializer.Deserialize<AuthenticationData>(File.ReadAllText(ConfigPath));
149+
// }
150+
151+
// private void Save(AuthenticationData data)
152+
// {
153+
// File.WriteAllText(ConfigPath, _jsonSerializer.Serialize(data));
154+
// }
155+
//}

0 commit comments

Comments
 (0)