Files
simpleidp/Areas/webauthn/Views/Register/Index.cshtml
2025-08-19 16:58:51 +02:00

179 lines
7.6 KiB
Plaintext

@using FormBuilder.Components.Workflow
@using FormBuilder
@using FormBuilder.Helpers
@using Microsoft.AspNetCore.Http
@using Microsoft.Extensions.Options;
@using SimpleIdServer.IdServer.Options;
@using System.Text.Json
@model SimpleIdServer.IdServer.UI.ViewModels.SidWorkflowViewModel
@inject IOptions<FormBuilderOptions> options
@inject IUriProvider uriProvider
@inject IHttpContextAccessor HttpContextAccessor;
@{
Layout = "~/Views/Shared/_FormBuilderLayout.cshtml";
var antiforgeryToken = HttpContextAccessor.HttpContext.Request.Cookies[options.Value.AntiforgeryCookieName];
Model.AntiforgeryToken.CookieValue = antiforgeryToken;
var step = Model.Workflow?.Steps?.SingleOrDefault(s => s.Id == Model.CurrentStepId);
var beginRegisterUrl = Model.Input["BeginRegisterUrl"].ToString();
var endRegisterUrl = Model.Input["EndRegisterUrl"].ToString();
var returnUrl = Model.Input["ReturnUrl"].ToString();
var isCreated = Model.Input["IsCreated"].ToString();
}
<component type="typeof(WorkflowViewer)"
render-mode="ServerPrerendered"
param-Input="@Model.Input"
param-Workflow="@Model.Workflow"
param-FormRecords="@Model.FormRecords"
param-CurrentStepId="@Model.CurrentStepId"
param-ErrorMessages="@Model.ErrorMessages"
param-SuccessMessages="@Model.SuccessMessages"
param-AntiforgeryToken="@Model.AntiforgeryToken"
param-SupportedLanguageCodes="@Model.SupportedLanguageCodes"
param-Template="@Model.Template" />
@section Header {
@foreach (var cssStyle in Model.Template.CssStyles)
{
<link rel="stylesheet" href="@uriProvider.GetCssUrl(Model.Template.Id, cssStyle)" />
}
@foreach (var jsStyle in Model.Template.JsStyles)
{
<script src="@uriProvider.GetJsUrl(Model.Template.Id, jsStyle)" type="text/javascript"></script>
}
}
@section Scripts {
<script type="text/javascript">
let csharpReference;
var init = function () {
var beginRegisterUrl = "@beginRegisterUrl";
var endRegisterUrl = "@endRegisterUrl";
var redirectUrl = "@returnUrl";
var isCreated = "@isCreated";
var isInitialized = false;
var displayError = function (errorJson) {
csharpReference.invokeMethodAsync("SetErrorMessage", errorJson["error_description"]);
}
var displaySuccessMessage = function () {
csharpReference.invokeMethodAsync("SetSuccessMessage", "User is created");
csharpReference.invokeMethodAsync("ClearErrorMessages");
csharpReference.invokeMethodAsync("SetInputData", isCreated, "true");
$("#webauthForm").hide();
}
async function registerCredential(newCredential, sessionId, login, nextRegistrationRedirectUrl) {
let attestationObject = new Uint8Array(newCredential.response.attestationObject);
let clientDataJSON = new Uint8Array(newCredential.response.clientDataJSON);
let rawId = new Uint8Array(newCredential.rawId);
const serializedAuthenticatorAttestationRawResponse = {
id: newCredential.id,
rawId: coerceToBase64Url(rawId),
type: newCredential.type,
extensions: newCredential.getClientExtensionResults(),
response: {
attestationObject: coerceToBase64Url(attestationObject),
clientDataJSON: coerceToBase64Url(clientDataJSON)
}
};
let response = await fetch(endRegisterUrl, {
method: 'POST',
body: JSON.stringify({
attestation: serializedAuthenticatorAttestationRawResponse,
login: login,
session_id: sessionId
}),
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
});
let responseJson = await response.json();
if (!response.ok) {
displayError(responseJson);
return;
}
if (nextRegistrationRedirectUrl) {
window.location.href = nextRegistrationRedirectUrl;
return;
}
displaySuccessMessage();
}
async function makeCredential(login, displayName) {
let response = await fetch(beginRegisterUrl, {
method: 'POST',
body: JSON.stringify({ login: login, display_name: displayName, credential_type: 'webauthn' }),
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
});
let responseJson = await response.json();
if (!response.ok) {
displayError(responseJson);
return;
}
let makeCredentialOptions = responseJson["credential_create_options"];
let sessionId = responseJson["session_id"];
let nextRegistrationRedirectUrl = null;
if (responseJson['next_registration_redirect_url']) {
nextRegistrationRedirectUrl = responseJson['next_registration_redirect_url'];
}
makeCredentialOptions.challenge = coerceToArrayBuffer(makeCredentialOptions.challenge);
makeCredentialOptions.user.id = coerceToArrayBuffer(makeCredentialOptions.user.id);
makeCredentialOptions.excludeCredentials = makeCredentialOptions.excludeCredentials.map((c) => {
c.id = coerceToArrayBuffer(c.id);
return c;
});
if (makeCredentialOptions.authenticatorSelection.authenticatorAttachment === null) makeCredentialOptions.authenticatorSelection.authenticatorAttachment = undefined;
let newCredential;
try {
newCredential = await navigator.credentials.create({
publicKey: makeCredentialOptions
});
} catch (e) {
var msg = "Could not create credentials in browser. Probably because the username is already registered with your authenticator. Please change username or authenticator."
console.error(msg, e);
return;
}
await registerCredential(newCredential, sessionId, login, nextRegistrationRedirectUrl);
};
var tryListenForm = function () {
const elt = $("#webauthForm");
if (isInitialized === true) return;
if (elt.length === 0) {
setTimeout(() => tryListenForm(), 500);
return;
}
isInitialized = true;
elt.submit(function (e) {
e.preventDefault();
var login = $("#webauthForm input[name='Login']").val();
var displayName = $("#webauthForm input[name='DisplayName']").val();
makeCredential(login, displayName);
});
}
tryListenForm();
};
setCsharpReference = function (ref) {
csharpReference = ref;
init();
};
</script>
}