diff --git a/src/VaultSharp/V1/SecretsEngines/TOTP/ITOTPSecretsEngine.cs b/src/VaultSharp/V1/SecretsEngines/TOTP/ITOTPSecretsEngine.cs
index 47376229..4ef05722 100644
--- a/src/VaultSharp/V1/SecretsEngines/TOTP/ITOTPSecretsEngine.cs
+++ b/src/VaultSharp/V1/SecretsEngines/TOTP/ITOTPSecretsEngine.cs
@@ -8,45 +8,6 @@ namespace VaultSharp.V1.SecretsEngines.TOTP
///
public interface ITOTPSecretsEngine
{
- ///
- /// Generates a new time-based one-time use password based on the named key.
- ///
- /// [required]
- /// Specifies the name of the key to create credentials against.
- ///
- /// [optional]
- /// The mount point for the TOTP backend. Defaults to
- /// Provide a value only if you have customized the TOTP mount point.
- ///
- /// [optional]
- /// The TTL for the token and can be either an integer number of seconds or a string duration of seconds.
- ///
- ///
- /// The secret with the as the data.
- ///
- Task> GetCodeAsync(string keyName, string mountPoint = null, string wrapTimeToLive = null);
-
- ///
- /// Generates a new time-based one-time use password based on the named key.
- ///
- /// [required]
- /// Specifies the name of the key to create credentials against.
- ///
- /// [required]
- /// Specifies the the password you want to validate.
- ///
- /// [optional]
- /// The mount point for the TOTP backend. Defaults to
- /// Provide a value only if you have customized the TOTP mount point.
- ///
- /// [optional]
- /// The TTL for the token and can be either an integer number of seconds or a string duration of seconds.
- ///
- ///
- /// The secret with the as the data.
- ///
- Task> ValidateCodeAsync(string keyName, string code, string mountPoint = null, string wrapTimeToLive = null);
-
///
/// This endpoint creates or updates a key definition.
///
@@ -101,5 +62,44 @@ public interface ITOTPSecretsEngine
/// The mount point for the TOTP backend. Defaults to
/// Provide a value only if you have customized the TOTP mount point.
Task DeleteKeyAsync(string keyName, string mountPoint = null);
+
+ ///
+ /// Generates a new time-based one-time use password based on the named key.
+ ///
+ /// [required]
+ /// Specifies the name of the key to create credentials against.
+ ///
+ /// [optional]
+ /// The mount point for the TOTP backend. Defaults to
+ /// Provide a value only if you have customized the TOTP mount point.
+ ///
+ /// [optional]
+ /// The TTL for the token and can be either an integer number of seconds or a string duration of seconds.
+ ///
+ ///
+ /// The secret with the as the data.
+ ///
+ Task> GetCodeAsync(string keyName, string mountPoint = null, string wrapTimeToLive = null);
+
+ ///
+ /// Generates a new time-based one-time use password based on the named key.
+ ///
+ /// [required]
+ /// Specifies the name of the key to create credentials against.
+ ///
+ /// [required]
+ /// Specifies the the password you want to validate.
+ ///
+ /// [optional]
+ /// The mount point for the TOTP backend. Defaults to
+ /// Provide a value only if you have customized the TOTP mount point.
+ ///
+ /// [optional]
+ /// The TTL for the token and can be either an integer number of seconds or a string duration of seconds.
+ ///
+ ///
+ /// The secret with the as the data.
+ ///
+ Task> ValidateCodeAsync(string keyName, string code, string mountPoint = null, string wrapTimeToLive = null);
}
}
\ No newline at end of file
diff --git a/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPKey.cs b/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPKey.cs
index 15dc2a62..c1a8e4a0 100644
--- a/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPKey.cs
+++ b/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPKey.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using Newtonsoft.Json;
+using Newtonsoft.Json;
namespace VaultSharp.V1.SecretsEngines.TOTP
{
@@ -40,6 +37,6 @@ public class TOTPKey
/// create a counter for the TOTP code calculation.
///
[JsonProperty("period")]
- public string Period { get; set; }
+ public long Period { get; set; }
}
}
diff --git a/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPSecretsEngineProvider.cs b/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPSecretsEngineProvider.cs
index 2eff1ad4..4b4e5b7b 100644
--- a/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPSecretsEngineProvider.cs
+++ b/src/VaultSharp/V1/SecretsEngines/TOTP/TOTPSecretsEngineProvider.cs
@@ -14,22 +14,6 @@ public TOTPSecretsEngineProvider(Polymath polymath)
_polymath = polymath;
}
- public async Task> GetCodeAsync(string keyName, string mountPoint = null, string wrapTimeToLive = null)
- {
- Checker.NotNull(keyName, "keyName");
-
- return await _polymath.MakeVaultApiRequest>(mountPoint ?? _polymath.VaultClientSettings.SecretsEngineMountPoints.TOTP, "/code/" + keyName.Trim('/'), HttpMethod.Get, wrapTimeToLive: wrapTimeToLive).ConfigureAwait(_polymath.VaultClientSettings.ContinueAsyncTasksOnCapturedContext);
- }
-
- public async Task> ValidateCodeAsync(string keyName, string code, string mountPoint = null, string wrapTimeToLive = null)
- {
- Checker.NotNull(keyName, "keyName");
- Checker.NotNull(code, "code");
-
- var requestData = new { code = code };
- return await _polymath.MakeVaultApiRequest>(mountPoint ?? _polymath.VaultClientSettings.SecretsEngineMountPoints.TOTP, "/code/" + keyName.Trim('/'), HttpMethod.Post, requestData, wrapTimeToLive: wrapTimeToLive).ConfigureAwait(_polymath.VaultClientSettings.ContinueAsyncTasksOnCapturedContext);
- }
-
public async Task> CreateKeyAsync(string keyName, TOTPCreateKeyRequest createKeyRequest, string mountPoint)
{
Checker.NotNull(keyName, "keyName");
@@ -95,5 +79,21 @@ public async Task DeleteKeyAsync(string keyName, string mountPoint = null)
await _polymath.MakeVaultApiRequest(mountPoint ?? _polymath.VaultClientSettings.SecretsEngineMountPoints.TOTP, "/keys/" + keyName.Trim('/'), HttpMethod.Delete).ConfigureAwait(_polymath.VaultClientSettings.ContinueAsyncTasksOnCapturedContext);
}
+
+ public async Task> GetCodeAsync(string keyName, string mountPoint = null, string wrapTimeToLive = null)
+ {
+ Checker.NotNull(keyName, "keyName");
+
+ return await _polymath.MakeVaultApiRequest>(mountPoint ?? _polymath.VaultClientSettings.SecretsEngineMountPoints.TOTP, "/code/" + keyName.Trim('/'), HttpMethod.Get, wrapTimeToLive: wrapTimeToLive).ConfigureAwait(_polymath.VaultClientSettings.ContinueAsyncTasksOnCapturedContext);
+ }
+
+ public async Task> ValidateCodeAsync(string keyName, string code, string mountPoint = null, string wrapTimeToLive = null)
+ {
+ Checker.NotNull(keyName, "keyName");
+ Checker.NotNull(code, "code");
+
+ var requestData = new { code = code };
+ return await _polymath.MakeVaultApiRequest>(mountPoint ?? _polymath.VaultClientSettings.SecretsEngineMountPoints.TOTP, "/code/" + keyName.Trim('/'), HttpMethod.Post, requestData, wrapTimeToLive: wrapTimeToLive).ConfigureAwait(_polymath.VaultClientSettings.ContinueAsyncTasksOnCapturedContext);
+ }
}
}
\ No newline at end of file
diff --git a/test/VaultSharp.Samples/Backends/Secrets/TOTPSecretsBackendSamples.cs b/test/VaultSharp.Samples/Backends/Secrets/TOTPSecretsBackendSamples.cs
new file mode 100644
index 00000000..866cb560
--- /dev/null
+++ b/test/VaultSharp.Samples/Backends/Secrets/TOTPSecretsBackendSamples.cs
@@ -0,0 +1,110 @@
+using System.Linq;
+using System;
+using Xunit;
+using VaultSharp.V1.SecretsEngines;
+using VaultSharp.V1.SecretsEngines.TOTP;
+
+namespace VaultSharp.Samples
+{
+ partial class Program
+ {
+ private static void RunTOTPSecretsBackendSamples()
+ {
+ var mountPoint = Guid.NewGuid().ToString();
+
+ var totpSecretsEngine = new SecretsEngine
+ {
+ Type = SecretsEngineType.TOTP,
+ Path = mountPoint
+ };
+
+ _authenticatedVaultClient.V1.System.MountSecretBackendAsync(totpSecretsEngine).Wait();
+
+ // Create key 1
+
+ var keyName = Guid.NewGuid().ToString();
+ var createKeyRequest = new TOTPCreateKeyRequest()
+ {
+ KeyGenerationOption = new TOTPVaultBasedKeyGeneration
+ {
+ Exported = true,
+ KeySize = 32,
+ Issuer = "raja-issuer",
+ AccountName = "raja-account-name",
+ QRSize = 200,
+ Skew = 1
+ },
+ AccountName = "raja-account-name",
+ Algorithm = "SHA512",
+ Issuer = "raja-issuer"
+ };
+
+ var createKeyResponse = _authenticatedVaultClient.V1.Secrets.TOTP.CreateKeyAsync(keyName, createKeyRequest, mountPoint).Result;
+ DisplayJson(createKeyResponse);
+ Assert.NotNull(createKeyResponse.Data.Url);
+ Assert.NotNull(createKeyResponse.Data.Barcode);
+
+ // Read key 1
+
+ var retrievedKey = _authenticatedVaultClient.V1.Secrets.TOTP.ReadKeyAsync(keyName, mountPoint).Result;
+ DisplayJson(retrievedKey);
+ Assert.Equal(createKeyRequest.AccountName, retrievedKey.Data.AccountName);
+
+ // Create key 2
+
+ var keyName2 = Guid.NewGuid().ToString();
+ var createKeyRequest2 = new TOTPCreateKeyRequest()
+ {
+ KeyGenerationOption = new TOTPVaultBasedKeyGeneration
+ {
+ Exported = true,
+ KeySize = 64,
+ Issuer = "raja-issuer2",
+ AccountName = "raja-account-name2",
+ QRSize = 200,
+ Skew = 0
+ },
+ AccountName = "raja-account-name2",
+ Algorithm = "SHA256",
+ Issuer = "raja-issuer2"
+
+ };
+
+ var createKeyResponse2 = _authenticatedVaultClient.V1.Secrets.TOTP.CreateKeyAsync(keyName2, createKeyRequest2, mountPoint).Result;
+ DisplayJson(createKeyResponse2);
+ Assert.NotNull(createKeyResponse2.Data.Url);
+ Assert.NotNull(createKeyResponse2.Data.Barcode);
+
+ // Read all keys
+
+ var allKeys = _authenticatedVaultClient.V1.Secrets.TOTP.ReadAllKeysAsync(mountPoint).Result;
+ DisplayJson(allKeys);
+ Assert.True(allKeys.Data.Keys.Count() == 2);
+
+ // Delete key 2
+
+ _authenticatedVaultClient.V1.Secrets.TOTP.DeleteKeyAsync(keyName2, mountPoint).Wait();
+ allKeys = _authenticatedVaultClient.V1.Secrets.TOTP.ReadAllKeysAsync(mountPoint).Result;
+ DisplayJson(allKeys);
+ Assert.True(allKeys.Data.Keys.Count() == 1);
+
+ // generate code
+ var generatedCode = _authenticatedVaultClient.V1.Secrets.TOTP.GetCodeAsync(keyName, mountPoint).Result;
+ DisplayJson(generatedCode);
+ Assert.NotNull(generatedCode.Data.Code);
+
+ // validate code
+ var validResponse = _authenticatedVaultClient.V1.Secrets.TOTP.ValidateCodeAsync(keyName, generatedCode.Data.Code, mountPoint).Result;
+ DisplayJson(validResponse);
+ Assert.True(validResponse.Data.Valid);
+
+ var invalidResponse = _authenticatedVaultClient.V1.Secrets.TOTP.ValidateCodeAsync(keyName, generatedCode.Data.Code + "2", mountPoint).Result;
+ DisplayJson(invalidResponse);
+ Assert.False(invalidResponse.Data.Valid);
+
+ // unmount
+
+ _authenticatedVaultClient.V1.System.UnmountSecretBackendAsync(mountPoint).Wait();
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/VaultSharp.Samples/Backends/SecretsBackendSamples.cs b/test/VaultSharp.Samples/Backends/SecretsBackendSamples.cs
index 269f17ca..23e5684a 100644
--- a/test/VaultSharp.Samples/Backends/SecretsBackendSamples.cs
+++ b/test/VaultSharp.Samples/Backends/SecretsBackendSamples.cs
@@ -19,6 +19,9 @@ private static void RunSecretsEngineSamples()
Console.WriteLine("\n RunKeyValueSecretsBackendSamples \n");
RunKeyValueSecretsBackendSamples();
+ Console.WriteLine("\n RunTOTPSecretsBackendSamples \n");
+ RunTOTPSecretsBackendSamples();
+
Console.WriteLine("\n RunTransitSecretsBackendSamples \n");
RunTransitSecretsBackendSamples();
}