public static WebAuthnAssertion VerifyAssertionResult(Fido2Configuration fido2Config, string requestJSON, string resultJSON, Func <string, byte[]> getStoredPublicKey)
        {
            var fido2 = new Fido2(fido2Config);

            IsUserHandleOwnerOfCredentialIdAsync callback = (args) =>
            {
                var u  = args.UserHandle;
                var id = args.CredentialId;
                return(Task.FromResult(true));
            };

            var request = Newtonsoft.Json.JsonConvert.DeserializeObject <AssertionOptions>(requestJSON);
            AuthenticatorAssertionRawResponse assertionResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <AuthenticatorAssertionRawResponse>(resultJSON);
            var  credentialId   = System.Convert.ToBase64String(assertionResponse.Id);
            uint storedCounter  = 0; // 0 means always success
            var  publicKey      = getStoredPublicKey(credentialId);
            var  success        = fido2.MakeAssertionAsync(assertionResponse, request, publicKey, storedCounter, callback).Result;
            var  clientDataJson = Newtonsoft.Json.JsonConvert.DeserializeObject <AuthenticatorResponse>(System.Text.UTF8Encoding.UTF8.GetString(assertionResponse.Response.ClientDataJson));
            var  challenge      = clientDataJson.Challenge;

            return(new WebAuthnAssertion
            {
                verified = true,
                challenge = System.Convert.ToBase64String(clientDataJson.Challenge),
                credentialId = credentialId,
                publicKey = System.Convert.ToBase64String(publicKey),
                userHandle = assertionResponse.Response.UserHandle
            });
        }
        public static WebAuthnAssertion VerifyAttestationResult(Fido2Configuration fido2Config, string requestJSON, string resultJSON)
        {
            var fido2 = new Fido2(fido2Config);
            IsCredentialIdUniqueToUserAsyncDelegate callback = (IsCredentialIdUniqueToUserParams args) =>
            {
                var id = args.CredentialId; // generated ID by authenticator(should be always unique for each authenticator, equivalent to client cert)
                var u  = args.User;         // user info, kind of useless as this can be changed by js at client side
                return(Task.FromResult(true));
            };
            var request = Newtonsoft.Json.JsonConvert.DeserializeObject <CredentialCreateOptions>(requestJSON);
            AuthenticatorAttestationRawResponse regResponse = Newtonsoft.Json.JsonConvert.DeserializeObject <AuthenticatorAttestationRawResponse>(resultJSON);
            var success        = fido2.MakeNewCredentialAsync(regResponse, request, callback).Result;
            var clientDataJson = Newtonsoft.Json.JsonConvert.DeserializeObject <AuthenticatorResponse>(System.Text.UTF8Encoding.UTF8.GetString(regResponse.Response.ClientDataJson));
            var challenge      = System.Convert.ToBase64String(clientDataJson.Challenge);
            var credentialId   = System.Convert.ToBase64String(success.Result.CredentialId);
            var publicKey      = System.Convert.ToBase64String(success.Result.PublicKey);
            var signingCounter = success.Result.Counter; // designed for replay attact prevention but useless for a multiple node situation
            var user           = success.Result.User;
            var aaguid         = success.Result.Aaguid;

            return(new WebAuthnAssertion
            {
                verified = true,
                challenge = challenge,
                credentialId = credentialId,
                publicKey = publicKey,
                signingCounter = signingCounter,
                aaguid = aaguid,
                userHandle = request.User.Id
            });
        }
예제 #3
0
        public void Validate_Success_Empty()
        {
            var config = new Fido2Configuration();
            var result = _validator.Validate(config, false);

            result.Failed.Should().BeFalse();
        }
        public async Task TestAppleAttestationAsync()
        {
            var jsonPost = JsonConvert.DeserializeObject <AuthenticatorAttestationRawResponse>(File.ReadAllText("./attestationAppleResponse.json"));
            var options  = JsonConvert.DeserializeObject <CredentialCreateOptions>(File.ReadAllText("./attestationAppleOptions.json"));
            var o        = AuthenticatorAttestationResponse.Parse(jsonPost);
            var config   = new Fido2Configuration {
                Origin = "https://6cc3c9e7967a.ngrok.io"
            };
            await o.VerifyAsync(options, config, (x) => Task.FromResult(true), _metadataService, null);

            byte[] ad = o.AttestationObject.AuthData;
            // TODO : Why read ad ? Is the test finished ?
        }
        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);
        }
예제 #6
0
        public UnitTest1()
        {
            var MDSAccessKey = Environment.GetEnvironmentVariable("fido2:MDSAccessKey");
            var CacheDir     = Environment.GetEnvironmentVariable("fido2:MDSCacheDirPath");

            // Only create and use MetadataService if we have an accesskey
            MetadataService = string.IsNullOrEmpty(MDSAccessKey) ? null : MDSMetadata.Instance(MDSAccessKey, CacheDir);
            if (null != MetadataService)
            {
                if (false == MetadataService.IsInitialized())
                {
                    MetadataService.Initialize().Wait();
                }
            }
            config = new Fido2Configuration {
                Origin = "https://localhost:44329"
            };
        }
