public RawAuthenticatorMakeCredentialOptions(AuthenticatorMakeCredentialOptions makeOptions) { ExcludeCredentialsList = new RawCredentialsList(makeOptions.ExcludeCredentials); if (makeOptions.ExcludeCredentialsEx?.Count > 0) { _excludeCredentialsExList = new RawCredentialExList(makeOptions.ExcludeCredentialsEx); ExcludeCredentialsExListPtr = Marshal.AllocHGlobal(Marshal.SizeOf<RawCredentialExList>()); Marshal.StructureToPtr(_excludeCredentialsExList, ExcludeCredentialsExListPtr, false); } CancellationId = IntPtr.Zero; if (makeOptions.CancellationId.HasValue) { CancellationId = Marshal.AllocHGlobal(Marshal.SizeOf<Guid>()); Marshal.StructureToPtr(makeOptions.CancellationId.Value, CancellationId, false); } TimeoutMilliseconds = makeOptions.TimeoutMilliseconds; AuthenticatorAttachment = makeOptions.AuthenticatorAttachment; UserVerificationRequirement = makeOptions.UserVerificationRequirement; AttestationConveyancePreference = makeOptions.AttestationConveyancePreference; RequireResidentKey = makeOptions.RequireResidentKey; Extensions = new RawWebauthnExtensions { Count = 0, Extensions = IntPtr.Zero }; //TODO }
public RawAuthenticatorGetAssertionOptions(AuthenticatorGetAssertionOptions getOptions) { AllowCredentialsList = new RawCredentialsList(getOptions.AllowedCredentials); if (getOptions.AllowedCredentialsEx?.Count > 0) { _allowedCredentialsExList = new RawCredentialExList(getOptions.AllowedCredentialsEx); AllowCredentialsExListPtr = Marshal.AllocHGlobal(Marshal.SizeOf <RawCredentialExList>()); Marshal.StructureToPtr(_allowedCredentialsExList, AllowCredentialsExListPtr, false); } CancellationId = IntPtr.Zero; if (getOptions.CancellationId.HasValue) { CancellationId = Marshal.AllocHGlobal(Marshal.SizeOf <Guid>()); Marshal.StructureToPtr(getOptions.CancellationId.Value, CancellationId, false); } U2fAppId = getOptions.U2fAppId; U2fAppIdUsedBoolPtr = Marshal.AllocHGlobal(Marshal.SizeOf <bool>()); TimeoutMilliseconds = getOptions.TimeoutMilliseconds; AuthenticatorAttachment = getOptions.AuthenticatorAttachment; UserVerificationRequirement = getOptions.UserVerificationRequirement; Extensions = new RawWebauthnExtensions { Count = 0, Extensions = IntPtr.Zero }; //TODO }
/// <summary> /// GetLoginAssertionsOptions method implementation /// </summary> private string GetLoginAssertionsOptions(AuthenticationContext ctx) { try { List <MFAPublicKeyCredentialDescriptor> existingCredentials = new List <MFAPublicKeyCredentialDescriptor>(); if (!string.IsNullOrEmpty(ctx.UPN)) { var user = RuntimeRepository.GetUser(Config, ctx.UPN); if (user == null) { throw new ArgumentException("Username was not registered"); } existingCredentials = RuntimeRepository.GetCredentialsByUser(Config, user).Select(c => c.Descriptor).ToList(); } AuthenticationExtensionsClientInputs exts = new AuthenticationExtensionsClientInputs() { SimpleTransactionAuthorization = "FIDO", GenericTransactionAuthorization = new TxAuthGenericArg { ContentType = "text/plain", Content = new byte[] { 0x46, 0x49, 0x44, 0x4F } }, UserVerificationIndex = this.UserVerificationIndex, Location = this.Location, UserVerificationMethod = this.UserVerificationMethod, EnforceCredProtect = this.EnforceCredProtect, CredProtect = this.CredProtect, HmacSecret = this.HmacSecret }; UserVerificationRequirement uv = this.UserVerificationRequirement.ToEnum <UserVerificationRequirement>(); AssertionOptions options = _webathn.GetAssertionOptions(existingCredentials.ToCore(), uv, exts); string result = options.ToJson(); ctx.AssertionOptions = result; return(result); } catch (Exception e) { Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), EventLogEntryType.Error, 5000); string result = (new AssertionOptions { Status = "error", ErrorMessage = string.Format("{0}{1}", e.Message, e.InnerException != null ? " (" + e.InnerException.Message + ")" : "") }).ToJson(); ctx.AssertionOptions = result; return(result); } }
/// <summary> /// GetLoginAssertionsOptions method implementation /// </summary> private string GetLoginAssertionsOptions(AuthenticationContext ctx) { try { List <MFAPublicKeyCredentialDescriptor> existingCredentials = new List <MFAPublicKeyCredentialDescriptor>(); if (!string.IsNullOrEmpty(ctx.UPN)) { var user = RuntimeRepository.GetUser(Config, ctx.UPN); if (user == null) { throw new ArgumentException("Username was not registered"); } existingCredentials = RuntimeRepository.GetCredentialsByUser(Config, user).Select(c => c.Descriptor).ToList(); } AuthenticationExtensionsClientInputs exts = new AuthenticationExtensionsClientInputs() { Extensions = this.Extentions, UserVerificationMethod = this.UserVerificationMethod, }; UserVerificationRequirement uv = this.UserVerificationRequirement; AssertionOptions options = null; if (existingCredentials.Count > 0) { options = _webathn.GetAssertionOptions(existingCredentials.ToCore(), uv, exts); } else { options = _webathn.GetAssertionOptions(null, uv, exts); } string result = options.ToJson(); ctx.AssertionOptions = result; return(result); } catch (Exception e) { Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), EventLogEntryType.Error, 5000); string result = (new AssertionOptions { Status = "error", ErrorMessage = string.Format("{0} / {1}", e.Message, e.InnerException != null ? " (" + e.InnerException.Message + ")" : "") }).ToJson(); ctx.AssertionOptions = result; return(result); } }
public JsonResult MakeCredentialOptions([FromForm] string username, [FromForm] string attType, [FromForm] string authType, [FromForm] bool requireResidentKey, [FromForm] string userVerification) { try { // 1. Get user from DB by username (in our example, auto create missing users) var user = DemoStorage.GetOrAddUser(username, () => new User { DisplayName = "Display " + username, Name = username, Id = Encoding.UTF8.GetBytes(username) // byte representation of userID is required }); // 2. Get user existing keys by username List <PublicKeyCredentialDescriptor> existingKeys = DemoStorage.GetCredentialsByUser(user).Select(c => c.Descriptor).ToList(); // 3. Create options var authenticatorSelection = new AuthenticatorSelection { AuthenticatorAttachment = !string.IsNullOrEmpty(authType) ? AuthenticatorAttachment.Parse(authType) : null, RequireResidentKey = requireResidentKey, UserVerification = UserVerificationRequirement.Parse(userVerification) }; var options = _lib.RequestNewCredential(user, existingKeys, authenticatorSelection, AttestationConveyancePreference.Parse(attType)); // 4. Temporarily store options, session/in-memory cache/redis/db HttpContext.Session.SetString("fido2.attestationOptions", options.ToJson()); // 5. return options to client return(Json(options)); } catch (Exception e) { return(Json(new CredentialCreateOptions { Status = "error", ErrorMessage = FormatException(e) })); } }
internal static AssertionOptions Create(Fido2.Configuration config, byte[] challenge, IEnumerable <PublicKeyCredentialDescriptor> allowedCredentials, UserVerificationRequirement userVerification, AuthenticationExtensionsClientInputs extensions) { return(new AssertionOptions() { Status = "ok", ErrorMessage = string.Empty, Challenge = challenge, Timeout = config.Timeout, RpId = config.ServerDomain, AllowCredentials = allowedCredentials ?? new List <PublicKeyCredentialDescriptor>(), UserVerification = userVerification, Extensions = extensions }); }
/// <summary> /// Returns AssertionOptions including a challenge to the browser/authr to assert existing credentials and authenticate a user. /// </summary> /// <returns></returns> public AssertionOptions GetAssertionOptions(IEnumerable <PublicKeyCredentialDescriptor> allowedCredentials, UserVerificationRequirement userVerification) { var challenge = new byte[Config.ChallengeSize]; _crypto.GetBytes(challenge); var options = AssertionOptions.Create(Config, challenge, allowedCredentials, userVerification); return(options); }
public AuthenticatorSelection() { requireResidentKey = false; authenticatorAttachment = ""; userVerification = UserVerificationRequirement.preferred; }
/// <summary> /// GetRegisterCredentialOptions method implementation /// </summary> private string GetRegisterCredentialOptions(AuthenticationContext ctx) { try { if (string.IsNullOrEmpty(ctx.UPN)) { throw new ArgumentNullException(ctx.UPN); } string attType = this.ConveyancePreference; // none, direct, indirect string authType = this.Attachement; // <empty>, platform, cross-platform UserVerificationRequirement userVerification = this.UserVerificationRequirement; // preferred, required, discouraged bool requireResidentKey = this.RequireResidentKey; // true,false MFAWebAuthNUser user = RuntimeRepository.GetUser(Config, ctx.UPN); if (user != null) { List <MFAPublicKeyCredentialDescriptor> existingKeys = RuntimeRepository.GetCredentialsByUser(Config, user).Select(c => c.Descriptor).ToList(); // 3. Create options AuthenticatorSelection authenticatorSelection = new AuthenticatorSelection { RequireResidentKey = requireResidentKey, UserVerification = userVerification }; if (!string.IsNullOrEmpty(authType)) { authenticatorSelection.AuthenticatorAttachment = authType.ToEnum <AuthenticatorAttachment>(); } AuthenticationExtensionsClientInputs exts = new AuthenticationExtensionsClientInputs() { Extensions = this.Extentions, UserVerificationMethod = this.UserVerificationMethod }; CredentialCreateOptions options = null; if (existingKeys.Count > 0) { options = _webathn.GetRegisterCredentialOptions(user.ToCore(), existingKeys.ToCore(), authenticatorSelection, attType.ToEnum <AttestationConveyancePreference>(), exts); } else { options = _webathn.GetRegisterCredentialOptions(user.ToCore(), null, authenticatorSelection, attType.ToEnum <AttestationConveyancePreference>(), exts); } string result = options.ToJson(); ctx.CredentialOptions = result; return(result); } else { Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !"), EventLogEntryType.Error, 5000); string result = (new CredentialMakeResult { Status = "error", ErrorMessage = string.Format("{0}", "User does not exists !") }).ToJson(); ctx.CredentialOptions = result; return(result); } } catch (Exception e) { Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), System.Diagnostics.EventLogEntryType.Error, 5000); string result = (new CredentialMakeResult { Status = "error", ErrorMessage = string.Format("{0}{1}", e.Message, e.InnerException != null ? " (" + e.InnerException.Message + ")" : "") }).ToJson(); ctx.CredentialOptions = result; return(result); } }
public static PublicKeyCredentialCreationOptions ConvertToPublicKeyCredentialCreationOptions(IFido2Client fido2Client, ServerPublicKeyCredentialCreationOptionsResponse response) { PublicKeyCredentialCreationOptions.Builder builder = new PublicKeyCredentialCreationOptions.Builder(); string name = response.Rp.Name; PublicKeyCredentialRpEntity entity = new PublicKeyCredentialRpEntity(name, name, null); builder.SetRp(entity); string id = response.User.Id; try { builder.SetUser(new PublicKeyCredentialUserEntity(id, System.Text.Encoding.UTF8.GetBytes(id))); } catch (UnsupportedEncodingException e) { Log.Error(Tag, e.Message, e); } builder.SetChallenge(ByteUtils.Base64ToByte(response.Challenge)); if (response.PubKeyCredParams != null) { List <PublicKeyCredentialParameters> parameters = new List <PublicKeyCredentialParameters>(); ServerPublicKeyCredentialParameters[] serverPublicKeyCredentialParameters = response.PubKeyCredParams; foreach (ServerPublicKeyCredentialParameters param in serverPublicKeyCredentialParameters) { try { PublicKeyCredentialParameters parameter = new PublicKeyCredentialParameters( PublicKeyCredentialType.PublicKey, Algorithm.FromCode(param.Alg)); parameters.Add(parameter); } catch (System.Exception e) { Log.Error(Tag, e.Message, e); } } builder.SetPubKeyCredParams(parameters); } if (response.ExcludeCredentials != null) { List <PublicKeyCredentialDescriptor> descriptors = new List <PublicKeyCredentialDescriptor>(); ServerPublicKeyCredentialDescriptor[] serverDescriptors = response.ExcludeCredentials; foreach (ServerPublicKeyCredentialDescriptor desc in serverDescriptors) { List <AuthenticatorTransport> transports = new List <AuthenticatorTransport>(); if (desc.Transports != null) { try { transports.Add(AuthenticatorTransport.FromValue(desc.Transports)); } catch (System.Exception e) { Log.Error(Tag, e.Message, e); } } PublicKeyCredentialDescriptor descriptor = new PublicKeyCredentialDescriptor( PublicKeyCredentialType.PublicKey, ByteUtils.Base64ToByte(desc.Id), transports); descriptors.Add(descriptor); } builder.SetExcludeList(descriptors); } Attachment attachment = null; if (response.AuthenticatorSelection != null) { ServerAuthenticatorSelectionCriteria selectionCriteria = response.AuthenticatorSelection; if (selectionCriteria.AuthenticatorAttachment != null) { try { attachment = Attachment.FromValue(selectionCriteria.AuthenticatorAttachment); } catch (System.Exception e) { Log.Error(Tag, e.Message, e); } } bool residentKey = selectionCriteria.IsRequireResidentKey; UserVerificationRequirement requirement = null; if (selectionCriteria.UserVerification != null) { try { requirement = UserVerificationRequirement.FromValue(selectionCriteria.UserVerification); } catch (System.Exception e) { Log.Error(Tag, e.Message, e); } } AuthenticatorSelectionCriteria fido2Selection = new AuthenticatorSelectionCriteria(attachment, (Java.Lang.Boolean)residentKey, requirement); builder.SetAuthenticatorSelection(fido2Selection); } // attestation if (response.Attestation != null) { try { AttestationConveyancePreference preference = AttestationConveyancePreference.FromValue(response.Attestation); builder.SetAttestation(preference); } catch (System.Exception e) { Log.Error(Tag, e.Message, e); } } Dictionary <string, Java.Lang.Object> extensions = new Dictionary <string, Java.Lang.Object>(); if (response.Extensions != null) { extensions.AddRangeOverride(response.Extensions); } // Specify a platform authenticator and related extension items. You can specify a platform // authenticator or not as needed. if (Attachment.Platform.Equals(attachment)) { UseSelectedPlatformAuthenticator(fido2Client, extensions); } builder.SetExtensions(extensions); builder.SetTimeoutSeconds((Java.Lang.Long)response.Timeout); return(builder.Build()); }