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 }
/// <summary> /// Returns CredentialCreateOptions including a challenge to be sent to the browser/authr to create new credentials /// </summary> /// <returns></returns> /// <param name="attestationPreference">This member is intended for use by Relying Parties that wish to express their preference for attestation conveyance. The default is none.</param> /// <param name="excludeCredentials">Recommended. This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account on a single authenticator.The client is requested to return an error if the new credential would be created on an authenticator that also contains one of the credentials enumerated in this parameter.</param> public CredentialCreateOptions RequestNewCredential( Fido2User user, List <PublicKeyCredentialDescriptor> excludeCredentials, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationPreference, AuthenticationExtensionsClientInputs extensions = null) { var challenge = new byte[_config.ChallengeSize]; _crypto.GetBytes(challenge); var options = CredentialCreateOptions.Create(_config, challenge, user, authenticatorSelection, attestationPreference, excludeCredentials, extensions); return(options); }
public static string MakeWebAuthnAttestationRequest(Fido2Configuration fido2Config, byte[] challenge, LoginUsr LUser, List <PublicKeyCredentialDescriptor> excludedCredentials) { string usrId = LUser.UsrId.ToString(); string usrIdB64 = System.Convert.ToBase64String(usrId.ToUtf8ByteArray()); Fido2User user = new Fido2User { DisplayName = LUser.UsrName, /* must be restricted to no more than than 64 for device like yubikey as it would fail without reason */ //Name = (Guid.NewGuid().ToString() + " " + DateTime.UtcNow.ToString("o")).Left(64), //Id= Guid.NewGuid().ToString().ToUtf8ByteArray() Name = LUser.LoginName, Id = usrIdB64.ToUtf8ByteArray() }; AuthenticatorSelection authenticatorSelection = new AuthenticatorSelection { RequireResidentKey = false, UserVerification = UserVerificationRequirement.Discouraged, // AuthenticatorAttachment = AuthenticatorAttachment.Platform, }; AttestationConveyancePreference attConveyancePreference = AttestationConveyancePreference.None; AuthenticationExtensionsClientInputs clientExtensions = new AuthenticationExtensionsClientInputs { Extensions = true, SimpleTransactionAuthorization = string.Format("you are registering to {0}", fido2Config.ServerName), Location = true, UserVerificationMethod = true, BiometricAuthenticatorPerformanceBounds = new AuthenticatorBiometricPerfBounds { FAR = float.MaxValue, FRR = float.MaxValue } }; var fido2 = new Fido2(fido2Config); // must do this for the verification to work var options = fido2.RequestNewCredential(user, excludedCredentials, authenticatorSelection, attConveyancePreference, clientExtensions); // the challenge is random byte but we need more info, replace it options.Challenge = challenge; var createRequest = Fido2NetLib.CredentialCreateOptions.Create(fido2Config , challenge, user, authenticatorSelection, attConveyancePreference , excludedCredentials != null && excludedCredentials.Count > 0 ? excludedCredentials : null , clientExtensions); string createRequestJson = options.ToJson(); return(createRequestJson); }
/// <summary> /// Create static method implementation /// </summary> public static RegisterCredentialOptions Create(Fido2Configuration config, byte[] challenge, Fido2User user, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationConveyancePreference, List <PublicKeyCredentialDescriptor> excludeCredentials, AuthenticationExtensionsClientInputs extensions) { return(new RegisterCredentialOptions { Status = "ok", ErrorMessage = string.Empty, Challenge = challenge, Rp = new PublicKeyCredentialRpEntity(config.ServerDomain, config.ServerName, config.ServerIcon), Timeout = config.Timeout, User = user, PubKeyCredParams = new List <PubKeyCredParam>() { // Add additional as appropriate ES256, RS256, PS256, ES384, RS384, PS384, ES512, RS512, PS512, }, AuthenticatorSelection = authenticatorSelection, Attestation = attestationConveyancePreference, ExcludeCredentials = excludeCredentials ?? new List <PublicKeyCredentialDescriptor>(), Extensions = extensions }); }
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) })); } }
/// <summary> /// Returns CredentialCreateOptions including a challenge to be sent to the browser/authr to create new credentials /// </summary> /// <returns></returns> /// <param name="attestationPreference">This member is intended for use by Relying Parties that wish to express their preference for attestation conveyance. The default is none.</param> /// <param name="excludeCredentials">Recommended. This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account on a single authenticator.The client is requested to return an error if the new credential would be created on an authenticator that also contains one of the credentials enumerated in this parameter.</param> public CredentialCreateOptions RequestNewCredential(User user, List <PublicKeyCredentialDescriptor> excludeCredentials, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationPreference) { // note: I have no idea if this crypto is ok... var challenge = new byte[Config.ChallengeSize]; _crypto.GetBytes(challenge); var options = CredentialCreateOptions.Create(Config, challenge, user, authenticatorSelection, attestationPreference, excludeCredentials); return(options); }
public static CredentialCreateOptions Create(Configuration config, byte[] challenge, User user, AuthenticatorSelection authenticatorSelection, AttestationConveyancePreference attestationConveyancePreference, List <PublicKeyCredentialDescriptor> excludeCredentials) { return(new CredentialCreateOptions { Status = "ok", ErrorMessage = string.Empty, Challenge = challenge, Rp = new Rp(config.ServerDomain, config.ServerName), Timeout = config.Timeout, User = user, PubKeyCredParams = new List <PubKeyCredParam>() { // Add additional as appropriate ES256, RS256, PS256, ES384, RS384, PS384, ES512, RS512, PS512, RS1 }, AuthenticatorSelection = authenticatorSelection, Attestation = attestationConveyancePreference, ExcludeCredentials = excludeCredentials ?? new List <PublicKeyCredentialDescriptor>() }); }
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()); }