diff --git a/.editorconfig b/.editorconfig
index f6e8274..b783571 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -18,7 +18,7 @@ indent_size = 4
tab_width = 4
# New line preferences
-end_of_line = crlf
+end_of_line = lf
insert_final_newline = false
#### .NET Coding Conventions ####
@@ -256,31 +256,31 @@ dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
dotnet_naming_symbols.interfaces.applicable_kinds = interface
dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.interfaces.required_modifiers =
+dotnet_naming_symbols.interfaces.required_modifiers =
dotnet_naming_symbols.enums.applicable_kinds = enum
dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.enums.required_modifiers =
+dotnet_naming_symbols.enums.required_modifiers =
dotnet_naming_symbols.events.applicable_kinds = event
dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.events.required_modifiers =
+dotnet_naming_symbols.events.required_modifiers =
dotnet_naming_symbols.methods.applicable_kinds = method
dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.methods.required_modifiers =
+dotnet_naming_symbols.methods.required_modifiers =
dotnet_naming_symbols.properties.applicable_kinds = property
dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.properties.required_modifiers =
+dotnet_naming_symbols.properties.required_modifiers =
dotnet_naming_symbols.public_fields.applicable_kinds = field
dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
-dotnet_naming_symbols.public_fields.required_modifiers =
+dotnet_naming_symbols.public_fields.required_modifiers =
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
-dotnet_naming_symbols.private_fields.required_modifiers =
+dotnet_naming_symbols.private_fields.required_modifiers =
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
@@ -288,15 +288,15 @@ dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.types_and_namespaces.required_modifiers =
+dotnet_naming_symbols.types_and_namespaces.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
-dotnet_naming_symbols.non_field_members.required_modifiers =
+dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
-dotnet_naming_symbols.type_parameters.required_modifiers =
+dotnet_naming_symbols.type_parameters.required_modifiers =
dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
@@ -304,7 +304,7 @@ dotnet_naming_symbols.private_constant_fields.required_modifiers = const
dotnet_naming_symbols.local_variables.applicable_kinds = local
dotnet_naming_symbols.local_variables.applicable_accessibilities = local
-dotnet_naming_symbols.local_variables.required_modifiers =
+dotnet_naming_symbols.local_variables.required_modifiers =
dotnet_naming_symbols.local_constants.applicable_kinds = local
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
@@ -312,7 +312,7 @@ dotnet_naming_symbols.local_constants.required_modifiers = const
dotnet_naming_symbols.parameters.applicable_kinds = parameter
dotnet_naming_symbols.parameters.applicable_accessibilities = *
-dotnet_naming_symbols.parameters.required_modifiers =
+dotnet_naming_symbols.parameters.required_modifiers =
dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
@@ -328,36 +328,36 @@ dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readon
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
-dotnet_naming_symbols.local_functions.required_modifiers =
+dotnet_naming_symbols.local_functions.required_modifiers =
# Naming styles
-dotnet_naming_style.pascalcase.required_prefix =
-dotnet_naming_style.pascalcase.required_suffix =
-dotnet_naming_style.pascalcase.word_separator =
+dotnet_naming_style.pascalcase.required_prefix =
+dotnet_naming_style.pascalcase.required_suffix =
+dotnet_naming_style.pascalcase.word_separator =
dotnet_naming_style.pascalcase.capitalization = pascal_case
dotnet_naming_style.ipascalcase.required_prefix = I
-dotnet_naming_style.ipascalcase.required_suffix =
-dotnet_naming_style.ipascalcase.word_separator =
+dotnet_naming_style.ipascalcase.required_suffix =
+dotnet_naming_style.ipascalcase.word_separator =
dotnet_naming_style.ipascalcase.capitalization = pascal_case
dotnet_naming_style.tpascalcase.required_prefix = T
-dotnet_naming_style.tpascalcase.required_suffix =
-dotnet_naming_style.tpascalcase.word_separator =
+dotnet_naming_style.tpascalcase.required_suffix =
+dotnet_naming_style.tpascalcase.word_separator =
dotnet_naming_style.tpascalcase.capitalization = pascal_case
dotnet_naming_style._camelcase.required_prefix = _
-dotnet_naming_style._camelcase.required_suffix =
-dotnet_naming_style._camelcase.word_separator =
+dotnet_naming_style._camelcase.required_suffix =
+dotnet_naming_style._camelcase.word_separator =
dotnet_naming_style._camelcase.capitalization = camel_case
-dotnet_naming_style.camelcase.required_prefix =
-dotnet_naming_style.camelcase.required_suffix =
-dotnet_naming_style.camelcase.word_separator =
+dotnet_naming_style.camelcase.required_prefix =
+dotnet_naming_style.camelcase.required_suffix =
+dotnet_naming_style.camelcase.word_separator =
dotnet_naming_style.camelcase.capitalization = camel_case
dotnet_naming_style.s_camelcase.required_prefix = s_
-dotnet_naming_style.s_camelcase.required_suffix =
-dotnet_naming_style.s_camelcase.word_separator =
+dotnet_naming_style.s_camelcase.required_suffix =
+dotnet_naming_style.s_camelcase.word_separator =
dotnet_naming_style.s_camelcase.capitalization = camel_case
diff --git a/Passwordless-dotnet.sln b/Passwordless-dotnet.sln
index 61913ec..1ddbe38 100644
--- a/Passwordless-dotnet.sln
+++ b/Passwordless-dotnet.sln
@@ -3,15 +3,17 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Tests", "tests\Sdk.Tests\Sdk.Tests.csproj", "{F64C850E-9923-43F1-BC84-432AFBBA4425}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passwordless.Tests", "tests\Passwordless.Tests\Passwordless.Tests.csproj", "{F64C850E-9923-43F1-BC84-432AFBBA4425}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk", "src\Sdk\Sdk.csproj", "{A01503A8-6AB9-43A7-AC5A-4EAE091B07B6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passwordless", "src\Passwordless\Passwordless.csproj", "{A01503A8-6AB9-43A7-AC5A-4EAE091B07B6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F239A76C-408E-4919-AB70-4499425E6F29}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
Directory.Build.props = Directory.Build.props
+ README.md = README.md
+ LICENSE = LICENSE
EndProjectSection
EndProject
Global
diff --git a/src/Sdk/Base64Url.cs b/src/Passwordless/Base64Url.cs
similarity index 95%
rename from src/Sdk/Base64Url.cs
rename to src/Passwordless/Base64Url.cs
index dfc7b9a..32f92ef 100644
--- a/src/Sdk/Base64Url.cs
+++ b/src/Passwordless/Base64Url.cs
@@ -1,136 +1,136 @@
-using System.Buffers;
-using System.Buffers.Text;
-
-namespace Passwordless.Net;
-
-internal static class Base64Url
-{
- ///
- /// Converts arg data to a Base64Url encoded string.
- ///
- public static string Encode(ReadOnlySpan arg)
- {
- int minimumLength = (int)(((long)arg.Length + 2L) / 3 * 4);
- char[] array = ArrayPool.Shared.Rent(minimumLength);
-
-#if NET5_0_OR_GREATER
- Convert.TryToBase64Chars(arg, array, out var charsWritten);
-#elif NET462 || NETSTANDARD2_0
- var charsWritten = Convert.ToBase64CharArray(arg.ToArray(), 0, minimumLength, array, 0);
-#endif
- Span span = array.AsSpan(0, charsWritten);
-
-
- for (int i = 0; i < span.Length; i++)
- {
- ref char reference = ref span[i];
- switch (reference)
- {
- case '+':
- reference = '-';
- break;
- case '/':
- reference = '_';
- break;
- }
- }
- int num = span.IndexOf('=');
- if (num > -1)
- {
- span = span.Slice(0, num);
- }
-
-#if NET5_0_OR_GREATER
- string result = new string(span);
-#elif NET462 || NETSTANDARD2_0
- string result = new string(span.ToArray());
-#endif
- ArrayPool.Shared.Return(array, clearArray: true);
- return result;
- }
-
- ///
- /// Decodes a Base64Url encoded string to its raw bytes.
- ///
- public static byte[] Decode(ReadOnlySpan text)
- {
- int num = (text.Length % 4) switch
- {
- 2 => 2,
- 3 => 1,
- _ => 0,
- };
- int num2 = text.Length + num;
- char[] array = ArrayPool.Shared.Rent(num2);
- text.CopyTo(array);
- for (int i = 0; i < text.Length; i++)
- {
- ref char reference = ref array[i];
- switch (reference)
- {
- case '-':
- reference = '+';
- break;
- case '_':
- reference = '/';
- break;
- }
- }
- switch (num)
- {
- case 1:
- array[num2 - 1] = '=';
- break;
- case 2:
- array[num2 - 1] = '=';
- array[num2 - 2] = '=';
- break;
- }
- byte[] result = Convert.FromBase64CharArray(array, 0, num2);
- ArrayPool.Shared.Return(array, clearArray: true);
- return result;
- }
-
- ///
- /// Decodes a Base64Url encoded string to its raw bytes.
- ///
- public static byte[] DecodeUtf8(ReadOnlySpan text)
- {
- int num = (text.Length % 4) switch
- {
- 2 => 2,
- 3 => 1,
- _ => 0,
- };
- int num2 = text.Length + num;
- byte[] array = ArrayPool.Shared.Rent(num2);
- text.CopyTo(array);
- for (int i = 0; i < text.Length; i++)
- {
- ref byte reference = ref array[i];
- switch (reference)
- {
- case 45:
- reference = 43;
- break;
- case 95:
- reference = 47;
- break;
- }
- }
- switch (num)
- {
- case 1:
- array[num2 - 1] = 61;
- break;
- case 2:
- array[num2 - 1] = 61;
- array[num2 - 2] = 61;
- break;
- }
- Base64.DecodeFromUtf8InPlace(array.AsSpan(0, num2), out var bytesWritten);
- byte[] result = array.AsSpan(0, bytesWritten).ToArray();
- ArrayPool.Shared.Return(array, clearArray: true);
- return result;
- }
+using System.Buffers;
+using System.Buffers.Text;
+
+namespace Passwordless;
+
+internal static class Base64Url
+{
+ ///
+ /// Converts arg data to a Base64Url encoded string.
+ ///
+ public static string Encode(ReadOnlySpan arg)
+ {
+ int minimumLength = (int)(((long)arg.Length + 2L) / 3 * 4);
+ char[] array = ArrayPool.Shared.Rent(minimumLength);
+
+#if NET5_0_OR_GREATER
+ Convert.TryToBase64Chars(arg, array, out var charsWritten);
+#elif NET462 || NETSTANDARD2_0
+ var charsWritten = Convert.ToBase64CharArray(arg.ToArray(), 0, minimumLength, array, 0);
+#endif
+ Span span = array.AsSpan(0, charsWritten);
+
+
+ for (int i = 0; i < span.Length; i++)
+ {
+ ref char reference = ref span[i];
+ switch (reference)
+ {
+ case '+':
+ reference = '-';
+ break;
+ case '/':
+ reference = '_';
+ break;
+ }
+ }
+ int num = span.IndexOf('=');
+ if (num > -1)
+ {
+ span = span.Slice(0, num);
+ }
+
+#if NET5_0_OR_GREATER
+ string result = new string(span);
+#elif NET462 || NETSTANDARD2_0
+ string result = new string(span.ToArray());
+#endif
+ ArrayPool.Shared.Return(array, clearArray: true);
+ return result;
+ }
+
+ ///
+ /// Decodes a Base64Url encoded string to its raw bytes.
+ ///
+ public static byte[] Decode(ReadOnlySpan text)
+ {
+ int num = (text.Length % 4) switch
+ {
+ 2 => 2,
+ 3 => 1,
+ _ => 0,
+ };
+ int num2 = text.Length + num;
+ char[] array = ArrayPool.Shared.Rent(num2);
+ text.CopyTo(array);
+ for (int i = 0; i < text.Length; i++)
+ {
+ ref char reference = ref array[i];
+ switch (reference)
+ {
+ case '-':
+ reference = '+';
+ break;
+ case '_':
+ reference = '/';
+ break;
+ }
+ }
+ switch (num)
+ {
+ case 1:
+ array[num2 - 1] = '=';
+ break;
+ case 2:
+ array[num2 - 1] = '=';
+ array[num2 - 2] = '=';
+ break;
+ }
+ byte[] result = Convert.FromBase64CharArray(array, 0, num2);
+ ArrayPool.Shared.Return(array, clearArray: true);
+ return result;
+ }
+
+ ///
+ /// Decodes a Base64Url encoded string to its raw bytes.
+ ///
+ public static byte[] DecodeUtf8(ReadOnlySpan text)
+ {
+ int num = (text.Length % 4) switch
+ {
+ 2 => 2,
+ 3 => 1,
+ _ => 0,
+ };
+ int num2 = text.Length + num;
+ byte[] array = ArrayPool.Shared.Rent(num2);
+ text.CopyTo(array);
+ for (int i = 0; i < text.Length; i++)
+ {
+ ref byte reference = ref array[i];
+ switch (reference)
+ {
+ case 45:
+ reference = 43;
+ break;
+ case 95:
+ reference = 47;
+ break;
+ }
+ }
+ switch (num)
+ {
+ case 1:
+ array[num2 - 1] = 61;
+ break;
+ case 2:
+ array[num2 - 1] = 61;
+ array[num2 - 2] = 61;
+ break;
+ }
+ Base64.DecodeFromUtf8InPlace(array.AsSpan(0, num2), out var bytesWritten);
+ byte[] result = array.AsSpan(0, bytesWritten).ToArray();
+ ArrayPool.Shared.Return(array, clearArray: true);
+ return result;
+ }
}
\ No newline at end of file
diff --git a/src/Sdk/Helpers/Base64UrlConverter.cs b/src/Passwordless/Helpers/Base64UrlConverter.cs
similarity index 92%
rename from src/Sdk/Helpers/Base64UrlConverter.cs
rename to src/Passwordless/Helpers/Base64UrlConverter.cs
index 6c08a7f..630429f 100644
--- a/src/Sdk/Helpers/Base64UrlConverter.cs
+++ b/src/Passwordless/Helpers/Base64UrlConverter.cs
@@ -1,21 +1,21 @@
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace Passwordless.Net;
-
-public sealed class Base64UrlConverter : JsonConverter
-{
- public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
- {
- if (!reader.HasValueSequence)
- {
- return Base64Url.DecodeUtf8(reader.ValueSpan);
- }
- return Base64Url.Decode(reader.GetString().AsSpan());
- }
-
- public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
- {
- writer.WriteStringValue(Base64Url.Encode(value));
- }
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Passwordless;
+
+public sealed class Base64UrlConverter : JsonConverter
+{
+ public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (!reader.HasValueSequence)
+ {
+ return Base64Url.DecodeUtf8(reader.ValueSpan);
+ }
+ return Base64Url.Decode(reader.GetString().AsSpan());
+ }
+
+ public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(Base64Url.Encode(value));
+ }
}
\ No newline at end of file
diff --git a/src/Sdk/Helpers/PasswordlessSerializerContext.cs b/src/Passwordless/Helpers/PasswordlessSerializerContext.cs
similarity index 91%
rename from src/Sdk/Helpers/PasswordlessSerializerContext.cs
rename to src/Passwordless/Helpers/PasswordlessSerializerContext.cs
index f75a51f..61d0526 100644
--- a/src/Sdk/Helpers/PasswordlessSerializerContext.cs
+++ b/src/Passwordless/Helpers/PasswordlessSerializerContext.cs
@@ -1,27 +1,27 @@
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using Passwordless.Net.Models;
-
-namespace Passwordless.Net.Helpers;
-
-[JsonSourceGenerationOptions(
- PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
- DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
-[JsonSerializable(typeof(AddAliasRequest))]
-[JsonSerializable(typeof(RegisterTokenResponse))]
-[JsonSerializable(typeof(RegisterOptions))]
-[JsonSerializable(typeof(VerifyTokenRequest))] // TODO: Use this with JsonContent.Create
-[JsonSerializable(typeof(VerifiedUser))]
-[JsonSerializable(typeof(DeleteUserRequest))]
-[JsonSerializable(typeof(ListResponse))]
-[JsonSerializable(typeof(ListResponse))]
-[JsonSerializable(typeof(ListResponse))]
-[JsonSerializable(typeof(DeleteCredentialRequest))]
-[JsonSerializable(typeof(UsersCount))]
-[JsonSerializable(typeof(PasswordlessProblemDetails))]
-[JsonSerializable(typeof(Dictionary))]
-[JsonSerializable(typeof(JsonElement))]
-internal partial class PasswordlessSerializerContext : JsonSerializerContext
-{
-
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Passwordless.Models;
+
+namespace Passwordless.Helpers;
+
+[JsonSourceGenerationOptions(
+ PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
+[JsonSerializable(typeof(AddAliasRequest))]
+[JsonSerializable(typeof(RegisterTokenResponse))]
+[JsonSerializable(typeof(RegisterOptions))]
+[JsonSerializable(typeof(VerifyTokenRequest))] // TODO: Use this with JsonContent.Create
+[JsonSerializable(typeof(VerifiedUser))]
+[JsonSerializable(typeof(DeleteUserRequest))]
+[JsonSerializable(typeof(ListResponse))]
+[JsonSerializable(typeof(ListResponse))]
+[JsonSerializable(typeof(ListResponse))]
+[JsonSerializable(typeof(DeleteCredentialRequest))]
+[JsonSerializable(typeof(UsersCount))]
+[JsonSerializable(typeof(PasswordlessProblemDetails))]
+[JsonSerializable(typeof(Dictionary))]
+[JsonSerializable(typeof(JsonElement))]
+internal partial class PasswordlessSerializerContext : JsonSerializerContext
+{
+
}
\ No newline at end of file
diff --git a/src/Sdk/IPasswordlessClient.cs b/src/Passwordless/IPasswordlessClient.cs
similarity index 97%
rename from src/Sdk/IPasswordlessClient.cs
rename to src/Passwordless/IPasswordlessClient.cs
index ef1d6e8..de9f49c 100644
--- a/src/Sdk/IPasswordlessClient.cs
+++ b/src/Passwordless/IPasswordlessClient.cs
@@ -1,90 +1,90 @@
-using Passwordless.Net.Models;
-
-namespace Passwordless.Net;
-
-///
-/// Provides APIs that help you interact with Passwordless.dev.
-///
-public interface IPasswordlessClient
-{
- ///
- /// Adds one or more aliases to an existing user.
- ///
- ///
- ///
- ///
- Task AddAliasAsync(AddAliasRequest request, CancellationToken cancellationToken = default);
-
- ///
- /// Creates a which will be used by your frontend to negotiate
- /// the creation of a WebAuth credential.
- ///
- /// The that will be used to configure your token.
- ///
- /// A task object representing the asynchronous operation containing the .
- /// An exception containing details abaout the reason for failure.
- Task CreateRegisterTokenAsync(RegisterOptions registerOptions, CancellationToken cancellationToken = default);
-
- ///
- /// Attempts to delete a credential via the supplied id.
- ///
- /// The id of a credential representing as a Base64 URL encoded .
- ///
- /// A task object representing the asynchronous operation.
- /// An exception containing details abaout the reason for failure.
- Task DeleteCredentialAsync(string id, CancellationToken cancellationToken = default);
-
- ///
- /// Attempts to delete a credential via the supplied id.
- ///
- /// The id of a credential representing as a Base64 URL encoded .
- ///
- /// A task object representing the asynchronous operation.
- /// An exception containing details abaout the reason for failure.
- Task DeleteCredentialAsync(byte[] id, CancellationToken cancellationToken = default);
-
- ///
- /// List all the for a given user.
- ///
- /// The userId of the user for which the aliases will be returned.
- ///
- /// A task object representing the asynchronous operation containing the .
- /// An exception containing details abaout the reason for failure.
- Task> ListAliasesAsync(string userId, CancellationToken cancellationToken = default);
-
- ///
- /// List all the for a given user.
- ///
- /// The userId of the user for which the credentials will be returned.
- ///
- /// A task object representing the asynchronous operation containing the .
- /// An exception containing details abaout the reason for failure.
- Task> ListCredentialsAsync(string userId, CancellationToken cancellationToken = default);
-
- ///
- /// List all the for the account associated with your ApiSecret.
- ///
- ///
- /// A task object representing the asynchronous operation containing the .
- /// An exception containing details abaout the reason for failure.
- Task> ListUsersAsync(CancellationToken cancellationToken = default);
-
- ///
- /// Verifies that the given token is valid and returns information packed into it. The token should have been generated
- /// via calling a signInWith* method from your frontend code.
- ///
- /// The token to verify.
- ///
- /// A task object representing the asynchronous operation containing the .
- /// An exception containing details abaout the reason for failure.
- Task VerifyTokenAsync(string verifyToken, CancellationToken cancellationToken = default);
-
- ///
- /// Deletes a user.
- ///
- /// The id of the user that should be deleted.
- ///
- /// A task object representing the asynchronous operation.
- /// An exception containing details abaout the reason for failure.
- Task DeleteUserAsync(string userId, CancellationToken cancellationToken = default);
+using Passwordless.Models;
+
+namespace Passwordless;
+
+///
+/// Provides APIs that help you interact with Passwordless.dev.
+///
+public interface IPasswordlessClient
+{
+ ///
+ /// Adds one or more aliases to an existing user.
+ ///
+ ///
+ ///
+ ///
+ Task AddAliasAsync(AddAliasRequest request, CancellationToken cancellationToken = default);
+
+ ///
+ /// Creates a which will be used by your frontend to negotiate
+ /// the creation of a WebAuth credential.
+ ///
+ /// The that will be used to configure your token.
+ ///
+ /// A task object representing the asynchronous operation containing the .
+ /// An exception containing details abaout the reason for failure.
+ Task CreateRegisterTokenAsync(RegisterOptions registerOptions, CancellationToken cancellationToken = default);
+
+ ///
+ /// Attempts to delete a credential via the supplied id.
+ ///
+ /// The id of a credential representing as a Base64 URL encoded .
+ ///
+ /// A task object representing the asynchronous operation.
+ /// An exception containing details abaout the reason for failure.
+ Task DeleteCredentialAsync(string id, CancellationToken cancellationToken = default);
+
+ ///
+ /// Attempts to delete a credential via the supplied id.
+ ///
+ /// The id of a credential representing as a Base64 URL encoded .
+ ///
+ /// A task object representing the asynchronous operation.
+ /// An exception containing details abaout the reason for failure.
+ Task DeleteCredentialAsync(byte[] id, CancellationToken cancellationToken = default);
+
+ ///
+ /// List all the for a given user.
+ ///
+ /// The userId of the user for which the aliases will be returned.
+ ///
+ /// A task object representing the asynchronous operation containing the .
+ /// An exception containing details abaout the reason for failure.
+ Task> ListAliasesAsync(string userId, CancellationToken cancellationToken = default);
+
+ ///
+ /// List all the for a given user.
+ ///
+ /// The userId of the user for which the credentials will be returned.
+ ///
+ /// A task object representing the asynchronous operation containing the .
+ /// An exception containing details abaout the reason for failure.
+ Task> ListCredentialsAsync(string userId, CancellationToken cancellationToken = default);
+
+ ///
+ /// List all the for the account associated with your ApiSecret.
+ ///
+ ///
+ /// A task object representing the asynchronous operation containing the .
+ /// An exception containing details abaout the reason for failure.
+ Task> ListUsersAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Verifies that the given token is valid and returns information packed into it. The token should have been generated
+ /// via calling a signInWith* method from your frontend code.
+ ///
+ /// The token to verify.
+ ///
+ /// A task object representing the asynchronous operation containing the .
+ /// An exception containing details abaout the reason for failure.
+ Task VerifyTokenAsync(string verifyToken, CancellationToken cancellationToken = default);
+
+ ///
+ /// Deletes a user.
+ ///
+ /// The id of the user that should be deleted.
+ ///
+ /// A task object representing the asynchronous operation.
+ /// An exception containing details abaout the reason for failure.
+ Task DeleteUserAsync(string userId, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/Sdk/Models/AddAliasRequest.cs b/src/Passwordless/Models/AddAliasRequest.cs
similarity index 94%
rename from src/Sdk/Models/AddAliasRequest.cs
rename to src/Passwordless/Models/AddAliasRequest.cs
index ed07275..0c084ee 100644
--- a/src/Sdk/Models/AddAliasRequest.cs
+++ b/src/Passwordless/Models/AddAliasRequest.cs
@@ -1,37 +1,37 @@
-namespace Passwordless.Net.Models;
-
-public class AddAliasRequest
-{
- public AddAliasRequest(string userId, string alias, bool hashing = true)
- : this(userId, hashing)
- {
- if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException($"'{nameof(alias)}' cannot be null, empty or whitespace.");
- Aliases = new HashSet
- {
- alias ?? throw new ArgumentNullException(nameof(alias))
- };
- }
-
- public AddAliasRequest(string userId, HashSet aliases, bool hashing = true)
- : this(userId, hashing)
- {
- if (aliases == null || !aliases.Any()) throw new ArgumentException($"'{nameof(aliases)}' cannot be null or empty.");
- if (aliases.Any(string.IsNullOrWhiteSpace)) throw new ArgumentException("One of the aliases is null, empty or whitespace");
- Aliases = aliases;
- }
-
- private AddAliasRequest(string userId, bool hashing = true)
- {
- UserId = userId ?? throw new ArgumentNullException(nameof(userId));
- Hashing = hashing;
- Aliases = new HashSet();
- }
-
- public string UserId { get; }
- public HashSet Aliases { get; }
-
- ///
- /// If you want your aliases to be available in plain text, set the false.
- ///
- public bool Hashing { get; } = true;
+namespace Passwordless.Models;
+
+public class AddAliasRequest
+{
+ public AddAliasRequest(string userId, string alias, bool hashing = true)
+ : this(userId, hashing)
+ {
+ if (string.IsNullOrWhiteSpace(alias)) throw new ArgumentException($"'{nameof(alias)}' cannot be null, empty or whitespace.");
+ Aliases = new HashSet
+ {
+ alias ?? throw new ArgumentNullException(nameof(alias))
+ };
+ }
+
+ public AddAliasRequest(string userId, HashSet aliases, bool hashing = true)
+ : this(userId, hashing)
+ {
+ if (aliases == null || !aliases.Any()) throw new ArgumentException($"'{nameof(aliases)}' cannot be null or empty.");
+ if (aliases.Any(string.IsNullOrWhiteSpace)) throw new ArgumentException("One of the aliases is null, empty or whitespace");
+ Aliases = aliases;
+ }
+
+ private AddAliasRequest(string userId, bool hashing = true)
+ {
+ UserId = userId ?? throw new ArgumentNullException(nameof(userId));
+ Hashing = hashing;
+ Aliases = new HashSet();
+ }
+
+ public string UserId { get; }
+ public HashSet Aliases { get; }
+
+ ///
+ /// If you want your aliases to be available in plain text, set the false.
+ ///
+ public bool Hashing { get; } = true;
}
\ No newline at end of file
diff --git a/src/Sdk/Models/AliasPointer.cs b/src/Passwordless/Models/AliasPointer.cs
similarity index 86%
rename from src/Sdk/Models/AliasPointer.cs
rename to src/Passwordless/Models/AliasPointer.cs
index 44a26bb..f17bad8 100644
--- a/src/Sdk/Models/AliasPointer.cs
+++ b/src/Passwordless/Models/AliasPointer.cs
@@ -1,15 +1,15 @@
-namespace Passwordless.Net;
-
-public class AliasPointer
-{
- public AliasPointer(string userId, string alias, string plaintext)
- {
- UserId = userId;
- Alias = alias;
- Plaintext = plaintext;
- }
-
- public string UserId { get; }
- public string Alias { get; }
- public string Plaintext { get; }
+namespace Passwordless;
+
+public class AliasPointer
+{
+ public AliasPointer(string userId, string alias, string plaintext)
+ {
+ UserId = userId;
+ Alias = alias;
+ Plaintext = plaintext;
+ }
+
+ public string UserId { get; }
+ public string Alias { get; }
+ public string Plaintext { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/Credential.cs b/src/Passwordless/Models/Credential.cs
similarity index 94%
rename from src/Sdk/Models/Credential.cs
rename to src/Passwordless/Models/Credential.cs
index 5e81ab5..2e3d806 100644
--- a/src/Sdk/Models/Credential.cs
+++ b/src/Passwordless/Models/Credential.cs
@@ -1,39 +1,39 @@
-namespace Passwordless.Net;
-
-public class Credential
-{
- public Credential(CredentialDescriptor descriptor, byte[] publicKey, byte[] userHandle, uint signatureCounter,
- string attestationFmt, DateTime createdAt, Guid aaGuid, DateTime lastUsedAt, string rpid,
- string origin, string country, string device, string nickname, string userId)
- {
- Descriptor = descriptor;
- PublicKey = publicKey;
- UserHandle = userHandle;
- SignatureCounter = signatureCounter;
- AttestationFmt = attestationFmt;
- CreatedAt = createdAt;
- AaGuid = aaGuid;
- LastUsedAt = lastUsedAt;
- RPID = rpid;
- Origin = origin;
- Country = country;
- Device = device;
- Nickname = nickname;
- UserId = userId;
- }
-
- public CredentialDescriptor Descriptor { get; }
- public byte[] PublicKey { get; }
- public byte[] UserHandle { get; }
- public uint SignatureCounter { get; }
- public string AttestationFmt { get; }
- public DateTime CreatedAt { get; }
- public Guid AaGuid { get; }
- public DateTime LastUsedAt { get; }
- public string RPID { get; }
- public string Origin { get; }
- public string Country { get; }
- public string Device { get; }
- public string Nickname { get; }
- public string UserId { get; }
+namespace Passwordless;
+
+public class Credential
+{
+ public Credential(CredentialDescriptor descriptor, byte[] publicKey, byte[] userHandle, uint signatureCounter,
+ string attestationFmt, DateTime createdAt, Guid aaGuid, DateTime lastUsedAt, string rpid,
+ string origin, string country, string device, string nickname, string userId)
+ {
+ Descriptor = descriptor;
+ PublicKey = publicKey;
+ UserHandle = userHandle;
+ SignatureCounter = signatureCounter;
+ AttestationFmt = attestationFmt;
+ CreatedAt = createdAt;
+ AaGuid = aaGuid;
+ LastUsedAt = lastUsedAt;
+ RPID = rpid;
+ Origin = origin;
+ Country = country;
+ Device = device;
+ Nickname = nickname;
+ UserId = userId;
+ }
+
+ public CredentialDescriptor Descriptor { get; }
+ public byte[] PublicKey { get; }
+ public byte[] UserHandle { get; }
+ public uint SignatureCounter { get; }
+ public string AttestationFmt { get; }
+ public DateTime CreatedAt { get; }
+ public Guid AaGuid { get; }
+ public DateTime LastUsedAt { get; }
+ public string RPID { get; }
+ public string Origin { get; }
+ public string Country { get; }
+ public string Device { get; }
+ public string Nickname { get; }
+ public string UserId { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/CredentialDescriptor.cs b/src/Passwordless/Models/CredentialDescriptor.cs
similarity index 85%
rename from src/Sdk/Models/CredentialDescriptor.cs
rename to src/Passwordless/Models/CredentialDescriptor.cs
index 1aee987..a3584b2 100644
--- a/src/Sdk/Models/CredentialDescriptor.cs
+++ b/src/Passwordless/Models/CredentialDescriptor.cs
@@ -1,14 +1,14 @@
-using System.Text.Json.Serialization;
-
-namespace Passwordless.Net;
-
-public class CredentialDescriptor
-{
- public CredentialDescriptor(byte[] id)
- {
- Id = id;
- }
-
- [JsonConverter(typeof(Base64UrlConverter))]
- public byte[] Id { get; set; }
+using System.Text.Json.Serialization;
+
+namespace Passwordless;
+
+public class CredentialDescriptor
+{
+ public CredentialDescriptor(byte[] id)
+ {
+ Id = id;
+ }
+
+ [JsonConverter(typeof(Base64UrlConverter))]
+ public byte[] Id { get; set; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/DeleteCredentialRequest.cs b/src/Passwordless/Models/DeleteCredentialRequest.cs
similarity index 80%
rename from src/Sdk/Models/DeleteCredentialRequest.cs
rename to src/Passwordless/Models/DeleteCredentialRequest.cs
index ce60135..e2e1ea9 100644
--- a/src/Sdk/Models/DeleteCredentialRequest.cs
+++ b/src/Passwordless/Models/DeleteCredentialRequest.cs
@@ -1,11 +1,11 @@
-namespace Passwordless.Net.Models;
-
-internal class DeleteCredentialRequest
-{
- public DeleteCredentialRequest(string credentialId)
- {
- CredentialId = credentialId;
- }
-
- public string CredentialId { get; }
+namespace Passwordless.Models;
+
+internal class DeleteCredentialRequest
+{
+ public DeleteCredentialRequest(string credentialId)
+ {
+ CredentialId = credentialId;
+ }
+
+ public string CredentialId { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/DeleteUserRequest.cs b/src/Passwordless/Models/DeleteUserRequest.cs
similarity index 77%
rename from src/Sdk/Models/DeleteUserRequest.cs
rename to src/Passwordless/Models/DeleteUserRequest.cs
index 8ff250a..2b98a97 100644
--- a/src/Sdk/Models/DeleteUserRequest.cs
+++ b/src/Passwordless/Models/DeleteUserRequest.cs
@@ -1,11 +1,11 @@
-namespace Passwordless.Net.Models;
-
-internal class DeleteUserRequest
-{
- public DeleteUserRequest(string userId)
- {
- UserId = userId;
- }
-
- public string UserId { get; }
+namespace Passwordless.Models;
+
+internal class DeleteUserRequest
+{
+ public DeleteUserRequest(string userId)
+ {
+ UserId = userId;
+ }
+
+ public string UserId { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/ListResponse.cs b/src/Passwordless/Models/ListResponse.cs
similarity index 78%
rename from src/Sdk/Models/ListResponse.cs
rename to src/Passwordless/Models/ListResponse.cs
index 0a91c42..248f527 100644
--- a/src/Sdk/Models/ListResponse.cs
+++ b/src/Passwordless/Models/ListResponse.cs
@@ -1,11 +1,11 @@
-namespace Passwordless.Net.Models;
-
-internal class ListResponse
-{
- public ListResponse(IReadOnlyList values)
- {
- Values = values;
- }
-
- public IReadOnlyList Values { get; }
+namespace Passwordless.Models;
+
+internal class ListResponse
+{
+ public ListResponse(IReadOnlyList values)
+ {
+ Values = values;
+ }
+
+ public IReadOnlyList Values { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/PasswordlessUserSummary.cs b/src/Passwordless/Models/PasswordlessUserSummary.cs
similarity index 92%
rename from src/Sdk/Models/PasswordlessUserSummary.cs
rename to src/Passwordless/Models/PasswordlessUserSummary.cs
index a285adc..1542211 100644
--- a/src/Sdk/Models/PasswordlessUserSummary.cs
+++ b/src/Passwordless/Models/PasswordlessUserSummary.cs
@@ -1,20 +1,20 @@
-namespace Passwordless.Net;
-
-public class PasswordlessUserSummary
-{
- public PasswordlessUserSummary(string userId, IReadOnlyList aliases, int credentialsCount,
- int aliasCount, DateTime? lastUsedAt)
- {
- UserId = userId;
- Aliases = aliases;
- CredentialsCount = credentialsCount;
- AliasCount = aliasCount;
- LastUsedAt = lastUsedAt;
- }
-
- public string UserId { get; }
- public IReadOnlyList Aliases { get; }
- public int CredentialsCount { get; }
- public int AliasCount { get; }
- public DateTime? LastUsedAt { get; }
+namespace Passwordless;
+
+public class PasswordlessUserSummary
+{
+ public PasswordlessUserSummary(string userId, IReadOnlyList aliases, int credentialsCount,
+ int aliasCount, DateTime? lastUsedAt)
+ {
+ UserId = userId;
+ Aliases = aliases;
+ CredentialsCount = credentialsCount;
+ AliasCount = aliasCount;
+ LastUsedAt = lastUsedAt;
+ }
+
+ public string UserId { get; }
+ public IReadOnlyList Aliases { get; }
+ public int CredentialsCount { get; }
+ public int AliasCount { get; }
+ public DateTime? LastUsedAt { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/RegisterOptions.cs b/src/Passwordless/Models/RegisterOptions.cs
similarity index 96%
rename from src/Sdk/Models/RegisterOptions.cs
rename to src/Passwordless/Models/RegisterOptions.cs
index 7a67df9..f7aecb1 100644
--- a/src/Sdk/Models/RegisterOptions.cs
+++ b/src/Passwordless/Models/RegisterOptions.cs
@@ -1,80 +1,80 @@
-using System.Text.Json.Serialization;
-
-namespace Passwordless.Net;
-
-///
-///
-///
-public class RegisterOptions
-{
- ///
- ///
- ///
- ///
- ///
- public RegisterOptions(string userId, string username)
- {
- UserId = userId;
- Username = username;
- }
-
- ///
- /// A WebAuthn User Handle, which should be generated by your application.
- /// This is used to identify your user (could be a database primary key ID or a guid).
- /// Max. 64 bytes. Should not contain PII about the user.
- ///
- public string UserId { get; }
-
- ///
- /// A human-palatable identifier for a user account. It is intended only for display,
- /// i.e., aiding the user in determining the difference between user accounts with
- /// similar displayNames. Used in Browser UI's and never stored on the server.
- ///
- public string Username { get; }
-
- ///
- /// A human-palatable name for the account, which should be chosen by the user.
- /// Used in Browser UI's and never stored on the server.
- ///
- public string? DisplayName { get; set; }
-
- ///
- /// WebAuthn attestation conveyance preference. Only "none" (default) is supported.
- ///
- public string? Attestation { get; set; }
-
- ///
- /// WebAuthn authenticator attachment modality. Can be "any" (default), "platform",
- /// which triggers client device-specific options Windows Hello, FaceID, or TouchID,
- /// or "cross-platform", which triggers roaming options like security keys.
- ///
- public string? AuthenticatorType { get; set; }
-
- ///
- /// If true, creates a client-side Discoverable Credential that allows sign in without needing a username.
- ///
- public bool? Discoverable { get; set; }
-
- ///
- /// Allows choosing preference for requiring User Verification
- /// (biometrics, pin code etc) when authenticating Can be "preferred" (default), "required" or "discouraged".
- ///
- public string? UserVerification { get; set; }
-
- ///
- /// Timestamp (UTC) when the registration token should expire. By default, current time + 120 seconds.
- ///
- public DateTime? ExpiresAt { get; set; }
-
- ///
- /// A array of aliases for the userId, such as an email or username. Used to initiate a
- /// signin on the client side with the signinWithAlias() method. An alias must be unique to the userId.
- /// Defaults to an empty array [].
- ///
- public HashSet Aliases { get; set; } = new HashSet();
-
- ///
- /// Whether aliases should be hashed before being stored. Defaults to true.
- ///
- public bool? AliasHashing { get; set; }
+using System.Text.Json.Serialization;
+
+namespace Passwordless;
+
+///
+///
+///
+public class RegisterOptions
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RegisterOptions(string userId, string username)
+ {
+ UserId = userId;
+ Username = username;
+ }
+
+ ///
+ /// A WebAuthn User Handle, which should be generated by your application.
+ /// This is used to identify your user (could be a database primary key ID or a guid).
+ /// Max. 64 bytes. Should not contain PII about the user.
+ ///
+ public string UserId { get; }
+
+ ///
+ /// A human-palatable identifier for a user account. It is intended only for display,
+ /// i.e., aiding the user in determining the difference between user accounts with
+ /// similar displayNames. Used in Browser UI's and never stored on the server.
+ ///
+ public string Username { get; }
+
+ ///
+ /// A human-palatable name for the account, which should be chosen by the user.
+ /// Used in Browser UI's and never stored on the server.
+ ///
+ public string? DisplayName { get; set; }
+
+ ///
+ /// WebAuthn attestation conveyance preference. Only "none" (default) is supported.
+ ///
+ public string? Attestation { get; set; }
+
+ ///
+ /// WebAuthn authenticator attachment modality. Can be "any" (default), "platform",
+ /// which triggers client device-specific options Windows Hello, FaceID, or TouchID,
+ /// or "cross-platform", which triggers roaming options like security keys.
+ ///
+ public string? AuthenticatorType { get; set; }
+
+ ///
+ /// If true, creates a client-side Discoverable Credential that allows sign in without needing a username.
+ ///
+ public bool? Discoverable { get; set; }
+
+ ///
+ /// Allows choosing preference for requiring User Verification
+ /// (biometrics, pin code etc) when authenticating Can be "preferred" (default), "required" or "discouraged".
+ ///
+ public string? UserVerification { get; set; }
+
+ ///
+ /// Timestamp (UTC) when the registration token should expire. By default, current time + 120 seconds.
+ ///
+ public DateTime? ExpiresAt { get; set; }
+
+ ///
+ /// A array of aliases for the userId, such as an email or username. Used to initiate a
+ /// signin on the client side with the signinWithAlias() method. An alias must be unique to the userId.
+ /// Defaults to an empty array [].
+ ///
+ public HashSet Aliases { get; set; } = new HashSet();
+
+ ///
+ /// Whether aliases should be hashed before being stored. Defaults to true.
+ ///
+ public bool? AliasHashing { get; set; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/RegisterTokenResponse.cs b/src/Passwordless/Models/RegisterTokenResponse.cs
similarity index 80%
rename from src/Sdk/Models/RegisterTokenResponse.cs
rename to src/Passwordless/Models/RegisterTokenResponse.cs
index ebdf77d..41c2e9a 100644
--- a/src/Sdk/Models/RegisterTokenResponse.cs
+++ b/src/Passwordless/Models/RegisterTokenResponse.cs
@@ -1,13 +1,13 @@
-using System.Text.Json.Serialization;
-
-namespace Passwordless.Net.Models;
-
-public class RegisterTokenResponse
-{
- public RegisterTokenResponse(string token)
- {
- Token = token;
- }
-
- public string Token { get; }
+using System.Text.Json.Serialization;
+
+namespace Passwordless.Models;
+
+public class RegisterTokenResponse
+{
+ public RegisterTokenResponse(string token)
+ {
+ Token = token;
+ }
+
+ public string Token { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/UsersCount.cs b/src/Passwordless/Models/UsersCount.cs
similarity index 76%
rename from src/Sdk/Models/UsersCount.cs
rename to src/Passwordless/Models/UsersCount.cs
index 756983c..881e648 100644
--- a/src/Sdk/Models/UsersCount.cs
+++ b/src/Passwordless/Models/UsersCount.cs
@@ -1,11 +1,11 @@
-namespace Passwordless.Net;
-
-public class UsersCount
-{
- public UsersCount(int count)
- {
- Count = count;
- }
-
- public int Count { get; }
+namespace Passwordless;
+
+public class UsersCount
+{
+ public UsersCount(int count)
+ {
+ Count = count;
+ }
+
+ public int Count { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/VerifiedUser.cs b/src/Passwordless/Models/VerifiedUser.cs
similarity index 94%
rename from src/Sdk/Models/VerifiedUser.cs
rename to src/Passwordless/Models/VerifiedUser.cs
index 84f7146..7a784d1 100644
--- a/src/Sdk/Models/VerifiedUser.cs
+++ b/src/Passwordless/Models/VerifiedUser.cs
@@ -1,35 +1,35 @@
-namespace Passwordless.Net;
-
-public class VerifiedUser
-{
- public VerifiedUser(string userId, byte[] credentialId, bool success,
- DateTime timestamp, string rpId, string origin, string device,
- string country, string nickname, DateTime expiresAt, Guid tokenId,
- string type)
- {
- UserId = userId;
- CredentialId = credentialId;
- Success = success;
- Timestamp = timestamp;
- RpId = rpId;
- Origin = origin;
- Device = device;
- Country = country;
- Nickname = nickname;
- ExpiresAt = expiresAt;
- TokenId = tokenId;
- Type = type;
- }
- public string UserId { get; }
- public byte[] CredentialId { get; }
- public bool Success { get; }
- public DateTime Timestamp { get; }
- public string RpId { get; }
- public string Origin { get; }
- public string Device { get; }
- public string Country { get; }
- public string Nickname { get; }
- public DateTime ExpiresAt { get; }
- public Guid TokenId { get; }
- public string Type { get; }
+namespace Passwordless;
+
+public class VerifiedUser
+{
+ public VerifiedUser(string userId, byte[] credentialId, bool success,
+ DateTime timestamp, string rpId, string origin, string device,
+ string country, string nickname, DateTime expiresAt, Guid tokenId,
+ string type)
+ {
+ UserId = userId;
+ CredentialId = credentialId;
+ Success = success;
+ Timestamp = timestamp;
+ RpId = rpId;
+ Origin = origin;
+ Device = device;
+ Country = country;
+ Nickname = nickname;
+ ExpiresAt = expiresAt;
+ TokenId = tokenId;
+ Type = type;
+ }
+ public string UserId { get; }
+ public byte[] CredentialId { get; }
+ public bool Success { get; }
+ public DateTime Timestamp { get; }
+ public string RpId { get; }
+ public string Origin { get; }
+ public string Device { get; }
+ public string Country { get; }
+ public string Nickname { get; }
+ public DateTime ExpiresAt { get; }
+ public Guid TokenId { get; }
+ public string Type { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Models/VerifyTokenRequest.cs b/src/Passwordless/Models/VerifyTokenRequest.cs
similarity index 77%
rename from src/Sdk/Models/VerifyTokenRequest.cs
rename to src/Passwordless/Models/VerifyTokenRequest.cs
index 89cc8b4..323b36b 100644
--- a/src/Sdk/Models/VerifyTokenRequest.cs
+++ b/src/Passwordless/Models/VerifyTokenRequest.cs
@@ -1,11 +1,11 @@
-namespace Passwordless.Net.Models;
-
-internal class VerifyTokenRequest
-{
- public VerifyTokenRequest(string token)
- {
- Token = token;
- }
-
- public string Token { get; }
+namespace Passwordless.Models;
+
+internal class VerifyTokenRequest
+{
+ public VerifyTokenRequest(string token)
+ {
+ Token = token;
+ }
+
+ public string Token { get; }
}
\ No newline at end of file
diff --git a/src/Sdk/Sdk.csproj b/src/Passwordless/Passwordless.csproj
similarity index 64%
rename from src/Sdk/Sdk.csproj
rename to src/Passwordless/Passwordless.csproj
index b0e9f00..530ab82 100644
--- a/src/Sdk/Sdk.csproj
+++ b/src/Passwordless/Passwordless.csproj
@@ -1,20 +1,21 @@
- Passwordless.Net
- Passwordless.Net
- Passwordless
net462;net6.0;net7.0;netstandard2.0
- $(TargetFrameworks);$(CurrentPreviewTfm)
+ $(TargetFrameworks);$(CurrentPreviewTfm)
+ true
+
+
+
+
Bitwarden
https://github.com/passwordless/passwordless-dotnet
git
README.md
- true
-
+
$(DefineConstants);INCLUDE_DYNAMICALLY_ACCESSED_MEMBERS
@@ -23,20 +24,19 @@
-
+
-
+
-
-
+
diff --git a/src/Sdk/PasswordlessApiException.cs b/src/Passwordless/PasswordlessApiException.cs
similarity index 94%
rename from src/Sdk/PasswordlessApiException.cs
rename to src/Passwordless/PasswordlessApiException.cs
index 0e6a409..2fb6858 100644
--- a/src/Sdk/PasswordlessApiException.cs
+++ b/src/Passwordless/PasswordlessApiException.cs
@@ -1,39 +1,39 @@
-using System.Diagnostics;
-using System.Net.Http;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace Passwordless.Net;
-
-public sealed class PasswordlessApiException : HttpRequestException
-{
- public PasswordlessProblemDetails Details { get; }
-
- public PasswordlessApiException(PasswordlessProblemDetails problemDetails) : base(problemDetails.Title)
- {
- Details = problemDetails;
- }
-}
-
-public class PasswordlessProblemDetails
-{
- public PasswordlessProblemDetails(string type,
- string title, int status, string? detail, string? instance)
- {
- Type = type;
- Title = title;
- Status = status;
- Detail = detail;
- Instance = instance;
- }
-
- // TODO: Include errorCode as a property once it's more common
- public string Type { get; }
- public string Title { get; }
- public int Status { get; }
- public string? Detail { get; }
- public string? Instance { get; }
-
- [JsonExtensionData]
- public Dictionary Extensions { get; set; } = new Dictionary();
+using System.Diagnostics;
+using System.Net.Http;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Passwordless;
+
+public sealed class PasswordlessApiException : HttpRequestException
+{
+ public PasswordlessProblemDetails Details { get; }
+
+ public PasswordlessApiException(PasswordlessProblemDetails problemDetails) : base(problemDetails.Title)
+ {
+ Details = problemDetails;
+ }
+}
+
+public class PasswordlessProblemDetails
+{
+ public PasswordlessProblemDetails(string type,
+ string title, int status, string? detail, string? instance)
+ {
+ Type = type;
+ Title = title;
+ Status = status;
+ Detail = detail;
+ Instance = instance;
+ }
+
+ // TODO: Include errorCode as a property once it's more common
+ public string Type { get; }
+ public string Title { get; }
+ public int Status { get; }
+ public string? Detail { get; }
+ public string? Instance { get; }
+
+ [JsonExtensionData]
+ public Dictionary Extensions { get; set; } = new Dictionary();
}
\ No newline at end of file
diff --git a/src/Sdk/PasswordlessClient.cs b/src/Passwordless/PasswordlessClient.cs
similarity index 86%
rename from src/Sdk/PasswordlessClient.cs
rename to src/Passwordless/PasswordlessClient.cs
index e9b354e..d5c9b01 100644
--- a/src/Sdk/PasswordlessClient.cs
+++ b/src/Passwordless/PasswordlessClient.cs
@@ -1,192 +1,193 @@
-using System.Diagnostics;
-using System.Net.Http.Json;
-using System.Text;
-using Passwordless.Net.Models;
-using JsonContext = Passwordless.Net.Helpers.PasswordlessSerializerContext;
-
-namespace Passwordless.Net;
-
-///
-/// TODO: FILL IN
-///
-[DebuggerDisplay("{DebuggerToString(),nq}")]
-public class PasswordlessClient : IPasswordlessClient, IDisposable
-{
- private readonly bool _needsDisposing;
- private readonly HttpClient _client;
-
- public static PasswordlessClient Create(PasswordlessOptions options, IHttpClientFactory factory)
- {
- var client = factory.CreateClient();
- client.BaseAddress = new Uri(options.ApiUrl);
- client.DefaultRequestHeaders.Add("ApiSecret", options.ApiSecret);
- return new PasswordlessClient(client);
- }
-
- public PasswordlessClient(PasswordlessOptions passwordlessOptions)
- {
- _needsDisposing = true;
- _client = new HttpClient
- {
- BaseAddress = new Uri(passwordlessOptions.ApiUrl),
- };
- _client.DefaultRequestHeaders.Add("ApiSecret", passwordlessOptions.ApiSecret);
- }
-
- public PasswordlessClient(HttpClient client)
- {
- _needsDisposing = false;
- _client = client;
- }
-
- ///
- public async Task AddAliasAsync(AddAliasRequest request, CancellationToken cancellationToken)
- {
- var res = await _client.PostAsJsonAsync("alias",
- request,
- JsonContext.Default.AddAliasRequest,
- cancellationToken);
- res.EnsureSuccessStatusCode();
- }
-
- ///
- public async Task CreateRegisterTokenAsync(RegisterOptions registerOptions, CancellationToken cancellationToken = default)
- {
- var res = await _client.PostAsJsonAsync("register/token",
- registerOptions,
- JsonContext.Default.RegisterOptions,
- cancellationToken);
- res.EnsureSuccessStatusCode();
- return (await res.Content.ReadFromJsonAsync(
- JsonContext.Default.RegisterTokenResponse,
- cancellationToken))!;
- }
-
- ///
- public async Task VerifyTokenAsync(string verifyToken, CancellationToken cancellationToken = default)
- {
- var request = new HttpRequestMessage(HttpMethod.Post, "signin/verify")
- {
- // TODO: No JsonTypeInfo overload yet?
- Content = JsonContent.Create(new VerifyTokenRequest(verifyToken)),
- };
-
- // We just want to return null if there is a problem.
- request.SkipErrorHandling();
- var response = await _client.SendAsync(request, cancellationToken);
-
- if (response.IsSuccessStatusCode)
- {
- var res = await response.Content.ReadFromJsonAsync(
- JsonContext.Default.VerifiedUser,
- cancellationToken);
- return res;
- }
-
- return null;
- }
-
- ///
- public async Task DeleteUserAsync(string userId, CancellationToken cancellationToken = default)
- {
- await _client.PostAsJsonAsync("users/delete",
- new DeleteUserRequest(userId),
- JsonContext.Default.DeleteUserRequest,
- cancellationToken);
- }
-
- ///
- public async Task> ListUsersAsync(CancellationToken cancellationToken = default)
- {
- var response = await _client.GetFromJsonAsync(
- "users/list",
- JsonContext.Default.ListResponsePasswordlessUserSummary,
- cancellationToken);
- return response!.Values;
- }
-
- ///
- public async Task> ListAliasesAsync(string userId, CancellationToken cancellationToken = default)
- {
- var response = await _client.GetFromJsonAsync(
- $"alias/list?userid={userId}",
- JsonContext.Default.ListResponseAliasPointer,
- cancellationToken);
- return response!.Values;
- }
-
- ///
- public async Task> ListCredentialsAsync(string userId, CancellationToken cancellationToken = default)
- {
- var response = await _client.GetFromJsonAsync(
- $"credentials/list?userid={userId}",
- JsonContext.Default.ListResponseCredential,
- cancellationToken);
- return response!.Values;
- }
-
- ///
- public async Task DeleteCredentialAsync(string id, CancellationToken cancellationToken = default)
- {
- await _client.PostAsJsonAsync("credentials/delete",
- new DeleteCredentialRequest(id),
- JsonContext.Default.DeleteCredentialRequest,
- cancellationToken);
- }
-
- ///
- public async Task DeleteCredentialAsync(byte[] id, CancellationToken cancellationToken = default)
- {
- await DeleteCredentialAsync(Base64Url.Encode(id), cancellationToken);
- }
-
- public async Task GetUsersCountAsync(CancellationToken cancellationToken = default)
- {
- return (await _client.GetFromJsonAsync(
- "users/count",
- JsonContext.Default.UsersCount,
- cancellationToken))!;
- }
-
- private string DebuggerToString()
- {
- var sb = new StringBuilder();
- sb.Append("ApiUrl = ");
- sb.Append(_client.BaseAddress);
- if (_client.DefaultRequestHeaders.TryGetValues("ApiSecret", out var values))
- {
- var apiSecret = values.First();
- if (apiSecret.Length > 5)
- {
- sb.Append(' ');
- sb.Append("ApiSecret = ");
- sb.Append("***");
- sb.Append(apiSecret.Substring(apiSecret.Length - 4));
- }
- }
- else
- {
- sb.Append(' ');
- sb.Append("ApiSecret = (null)");
- }
-
- return sb.ToString();
- }
-
- public void Dispose()
- {
- if (_needsDisposing)
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- _client.Dispose();
- }
- }
+using System.Diagnostics;
+using System.Net.Http.Json;
+using System.Text;
+using Passwordless.Helpers;
+using Passwordless.Models;
+using JsonContext = Passwordless.Helpers.PasswordlessSerializerContext;
+
+namespace Passwordless;
+
+///
+/// TODO: FILL IN
+///
+[DebuggerDisplay("{DebuggerToString(),nq}")]
+public class PasswordlessClient : IPasswordlessClient, IDisposable
+{
+ private readonly bool _needsDisposing;
+ private readonly HttpClient _client;
+
+ public static PasswordlessClient Create(PasswordlessOptions options, IHttpClientFactory factory)
+ {
+ var client = factory.CreateClient();
+ client.BaseAddress = new Uri(options.ApiUrl);
+ client.DefaultRequestHeaders.Add("ApiSecret", options.ApiSecret);
+ return new PasswordlessClient(client);
+ }
+
+ public PasswordlessClient(PasswordlessOptions passwordlessOptions)
+ {
+ _needsDisposing = true;
+ _client = new HttpClient
+ {
+ BaseAddress = new Uri(passwordlessOptions.ApiUrl),
+ };
+ _client.DefaultRequestHeaders.Add("ApiSecret", passwordlessOptions.ApiSecret);
+ }
+
+ public PasswordlessClient(HttpClient client)
+ {
+ _needsDisposing = false;
+ _client = client;
+ }
+
+ ///
+ public async Task AddAliasAsync(AddAliasRequest request, CancellationToken cancellationToken)
+ {
+ var res = await _client.PostAsJsonAsync("alias",
+ request,
+ PasswordlessSerializerContext.Default.AddAliasRequest,
+ cancellationToken);
+ res.EnsureSuccessStatusCode();
+ }
+
+ ///
+ public async Task CreateRegisterTokenAsync(RegisterOptions registerOptions, CancellationToken cancellationToken = default)
+ {
+ var res = await _client.PostAsJsonAsync("register/token",
+ registerOptions,
+ PasswordlessSerializerContext.Default.RegisterOptions,
+ cancellationToken);
+ res.EnsureSuccessStatusCode();
+ return (await res.Content.ReadFromJsonAsync(
+ PasswordlessSerializerContext.Default.RegisterTokenResponse,
+ cancellationToken))!;
+ }
+
+ ///
+ public async Task VerifyTokenAsync(string verifyToken, CancellationToken cancellationToken = default)
+ {
+ var request = new HttpRequestMessage(HttpMethod.Post, "signin/verify")
+ {
+ // TODO: No JsonTypeInfo overload yet?
+ Content = JsonContent.Create(new VerifyTokenRequest(verifyToken)),
+ };
+
+ // We just want to return null if there is a problem.
+ request.SkipErrorHandling();
+ var response = await _client.SendAsync(request, cancellationToken);
+
+ if (response.IsSuccessStatusCode)
+ {
+ var res = await response.Content.ReadFromJsonAsync(
+ PasswordlessSerializerContext.Default.VerifiedUser,
+ cancellationToken);
+ return res;
+ }
+
+ return null;
+ }
+
+ ///
+ public async Task DeleteUserAsync(string userId, CancellationToken cancellationToken = default)
+ {
+ await _client.PostAsJsonAsync("users/delete",
+ new DeleteUserRequest(userId),
+ PasswordlessSerializerContext.Default.DeleteUserRequest,
+ cancellationToken);
+ }
+
+ ///
+ public async Task> ListUsersAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await _client.GetFromJsonAsync(
+ "users/list",
+ PasswordlessSerializerContext.Default.ListResponsePasswordlessUserSummary,
+ cancellationToken);
+ return response!.Values;
+ }
+
+ ///
+ public async Task> ListAliasesAsync(string userId, CancellationToken cancellationToken = default)
+ {
+ var response = await _client.GetFromJsonAsync(
+ $"alias/list?userid={userId}",
+ PasswordlessSerializerContext.Default.ListResponseAliasPointer,
+ cancellationToken);
+ return response!.Values;
+ }
+
+ ///
+ public async Task> ListCredentialsAsync(string userId, CancellationToken cancellationToken = default)
+ {
+ var response = await _client.GetFromJsonAsync(
+ $"credentials/list?userid={userId}",
+ PasswordlessSerializerContext.Default.ListResponseCredential,
+ cancellationToken);
+ return response!.Values;
+ }
+
+ ///
+ public async Task DeleteCredentialAsync(string id, CancellationToken cancellationToken = default)
+ {
+ await _client.PostAsJsonAsync("credentials/delete",
+ new DeleteCredentialRequest(id),
+ PasswordlessSerializerContext.Default.DeleteCredentialRequest,
+ cancellationToken);
+ }
+
+ ///
+ public async Task DeleteCredentialAsync(byte[] id, CancellationToken cancellationToken = default)
+ {
+ await DeleteCredentialAsync(Base64Url.Encode(id), cancellationToken);
+ }
+
+ public async Task GetUsersCountAsync(CancellationToken cancellationToken = default)
+ {
+ return (await _client.GetFromJsonAsync(
+ "users/count",
+ PasswordlessSerializerContext.Default.UsersCount,
+ cancellationToken))!;
+ }
+
+ private string DebuggerToString()
+ {
+ var sb = new StringBuilder();
+ sb.Append("ApiUrl = ");
+ sb.Append(_client.BaseAddress);
+ if (_client.DefaultRequestHeaders.TryGetValues("ApiSecret", out var values))
+ {
+ var apiSecret = values.First();
+ if (apiSecret.Length > 5)
+ {
+ sb.Append(' ');
+ sb.Append("ApiSecret = ");
+ sb.Append("***");
+ sb.Append(apiSecret.Substring(apiSecret.Length - 4));
+ }
+ }
+ else
+ {
+ sb.Append(' ');
+ sb.Append("ApiSecret = (null)");
+ }
+
+ return sb.ToString();
+ }
+
+ public void Dispose()
+ {
+ if (_needsDisposing)
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _client.Dispose();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Sdk/PasswordlessDelegatingHandler.cs b/src/Passwordless/PasswordlessDelegatingHandler.cs
similarity index 91%
rename from src/Sdk/PasswordlessDelegatingHandler.cs
rename to src/Passwordless/PasswordlessDelegatingHandler.cs
index 1e145e5..f467ed1 100644
--- a/src/Sdk/PasswordlessDelegatingHandler.cs
+++ b/src/Passwordless/PasswordlessDelegatingHandler.cs
@@ -1,32 +1,32 @@
-using System.Net.Http;
-using System.Net.Http.Json;
-using Passwordless.Net.Helpers;
-
-namespace Passwordless.Net;
-
-internal class PasswordlessDelegatingHandler : DelegatingHandler
-{
- protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
- {
- var response = await base.SendAsync(request, cancellationToken);
-
- if (request.ShouldSkipErrorHandling())
- {
- return response;
- }
-
- if (!response.IsSuccessStatusCode
- && string.Equals(response.Content.Headers.ContentType?.MediaType, "application/problem+json", StringComparison.OrdinalIgnoreCase))
- {
- // Attempt to read problem details
- var problemDetails = await response.Content.ReadFromJsonAsync(
- PasswordlessSerializerContext.Default.PasswordlessProblemDetails,
- cancellationToken);
-
- // Throw exception
- throw new PasswordlessApiException(problemDetails!);
- }
-
- return response;
- }
+using System.Net.Http;
+using System.Net.Http.Json;
+using Passwordless.Helpers;
+
+namespace Passwordless;
+
+internal class PasswordlessDelegatingHandler : DelegatingHandler
+{
+ protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ var response = await base.SendAsync(request, cancellationToken);
+
+ if (request.ShouldSkipErrorHandling())
+ {
+ return response;
+ }
+
+ if (!response.IsSuccessStatusCode
+ && string.Equals(response.Content.Headers.ContentType?.MediaType, "application/problem+json", StringComparison.OrdinalIgnoreCase))
+ {
+ // Attempt to read problem details
+ var problemDetails = await response.Content.ReadFromJsonAsync(
+ PasswordlessSerializerContext.Default.PasswordlessProblemDetails,
+ cancellationToken);
+
+ // Throw exception
+ throw new PasswordlessApiException(problemDetails!);
+ }
+
+ return response;
+ }
}
\ No newline at end of file
diff --git a/src/Sdk/PasswordlessExtensions.cs b/src/Passwordless/PasswordlessExtensions.cs
similarity index 79%
rename from src/Sdk/PasswordlessExtensions.cs
rename to src/Passwordless/PasswordlessExtensions.cs
index 1b7a855..cfa479f 100644
--- a/src/Sdk/PasswordlessExtensions.cs
+++ b/src/Passwordless/PasswordlessExtensions.cs
@@ -1,9 +1,9 @@
-namespace Passwordless.Net;
-
-public static class PasswordlessExtensions
-{
- public static string ToBase64Url(this byte[] bytes)
- {
- return Base64Url.Encode(bytes);
- }
+namespace Passwordless;
+
+public static class PasswordlessExtensions
+{
+ public static string ToBase64Url(this byte[] bytes)
+ {
+ return Base64Url.Encode(bytes);
+ }
}
\ No newline at end of file
diff --git a/src/Sdk/PasswordlessHttpRequestExtensions.cs b/src/Passwordless/PasswordlessHttpRequestExtensions.cs
similarity index 94%
rename from src/Sdk/PasswordlessHttpRequestExtensions.cs
rename to src/Passwordless/PasswordlessHttpRequestExtensions.cs
index 75d4fb9..0347c6a 100644
--- a/src/Sdk/PasswordlessHttpRequestExtensions.cs
+++ b/src/Passwordless/PasswordlessHttpRequestExtensions.cs
@@ -1,33 +1,33 @@
-using System.Net.Http;
-
-namespace Passwordless.Net;
-
-internal static class PasswordlessHttpRequestExtensions
-{
-#if NET5_0_OR_GREATER
- internal static HttpRequestOptionsKey SkipErrorHandlingOption = new(nameof(SkipErrorHandling));
-#elif NET462 || NETSTANDARD2_0
- internal const string SkipErrorHandlingOption = nameof(SkipErrorHandling);
-#endif
-
- internal static HttpRequestMessage SkipErrorHandling(this HttpRequestMessage request, bool skip = true)
- {
-#if NET5_0_OR_GREATER
- request.Options.Set(SkipErrorHandlingOption, skip);
-#elif NET462 || NETSTANDARD2_0
- request.Properties[SkipErrorHandlingOption] = skip;
-#endif
- return request;
- }
-
- internal static bool ShouldSkipErrorHandling(this HttpRequestMessage request)
- {
-#if NET5_0_OR_GREATER
- return request.Options.TryGetValue(SkipErrorHandlingOption, out var doNotErrorHandle) && doNotErrorHandle;
-#elif NET462 || NETSTANDARD2_0
- return request.Properties.TryGetValue(SkipErrorHandlingOption, out var shouldSkipOptionObject)
- && shouldSkipOptionObject is bool shouldSkipOption
- && shouldSkipOption;
-#endif
- }
+using System.Net.Http;
+
+namespace Passwordless;
+
+internal static class PasswordlessHttpRequestExtensions
+{
+#if NET5_0_OR_GREATER
+ internal static HttpRequestOptionsKey SkipErrorHandlingOption = new(nameof(SkipErrorHandling));
+#elif NET462 || NETSTANDARD2_0
+ internal const string SkipErrorHandlingOption = nameof(SkipErrorHandling);
+#endif
+
+ internal static HttpRequestMessage SkipErrorHandling(this HttpRequestMessage request, bool skip = true)
+ {
+#if NET5_0_OR_GREATER
+ request.Options.Set(SkipErrorHandlingOption, skip);
+#elif NET462 || NETSTANDARD2_0
+ request.Properties[SkipErrorHandlingOption] = skip;
+#endif
+ return request;
+ }
+
+ internal static bool ShouldSkipErrorHandling(this HttpRequestMessage request)
+ {
+#if NET5_0_OR_GREATER
+ return request.Options.TryGetValue(SkipErrorHandlingOption, out var doNotErrorHandle) && doNotErrorHandle;
+#elif NET462 || NETSTANDARD2_0
+ return request.Properties.TryGetValue(SkipErrorHandlingOption, out var shouldSkipOptionObject)
+ && shouldSkipOptionObject is bool shouldSkipOption
+ && shouldSkipOption;
+#endif
+ }
}
\ No newline at end of file
diff --git a/src/Sdk/PasswordlessOptions.cs b/src/Passwordless/PasswordlessOptions.cs
similarity index 94%
rename from src/Sdk/PasswordlessOptions.cs
rename to src/Passwordless/PasswordlessOptions.cs
index 2ccecf9..1748ae5 100644
--- a/src/Sdk/PasswordlessOptions.cs
+++ b/src/Passwordless/PasswordlessOptions.cs
@@ -1,33 +1,33 @@
-namespace Passwordless.Net;
-
-///
-/// Represents all the options you can use to configure a backend Passwordless system.
-///
-public class PasswordlessOptions
-{
- ///
- /// Passwordless Cloud Url
- ///
- public const string CloudApiUrl = "https://v4.passwordless.dev";
-
- ///
- /// Gets or sets the url to use for Passwordless operations.
- ///
- ///
- /// Defaults to .
- ///
- public string ApiUrl { get; set; } = CloudApiUrl;
-
- ///
- /// Gets or sets the secret API key used to authenticate with the Passwordless API.
- ///
- public string ApiSecret { get; set; } = default!;
-
- ///
- /// Gets or sets the public API key used to interact with the Passwordless API.
- ///
- ///
- /// Optional: Only used for frontend operations by the JS Client. E.g: Useful if you're using MVC/Razor pages
- ///
- public string? ApiKey { get; set; }
+namespace Passwordless;
+
+///
+/// Represents all the options you can use to configure a backend Passwordless system.
+///
+public class PasswordlessOptions
+{
+ ///
+ /// Passwordless Cloud Url
+ ///
+ public const string CloudApiUrl = "https://v4.passwordless.dev";
+
+ ///
+ /// Gets or sets the url to use for Passwordless operations.
+ ///
+ ///
+ /// Defaults to .
+ ///
+ public string ApiUrl { get; set; } = CloudApiUrl;
+
+ ///
+ /// Gets or sets the secret API key used to authenticate with the Passwordless API.
+ ///
+ public string ApiSecret { get; set; } = default!;
+
+ ///
+ /// Gets or sets the public API key used to interact with the Passwordless API.
+ ///
+ ///
+ /// Optional: Only used for frontend operations by the JS Client. E.g: Useful if you're using MVC/Razor pages
+ ///
+ public string? ApiKey { get; set; }
}
\ No newline at end of file
diff --git a/src/Sdk/Pollyfill.cs b/src/Passwordless/Pollyfill.cs
similarity index 97%
rename from src/Sdk/Pollyfill.cs
rename to src/Passwordless/Pollyfill.cs
index 63234d9..3b9f508 100644
--- a/src/Sdk/Pollyfill.cs
+++ b/src/Passwordless/Pollyfill.cs
@@ -1,143 +1,143 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Diagnostics.CodeAnalysis
-{
-#if INCLUDE_DYNAMICALLY_ACCESSED_MEMBERS
- ///
- /// Indicates that certain members on a specified are accessed dynamically,
- /// for example through .
- ///
- ///
- /// This allows tools to understand which members are being accessed during the execution
- /// of a program.
- ///
- /// This attribute is valid on members whose type is or .
- ///
- /// When this attribute is applied to a location of type , the assumption is
- /// that the string represents a fully qualified type name.
- ///
- /// When this attribute is applied to a class, interface, or struct, the members specified
- /// can be accessed dynamically on instances returned from calling
- /// on instances of that class, interface, or struct.
- ///
- /// If the attribute is applied to a method it's treated as a special case and it implies
- /// the attribute should be applied to the "this" parameter of the method. As such the attribute
- /// should only be used on instance methods of types assignable to System.Type (or string, but no methods
- /// will use it there).
- ///
- [AttributeUsage(
- AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
- AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
- AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
- Inherited = false)]
- internal sealed class DynamicallyAccessedMembersAttribute : Attribute
- {
- ///
- /// Initializes a new instance of the class
- /// with the specified member types.
- ///
- /// The types of members dynamically accessed.
- public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
- {
- MemberTypes = memberTypes;
- }
-
- ///
- /// Gets the which specifies the type
- /// of members dynamically accessed.
- ///
- public DynamicallyAccessedMemberTypes MemberTypes { get; }
- }
-
- ///
- /// Specifies the types of members that are dynamically accessed.
- ///
- /// This enumeration has a attribute that allows a
- /// bitwise combination of its member values.
- ///
- [Flags]
- internal enum DynamicallyAccessedMemberTypes
- {
- ///
- /// Specifies no members.
- ///
- None = 0,
-
- ///
- /// Specifies the default, parameterless public constructor.
- ///
- PublicParameterlessConstructor = 0x0001,
-
- ///
- /// Specifies all public constructors.
- ///
- PublicConstructors = 0x0002 | PublicParameterlessConstructor,
-
- ///
- /// Specifies all non-public constructors.
- ///
- NonPublicConstructors = 0x0004,
-
- ///
- /// Specifies all public methods.
- ///
- PublicMethods = 0x0008,
-
- ///
- /// Specifies all non-public methods.
- ///
- NonPublicMethods = 0x0010,
-
- ///
- /// Specifies all public fields.
- ///
- PublicFields = 0x0020,
-
- ///
- /// Specifies all non-public fields.
- ///
- NonPublicFields = 0x0040,
-
- ///
- /// Specifies all public nested types.
- ///
- PublicNestedTypes = 0x0080,
-
- ///
- /// Specifies all non-public nested types.
- ///
- NonPublicNestedTypes = 0x0100,
-
- ///
- /// Specifies all public properties.
- ///
- PublicProperties = 0x0200,
-
- ///
- /// Specifies all non-public properties.
- ///
- NonPublicProperties = 0x0400,
-
- ///
- /// Specifies all public events.
- ///
- PublicEvents = 0x0800,
-
- ///
- /// Specifies all non-public events.
- ///
- NonPublicEvents = 0x1000,
-
- ///
- /// Specifies all interfaces implemented by the type.
- ///
- Interfaces = 0x2000,
-
- ///
- /// Specifies all members.
- ///
- All = ~None
- }
-#endif
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Diagnostics.CodeAnalysis
+{
+#if INCLUDE_DYNAMICALLY_ACCESSED_MEMBERS
+ ///
+ /// Indicates that certain members on a specified are accessed dynamically,
+ /// for example through .
+ ///
+ ///
+ /// This allows tools to understand which members are being accessed during the execution
+ /// of a program.
+ ///
+ /// This attribute is valid on members whose type is or .
+ ///
+ /// When this attribute is applied to a location of type , the assumption is
+ /// that the string represents a fully qualified type name.
+ ///
+ /// When this attribute is applied to a class, interface, or struct, the members specified
+ /// can be accessed dynamically on instances returned from calling
+ /// on instances of that class, interface, or struct.
+ ///
+ /// If the attribute is applied to a method it's treated as a special case and it implies
+ /// the attribute should be applied to the "this" parameter of the method. As such the attribute
+ /// should only be used on instance methods of types assignable to System.Type (or string, but no methods
+ /// will use it there).
+ ///
+ [AttributeUsage(
+ AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
+ AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
+ AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
+ Inherited = false)]
+ internal sealed class DynamicallyAccessedMembersAttribute : Attribute
+ {
+ ///
+ /// Initializes a new instance of the class
+ /// with the specified member types.
+ ///
+ /// The types of members dynamically accessed.
+ public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
+ {
+ MemberTypes = memberTypes;
+ }
+
+ ///
+ /// Gets the which specifies the type
+ /// of members dynamically accessed.
+ ///
+ public DynamicallyAccessedMemberTypes MemberTypes { get; }
+ }
+
+ ///
+ /// Specifies the types of members that are dynamically accessed.
+ ///
+ /// This enumeration has a attribute that allows a
+ /// bitwise combination of its member values.
+ ///
+ [Flags]
+ internal enum DynamicallyAccessedMemberTypes
+ {
+ ///
+ /// Specifies no members.
+ ///
+ None = 0,
+
+ ///
+ /// Specifies the default, parameterless public constructor.
+ ///
+ PublicParameterlessConstructor = 0x0001,
+
+ ///
+ /// Specifies all public constructors.
+ ///
+ PublicConstructors = 0x0002 | PublicParameterlessConstructor,
+
+ ///
+ /// Specifies all non-public constructors.
+ ///
+ NonPublicConstructors = 0x0004,
+
+ ///
+ /// Specifies all public methods.
+ ///
+ PublicMethods = 0x0008,
+
+ ///
+ /// Specifies all non-public methods.
+ ///
+ NonPublicMethods = 0x0010,
+
+ ///
+ /// Specifies all public fields.
+ ///
+ PublicFields = 0x0020,
+
+ ///
+ /// Specifies all non-public fields.
+ ///
+ NonPublicFields = 0x0040,
+
+ ///
+ /// Specifies all public nested types.
+ ///
+ PublicNestedTypes = 0x0080,
+
+ ///
+ /// Specifies all non-public nested types.
+ ///
+ NonPublicNestedTypes = 0x0100,
+
+ ///
+ /// Specifies all public properties.
+ ///
+ PublicProperties = 0x0200,
+
+ ///
+ /// Specifies all non-public properties.
+ ///
+ NonPublicProperties = 0x0400,
+
+ ///
+ /// Specifies all public events.
+ ///
+ PublicEvents = 0x0800,
+
+ ///
+ /// Specifies all non-public events.
+ ///
+ NonPublicEvents = 0x1000,
+
+ ///
+ /// Specifies all interfaces implemented by the type.
+ ///
+ Interfaces = 0x2000,
+
+ ///
+ /// Specifies all members.
+ ///
+ All = ~None
+ }
+#endif
}
\ No newline at end of file
diff --git a/src/Sdk/ServiceCollectionExtensions.cs b/src/Passwordless/ServiceCollectionExtensions.cs
similarity index 96%
rename from src/Sdk/ServiceCollectionExtensions.cs
rename to src/Passwordless/ServiceCollectionExtensions.cs
index fc64789..8febcb3 100644
--- a/src/Sdk/ServiceCollectionExtensions.cs
+++ b/src/Passwordless/ServiceCollectionExtensions.cs
@@ -1,52 +1,52 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Net.Http;
-using Microsoft.Extensions.Options;
-using Passwordless.Net;
-
-// This is a trick to always show up in a class when people are registering services
-namespace Microsoft.Extensions.DependencyInjection;
-
-public static class ServiceCollectionExtensions
-{
- public static IServiceCollection AddPasswordlessSdk(this IServiceCollection services, Action configureOptions)
- {
- services.AddOptions()
- .Configure(configureOptions)
- .PostConfigure(options => options.ApiUrl ??= PasswordlessOptions.CloudApiUrl)
- .Validate(options => !string.IsNullOrEmpty(options.ApiSecret), "Passwordless: Missing ApiSecret");
-
- services.AddPasswordlessClientCore((sp, client) =>
- {
- var options = sp.GetRequiredService>().Value;
-
- client.BaseAddress = new Uri(options.ApiUrl);
- client.DefaultRequestHeaders.Add("ApiSecret", options.ApiSecret);
- });
-
- // TODO: Get rid of this service, all consumers should use the interface
- services.AddTransient(sp => (PasswordlessClient)sp.GetRequiredService());
-
- return services;
- }
-
- ///
- /// Helper method for making custom typed HttpClient implementations that also have
- /// the inner handler for throwing fancy exceptions. Not intended for public use,
- /// hence the hiding of it in IDE's.
- ///
- ///
- /// This method signature is subject to change without major version bump/announcement.
- ///
- internal static IServiceCollection AddPasswordlessClientCore<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection services, Action configureClient)
- where TClient : class
- where TImplementation : class, TClient
- {
- services.AddTransient();
-
- services
- .AddHttpClient(configureClient)
- .AddHttpMessageHandler();
-
- return services;
- }
+using System.Diagnostics.CodeAnalysis;
+using System.Net.Http;
+using Microsoft.Extensions.Options;
+using Passwordless;
+
+// This is a trick to always show up in a class when people are registering services
+namespace Microsoft.Extensions.DependencyInjection;
+
+public static class ServiceCollectionExtensions
+{
+ public static IServiceCollection AddPasswordlessSdk(this IServiceCollection services, Action configureOptions)
+ {
+ services.AddOptions()
+ .Configure(configureOptions)
+ .PostConfigure(options => options.ApiUrl ??= PasswordlessOptions.CloudApiUrl)
+ .Validate(options => !string.IsNullOrEmpty(options.ApiSecret), "Passwordless: Missing ApiSecret");
+
+ services.AddPasswordlessClientCore((sp, client) =>
+ {
+ var options = sp.GetRequiredService>().Value;
+
+ client.BaseAddress = new Uri(options.ApiUrl);
+ client.DefaultRequestHeaders.Add("ApiSecret", options.ApiSecret);
+ });
+
+ // TODO: Get rid of this service, all consumers should use the interface
+ services.AddTransient(sp => (PasswordlessClient)sp.GetRequiredService());
+
+ return services;
+ }
+
+ ///
+ /// Helper method for making custom typed HttpClient implementations that also have
+ /// the inner handler for throwing fancy exceptions. Not intended for public use,
+ /// hence the hiding of it in IDE's.
+ ///
+ ///
+ /// This method signature is subject to change without major version bump/announcement.
+ ///
+ internal static IServiceCollection AddPasswordlessClientCore<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TClient, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection services, Action configureClient)
+ where TClient : class
+ where TImplementation : class, TClient
+ {
+ services.AddTransient();
+
+ services
+ .AddHttpClient(configureClient)
+ .AddHttpMessageHandler();
+
+ return services;
+ }
}
\ No newline at end of file
diff --git a/tests/Sdk.Tests/ApiFactAttribute.cs b/tests/Passwordless.Tests/ApiFactAttribute.cs
similarity index 85%
rename from tests/Sdk.Tests/ApiFactAttribute.cs
rename to tests/Passwordless.Tests/ApiFactAttribute.cs
index 8286407..116486b 100644
--- a/tests/Sdk.Tests/ApiFactAttribute.cs
+++ b/tests/Passwordless.Tests/ApiFactAttribute.cs
@@ -1,14 +1,14 @@
-// Uncomment line while running API in mock mode to run tests
-// #define RUNNING_API
-
-namespace Passwordless.Net.Tests;
-
-public class ApiFactAttribute : FactAttribute
-{
- public ApiFactAttribute()
- {
-#if !RUNNING_API
- Skip = "These tests are skipped unless you are running the API locally.";
-#endif
- }
+// Uncomment line while running API in mock mode to run tests
+// #define RUNNING_API
+
+namespace Passwordless.Tests;
+
+public class ApiFactAttribute : FactAttribute
+{
+ public ApiFactAttribute()
+ {
+#if !RUNNING_API
+ Skip = "These tests are skipped unless you are running the API locally.";
+#endif
+ }
}
\ No newline at end of file
diff --git a/tests/Sdk.Tests/Sdk.Tests.csproj b/tests/Passwordless.Tests/Passwordless.Tests.csproj
similarity index 85%
rename from tests/Sdk.Tests/Sdk.Tests.csproj
rename to tests/Passwordless.Tests/Passwordless.Tests.csproj
index e62fda2..5d042a6 100644
--- a/tests/Sdk.Tests/Sdk.Tests.csproj
+++ b/tests/Passwordless.Tests/Passwordless.Tests.csproj
@@ -1,13 +1,11 @@
- false
- true
- Passwordless.Net.Tests
- Passwordless.Net.Tests
net6.0;net7.0
$(TargetFrameworks);net462
$(TargetFrameworks);$(CurrentPreviewTfm)
+ false
+ true
@@ -20,7 +18,7 @@
-
+
diff --git a/tests/Sdk.Tests/PasswordlessClientTests.cs b/tests/Passwordless.Tests/PasswordlessClientTests.cs
similarity index 95%
rename from tests/Sdk.Tests/PasswordlessClientTests.cs
rename to tests/Passwordless.Tests/PasswordlessClientTests.cs
index c5fe3e6..032f20f 100644
--- a/tests/Sdk.Tests/PasswordlessClientTests.cs
+++ b/tests/Passwordless.Tests/PasswordlessClientTests.cs
@@ -1,125 +1,125 @@
-using System.Net.Http;
-using System.Text.Json;
-using Microsoft.Extensions.DependencyInjection;
-
-
-namespace Passwordless.Net.Tests;
-
-public class PasswordlessClientTests
-{
- private readonly PasswordlessClient _sut;
-
- public PasswordlessClientTests()
- {
- var services = new ServiceCollection();
-
- services.AddPasswordlessSdk(options =>
- {
- options.ApiUrl = "https://localhost:7002";
- options.ApiSecret = "test:secret:a679563b331846c79c20b114a4f56d02";
- });
-
- var provider = services.BuildServiceProvider();
-
- _sut = (PasswordlessClient)provider.GetRequiredService();
- }
-
- [ApiFact]
- public async Task CreateRegisterTokenAsync_ThrowsExceptionWhenBad()
- {
- var exception = await Assert.ThrowsAnyAsync(
- async () => await _sut.CreateRegisterTokenAsync(new RegisterOptions(null!, null!)));
- }
-
- [ApiFact]
- public async Task VerifyTokenAsync_DoesNotThrowOnBadToken()
- {
- var verifiedUser = await _sut.VerifyTokenAsync("bad_token");
-
- Assert.Null(verifiedUser);
- }
-
- [ApiFact]
- public async Task DeleteUserAsync_BadUserId_ThrowsException()
- {
- var exception = await Assert.ThrowsAnyAsync(
- async () => await _sut.DeleteUserAsync(null!));
- }
-
- [ApiFact]
- public async Task ListAsiasesAsync_BadUserId_ThrowsException()
- {
- var exception = await Assert.ThrowsAnyAsync(
- async () => await _sut.ListAliasesAsync(null!));
- }
-
- [ApiFact]
- public async Task ListCredentialsAsync_BadUserId_ThrowsException()
- {
- var exception = await Assert.ThrowsAnyAsync(
- async () => await _sut.ListCredentialsAsync(null!));
-
- var errorCode = Assert.Contains("errorCode", (IDictionary)exception.Details.Extensions);
- Assert.Equal(JsonValueKind.String, errorCode.ValueKind);
- Assert.Equal("missing_userid", errorCode.GetString());
- }
-
- [ApiFact]
- public async Task CreateRegisterTokenAsync_Works()
- {
- var userId = Guid.NewGuid().ToString();
-
- var response = await _sut.CreateRegisterTokenAsync(new RegisterOptions(userId, "test_username"));
-
- Assert.NotNull(response.Token);
- Assert.StartsWith("register_", response.Token);
- }
-
- [ApiFact]
- public async Task VerifyTokenAsync_Works()
- {
- var user = await _sut.VerifyTokenAsync("verify_valid");
-
- Assert.NotNull(user);
- Assert.True(user.Success);
- }
-
- [ApiFact]
- public async Task ListUsersAsync_Works()
- {
- var users = await _sut.ListUsersAsync();
-
- Assert.NotEmpty(users);
- }
-
- [ApiFact]
- public async Task ListAliasesAsync_Works()
- {
- // Act
- var aliases = await _sut.ListAliasesAsync("has_aliases");
-
- // Assert
- Assert.NotEmpty(aliases);
- }
-
- [ApiFact]
- public async Task ListCredentialsAsync_Works()
- {
- var credentials = await _sut.ListCredentialsAsync("has_credentials");
-
- Assert.NotEmpty(credentials);
- }
-
- [ApiFact]
- public async Task DeleteCredentialAsync_Works()
- {
- await _sut.DeleteCredentialAsync("can_delete");
- }
-
- [ApiFact]
- public async Task GetUsersCountAsync_Works()
- {
- var usersCount = await _sut.GetUsersCountAsync();
- Assert.NotEqual(0, usersCount.Count);
- }
+using System.Net.Http;
+using System.Text.Json;
+using Microsoft.Extensions.DependencyInjection;
+
+
+namespace Passwordless.Tests;
+
+public class PasswordlessClientTests
+{
+ private readonly PasswordlessClient _sut;
+
+ public PasswordlessClientTests()
+ {
+ var services = new ServiceCollection();
+
+ services.AddPasswordlessSdk(options =>
+ {
+ options.ApiUrl = "https://localhost:7002";
+ options.ApiSecret = "test:secret:a679563b331846c79c20b114a4f56d02";
+ });
+
+ var provider = services.BuildServiceProvider();
+
+ _sut = (PasswordlessClient)provider.GetRequiredService();
+ }
+
+ [ApiFact]
+ public async Task CreateRegisterTokenAsync_ThrowsExceptionWhenBad()
+ {
+ var exception = await Assert.ThrowsAnyAsync(
+ async () => await _sut.CreateRegisterTokenAsync(new RegisterOptions(null!, null!)));
+ }
+
+ [ApiFact]
+ public async Task VerifyTokenAsync_DoesNotThrowOnBadToken()
+ {
+ var verifiedUser = await _sut.VerifyTokenAsync("bad_token");
+
+ Assert.Null(verifiedUser);
+ }
+
+ [ApiFact]
+ public async Task DeleteUserAsync_BadUserId_ThrowsException()
+ {
+ var exception = await Assert.ThrowsAnyAsync(
+ async () => await _sut.DeleteUserAsync(null!));
+ }
+
+ [ApiFact]
+ public async Task ListAsiasesAsync_BadUserId_ThrowsException()
+ {
+ var exception = await Assert.ThrowsAnyAsync(
+ async () => await _sut.ListAliasesAsync(null!));
+ }
+
+ [ApiFact]
+ public async Task ListCredentialsAsync_BadUserId_ThrowsException()
+ {
+ var exception = await Assert.ThrowsAnyAsync(
+ async () => await _sut.ListCredentialsAsync(null!));
+
+ var errorCode = Assert.Contains("errorCode", (IDictionary)exception.Details.Extensions);
+ Assert.Equal(JsonValueKind.String, errorCode.ValueKind);
+ Assert.Equal("missing_userid", errorCode.GetString());
+ }
+
+ [ApiFact]
+ public async Task CreateRegisterTokenAsync_Works()
+ {
+ var userId = Guid.NewGuid().ToString();
+
+ var response = await _sut.CreateRegisterTokenAsync(new RegisterOptions(userId, "test_username"));
+
+ Assert.NotNull(response.Token);
+ Assert.StartsWith("register_", response.Token);
+ }
+
+ [ApiFact]
+ public async Task VerifyTokenAsync_Works()
+ {
+ var user = await _sut.VerifyTokenAsync("verify_valid");
+
+ Assert.NotNull(user);
+ Assert.True(user.Success);
+ }
+
+ [ApiFact]
+ public async Task ListUsersAsync_Works()
+ {
+ var users = await _sut.ListUsersAsync();
+
+ Assert.NotEmpty(users);
+ }
+
+ [ApiFact]
+ public async Task ListAliasesAsync_Works()
+ {
+ // Act
+ var aliases = await _sut.ListAliasesAsync("has_aliases");
+
+ // Assert
+ Assert.NotEmpty(aliases);
+ }
+
+ [ApiFact]
+ public async Task ListCredentialsAsync_Works()
+ {
+ var credentials = await _sut.ListCredentialsAsync("has_credentials");
+
+ Assert.NotEmpty(credentials);
+ }
+
+ [ApiFact]
+ public async Task DeleteCredentialAsync_Works()
+ {
+ await _sut.DeleteCredentialAsync("can_delete");
+ }
+
+ [ApiFact]
+ public async Task GetUsersCountAsync_Works()
+ {
+ var usersCount = await _sut.GetUsersCountAsync();
+ Assert.NotEqual(0, usersCount.Count);
+ }
}
\ No newline at end of file
diff --git a/tests/Sdk.Tests/Usings.cs b/tests/Passwordless.Tests/Usings.cs
similarity index 100%
rename from tests/Sdk.Tests/Usings.cs
rename to tests/Passwordless.Tests/Usings.cs