-
Notifications
You must be signed in to change notification settings - Fork 9
/
Index.razor.cs
151 lines (135 loc) · 5.29 KB
/
Index.razor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using KristofferStrube.Blazor.CredentialManagement;
using KristofferStrube.Blazor.WebAuthentication.JSONRepresentations;
using KristofferStrube.Blazor.WebIDL.Exceptions;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Text;
using static KristofferStrube.Blazor.WebAuthentication.WasmExample.WebAuthenticationClient;
namespace KristofferStrube.Blazor.WebAuthentication.WasmExample.Pages;
public partial class Index : ComponentBase
{
private bool isSupported = false;
private string username = "";
private CredentialsContainer container = default!;
private PublicKeyCredential? credential;
private PublicKeyCredential? validatedCredential;
private bool? validated = null;
private string? errorMessage;
private byte[]? challenge;
private byte[]? publicKey;
[Inject]
public required IJSRuntime JSRuntime { get; set; }
[Inject]
public required WebAuthenticationClient WebAuthenticationClient { get; set; }
protected override async Task OnInitializedAsync()
{
isSupported = await CredentialsService.IsSupportedAsync();
if (!isSupported) return;
container = await CredentialsService.GetCredentialsAsync();
}
private async Task CreateCredential()
{
byte[] userId = Encoding.ASCII.GetBytes(username);
challenge = await WebAuthenticationClient.RegisterChallenge(username);
CredentialCreationOptions options = new()
{
PublicKey = new PublicKeyCredentialCreationOptions()
{
Rp = new PublicKeyCredentialRpEntity
{
Name = "Kristoffer Strube Consulting"
},
User = new PublicKeyCredentialUserEntity()
{
Name = username,
Id = userId,
DisplayName = username
},
Challenge = challenge,
PubKeyCredParams =
[
new PublicKeyCredentialParameters()
{
Type = PublicKeyCredentialType.PublicKey,
Alg = COSEAlgorithm.ES256
},
new PublicKeyCredentialParameters()
{
Type = PublicKeyCredentialType.PublicKey,
Alg = COSEAlgorithm.RS256
}
],
Timeout = 360000,
Hints = "client-device",
Attestation = "none",
AttestationFormats = ["tpm"]
}
};
try
{
credential = await container.CreateAsync(options) is { } c ? new PublicKeyCredential(c) : null;
if (credential is not null)
{
PublicKeyCredentialJSON registrationResponse = await credential.ToJSONAsync();
if (registrationResponse is RegistrationResponseJSON { } registration)
{
await WebAuthenticationClient.Register(username, registration);
publicKey = registration.Response.PublicKey is not null ? Convert.FromBase64String(registration.Response.PublicKey) : null;
}
}
errorMessage = null;
}
catch (DOMException exception)
{
errorMessage = $"{exception.Name}: \"{exception.Message}\"";
credential = null;
}
}
private async Task GetCredential()
{
ValidateCredentials? setup = await WebAuthenticationClient.ValidateChallenge(username);
if (setup is not { Challenge: { Length: > 0 } challenge, Credentials: { Count: > 0 } credentials })
{
errorMessage = "The user was not previously registered.";
return;
}
this.challenge = challenge;
List<PublicKeyCredentialDescriptor> allowCredentials = new(credentials.Count);
foreach (byte[] credential in credentials)
{
allowCredentials.Add(new PublicKeyCredentialDescriptor()
{
Type = PublicKeyCredentialType.PublicKey,
Id = await JSRuntime.InvokeAsync<IJSObjectReference>("buffer", credential)
});
}
CredentialRequestOptions options = new()
{
PublicKey = new PublicKeyCredentialRequestOptions()
{
Challenge = challenge,
Timeout = 360000,
AllowCredentials = allowCredentials.ToArray()
}
};
try
{
validatedCredential = await container.GetAsync(options) is { } c ? new PublicKeyCredential(c) : null;
if (validatedCredential is not null)
{
PublicKeyCredentialJSON authenticationResponse = await validatedCredential.ToJSONAsync();
if (authenticationResponse is AuthenticationResponseJSON { } authentication)
{
validated = await WebAuthenticationClient.Validate(username, authentication);
}
}
errorMessage = null;
}
catch (DOMException exception)
{
errorMessage = $"{exception.Name}: \"{exception.Message}\"";
validatedCredential = null;
validated = false;
}
}
}