예제 #7
0
        public Fido2Tests()
        {
            var MDSAccessKey = Environment.GetEnvironmentVariable("fido2:MDSAccessKey");
            //var CacheDir = Environment.GetEnvironmentVariable("fido2:MDSCacheDirPath");

            var services = new ServiceCollection();

            var staticClient = new StaticMetadataRepository();

            var repos = new List <IMetadataRepository>();

            repos.Add(staticClient);

            if (!string.IsNullOrEmpty(MDSAccessKey))
            {
                repos.Add(new Fido2MetadataServiceRepository(MDSAccessKey, null));
            }

            services.AddDistributedMemoryCache();
            services.AddLogging();

            var provider = services.BuildServiceProvider();

            var memCache = provider.GetService <IDistributedCache>();

            var service = new DistributedCacheMetadataService(
                repos,
                memCache,
                provider.GetService <ILogger <DistributedCacheMetadataService> >());

            service.Initialize().Wait();

            _metadataService = service;

            _config = new Fido2Configuration {
                Origin = "https://localhost:44329"
            };
        }
        public static string MakeWebAuthnAssertionRequest(Fido2Configuration fido2Config, byte[] challenge, List <PublicKeyCredentialDescriptor> allowedCredentials)
        {
            AuthenticatorSelection authSelection = new AuthenticatorSelection
            {
                RequireResidentKey = false,
                UserVerification   = UserVerificationRequirement.Preferred,
                //                AuthenticatorAttachment = null,
            };
            AuthenticationExtensionsClientInputs clientExtensions = new AuthenticationExtensionsClientInputs
            {
                Extensions = true,
                SimpleTransactionAuthorization = string.Format("you are registering to {0}", fido2Config.ServerName),
                Location = true,
                UserVerificationMethod = true,
            };

            var fido2 = new Fido2(fido2Config);

            var    assertionRequest     = Fido2NetLib.AssertionOptions.Create(fido2Config, challenge, allowedCredentials, UserVerificationRequirement.Preferred, clientExtensions);
            string assertionRequestJson = assertionRequest.ToJson();

            return(assertionRequestJson);
        }
예제 #9
0
 public Fido2Service(ApplicationDbContextFactory contextFactory, IFido2 fido2, Fido2Configuration fido2Configuration)
 {
     _contextFactory     = contextFactory;
     _fido2              = fido2;
     _fido2Configuration = fido2Configuration;
 }
        static Fido2Tests()
        {
            var MDSAccessKey = Environment.GetEnvironmentVariable("fido2:MDSAccessKey");

            var services = new ServiceCollection();

            var staticClient = new StaticMetadataRepository();

            var repos = new List <IMetadataRepository>();

            repos.Add(staticClient);

            if (!string.IsNullOrEmpty(MDSAccessKey))
            {
                repos.Add(new Fido2MetadataServiceRepository(MDSAccessKey, null));
            }

            services.AddDistributedMemoryCache();
            services.AddLogging();

            var provider = services.BuildServiceProvider();

            var memCache = provider.GetService <IDistributedCache>();

            var service = new DistributedCacheMetadataService(
                repos,
                memCache,
                provider.GetService <ILogger <DistributedCacheMetadataService> >());

            service.Initialize().Wait();

            _metadataService = service;

            _config = new Fido2Configuration {
                Origin = "https://localhost:44329"
            };

            _validCOSEParameters = new List <object[]>();

            _validCOSEParameters.Add(new object[3] {
                COSE.KeyType.EC2, COSE.Algorithm.ES256, COSE.EllipticCurve.P256
            });
            _validCOSEParameters.Add(new object[3] {
                COSE.KeyType.EC2, COSE.Algorithm.ES384, COSE.EllipticCurve.P384
            });
            _validCOSEParameters.Add(new object[3] {
                COSE.KeyType.EC2, COSE.Algorithm.ES512, COSE.EllipticCurve.P521
            });
            _validCOSEParameters.Add(new object[2] {
                COSE.KeyType.RSA, COSE.Algorithm.RS256
            });
            _validCOSEParameters.Add(new object[2] {
                COSE.KeyType.RSA, COSE.Algorithm.RS384
            });
            _validCOSEParameters.Add(new object[2] {
                COSE.KeyType.RSA, COSE.Algorithm.RS512
            });
            _validCOSEParameters.Add(new object[2] {
                COSE.KeyType.RSA, COSE.Algorithm.PS256
            });
            _validCOSEParameters.Add(new object[2] {
                COSE.KeyType.RSA, COSE.Algorithm.PS384
            });
            _validCOSEParameters.Add(new object[2] {
                COSE.KeyType.RSA, COSE.Algorithm.PS512
            });
            _validCOSEParameters.Add(new object[3] {
                COSE.KeyType.OKP, COSE.Algorithm.EdDSA, COSE.EllipticCurve.Ed25519
            });
        }