/// <summary>
        /// Verifies the assertion response from the browser/authr to assert existing credentials and authenticate a user. (MakeAssertionAsync)
        /// </summary>
        /// <returns></returns>
        public Task <AssertionVerificationResult> SetAssertionResult(AuthenticatorAssertionRawResponse assertionResponse, AssertionOptions originalOptions,
                                                                     byte[] storedPublicKey, uint storedSignatureCounter, IsUserHandleOwnerOfCredentialIdAsync isUserHandleOwnerOfCredentialIdCallback, byte[] requestTokenBindingId = null)
        {
            var parsedResponse = AuthenticatorAssertionResponse.Parse(assertionResponse);
            var result         = parsedResponse.VerifyAsync(originalOptions, _config.Origin, storedPublicKey, storedSignatureCounter, isUserHandleOwnerOfCredentialIdCallback, requestTokenBindingId);

            return(result);
        }
        /// <summary>
        /// SetLoginAssertionResult method implementation
        /// </summary>
        private int SetLoginAssertionResult(AuthenticationContext ctx, string jsonResponse)
        {
            try
            {
                string jsonOptions = ctx.AssertionOptions;
                if (string.IsNullOrEmpty(jsonOptions))
                {
                    throw new ArgumentNullException(jsonOptions);
                }
                if (string.IsNullOrEmpty(jsonResponse))
                {
                    throw new ArgumentNullException(jsonResponse);
                }

                MFAWebAuthNUser user = RuntimeRepository.GetUser(Config, ctx.UPN);
                if (user != null)
                {
                    AssertionOptions options = AssertionOptions.FromJson(jsonOptions);
                    AuthenticatorAssertionRawResponse clientResponse = JsonConvert.DeserializeObject <AuthenticatorAssertionRawResponse>(jsonResponse);


                    MFAUserCredential creds = RuntimeRepository.GetCredentialById(Config, user, clientResponse.Id);

                    if (creds == null)
                    {
                        throw new Exception("Unknown credentials");
                    }

                    uint storedCounter = creds.SignatureCounter;

                    bool callback(IsUserHandleOwnerOfCredentialIdParams args)
                    {
                        var storedCreds = RuntimeRepository.GetCredentialsByUserHandle(Config, user, args.UserHandle);

                        return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                    }
                    AssertionVerificationResult res = _webathn.SetAssertionResult(clientResponse, options, creds.PublicKey, storedCounter, callback);
                    RuntimeRepository.UpdateCounter(Config, user, res.CredentialId, res.Counter);
                    return((int)AuthenticationResponseKind.Biometrics);
                }
                else
                {
                    Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !"), System.Diagnostics.EventLogEntryType.Error, 5000);
                    return((int)AuthenticationResponseKind.Error);
                }
            }
            catch (Exception e)
            {
                Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), System.Diagnostics.EventLogEntryType.Error, 5000);
                return((int)AuthenticationResponseKind.Error);
            }
        }
        internal static AuthenticatorAssertionResponse Parse(AuthenticatorAssertionRawResponse rawResponse)
        {
            var response = new AuthenticatorAssertionResponse(rawResponse.Response.ClientDataJson)
            {
                // we will need to access raw in Verify()
                Raw = rawResponse,
                AuthenticatorData = rawResponse.Response.AuthenticatorData,
                Signature         = rawResponse.Response.Signature,
                UserHandle        = rawResponse.Response.UserHandle
            };

            return(response);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// SetLoginAssertionResult method implementation
        /// </summary>
        private int SetLoginAssertionResult(AuthenticationContext ctx, string jsonResponse, out string error)
        {
            bool isDeserialized = false;

            try
            {
                string jsonOptions = ctx.AssertionOptions;
                if (string.IsNullOrEmpty(jsonOptions))
                {
                    throw new ArgumentNullException(jsonOptions);
                }
                if (string.IsNullOrEmpty(jsonResponse))
                {
                    throw new ArgumentNullException(jsonResponse);
                }

                MFAWebAuthNUser user = RuntimeRepository.GetUser(Config, ctx.UPN);
                if (user != null)
                {
                    AssertionOptions options = AssertionOptions.FromJson(jsonOptions);
                    try
                    {
                        AuthenticatorAssertionRawResponse clientResponse = JsonConvert.DeserializeObject <AuthenticatorAssertionRawResponse>(jsonResponse);
                        isDeserialized = true;

                        MFAUserCredential creds = RuntimeRepository.GetCredentialById(Config, user, clientResponse.Id);
                        if (creds == null)
                        {
                            throw new Exception("Unknown credentials");
                        }

                        // Check Replay
                        AuthenticatorData authData = new AuthenticatorData(clientResponse.Response.AuthenticatorData);
                        uint authCounter           = authData.SignCount;
                        uint storedCounter         = creds.SignatureCounter;
                        if ((authCounter <= 0) || (authCounter <= storedCounter))
                        {
                            ResourcesLocale Resources = new ResourcesLocale(ctx.Lcid);
                            throw new Exception(Resources.GetString(ResourcesLocaleKind.Html, "BIOERRORAUTHREPLAY"));
                        }

                        bool callback(IsUserHandleOwnerOfCredentialIdParams args)
                        {
                            var storedCreds = RuntimeRepository.GetCredentialsByUserHandle(Config, user, args.UserHandle);

                            return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                        }
                        AssertionVerificationResult res = _webathn.SetAssertionResult(clientResponse, options, creds.PublicKey, storedCounter, callback);
                        RuntimeRepository.UpdateCounter(Config, user, res.CredentialId, res.Counter);

                        if (!authData.UserPresent || !authData.UserVerified)
                        {
                            switch (creds.CredType)
                            {
                            case "none":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.None));
                                break;

                            case "android-key":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.AndroidKey));
                                break;

                            case "android-safetynet":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.AndroidSafetyNet));
                                break;

                            case "fido-u2f":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Fido2U2f));
                                break;

                            case "packed":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Packed));
                                break;

                            case "tpm":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.TPM));
                                break;

                            case "apple":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Apple));
                                break;

                            default:
                                ctx.PinRequirements = false;
                                break;
                            }
                        }
                        else
                        {
                            ctx.PinRequirements = false;
                        }
                        error = string.Empty;
                        return((int)AuthenticationResponseKind.Biometrics);
                    }
                    catch (Exception ex)
                    {
                        if (isDeserialized)
                        {
                            Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, ex.Message), EventLogEntryType.Error, 5000);
                        }
                        else
                        {
                            Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, jsonResponse), EventLogEntryType.Error, 5000);
                        }
                        error = ex.Message;
                        return((int)AuthenticationResponseKind.Error);
                    }
                }
                else
                {
                    Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !"), EventLogEntryType.Error, 5000);
                    error = string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !");
                    return((int)AuthenticationResponseKind.Error);
                }
            }
            catch (Exception e)
            {
                Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), EventLogEntryType.Error, 5000);
                error = e.Message;
                return((int)AuthenticationResponseKind.Error);
            }
        }
        /// <summary>
        /// SetLoginAssertionResult method implementation
        /// </summary>
        private int SetLoginAssertionResult(AuthenticationContext ctx, string jsonResponse, out string error)
        {
            bool isDeserialized = false;

            try
            {
                string jsonOptions = ctx.AssertionOptions;
                if (string.IsNullOrEmpty(jsonOptions))
                {
                    throw new ArgumentNullException(jsonOptions);
                }
                if (string.IsNullOrEmpty(jsonResponse))
                {
                    throw new ArgumentNullException(jsonResponse);
                }

                MFAWebAuthNUser user = RuntimeRepository.GetUser(Config, ctx.UPN);
                if (user != null)
                {
                    AssertionOptions options = AssertionOptions.FromJson(jsonOptions);
                    try
                    {
                        AuthenticatorAssertionRawResponse clientResponse = JsonConvert.DeserializeObject <AuthenticatorAssertionRawResponse>(jsonResponse);
                        isDeserialized = true;

                        MFAUserCredential creds = RuntimeRepository.GetCredentialById(Config, user, clientResponse.Id);
                        if (creds == null)
                        {
                            throw new Exception("Unknown credentials");
                        }

                        AuthenticatorData authData = new AuthenticatorData(clientResponse.Response.AuthenticatorData);
                        bool isnocount             = Utilities.IsNoCounterDevice(this.Config.WebAuthNProvider.Configuration, ctx);
                        uint authCounter           = 0;
                        uint storedCounter         = 0;

                        if (!isnocount)
                        {
                            authCounter   = authData.SignCount;
                            storedCounter = creds.SignatureCounter;
                        }
                        else
                        if ((authCounter > 0) && (authCounter <= storedCounter))
                        {
                            ResourcesLocale Resources = new ResourcesLocale(ctx.Lcid);
                            throw new Exception(Resources.GetString(ResourcesLocaleKind.FIDOHtml, "BIOERRORAUTHREPLAY"));
                        }

#pragma warning disable CS1998 // Cette méthode async n'a pas d'opérateur 'await' et elle s'exécutera de façon synchrone
                        IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
#pragma warning restore CS1998 // Cette méthode async n'a pas d'opérateur 'await' et elle s'exécutera de façon synchrone
                        {
                            var storedCreds = RuntimeRepository.GetCredentialsByUserHandle(Config, user, args.UserHandle);
                            return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                        };

                        // Apple counter always 0
                        AssertionVerificationResult res = _webathn.SetAssertionResult(clientResponse, options, creds.PublicKey, storedCounter, callback).Result;
                        if (!isnocount)
                        {
                            RuntimeRepository.UpdateCounter(Config, user, res.CredentialId, res.Counter);
                        }
                        else
                        {
                            RuntimeRepository.UpdateCounter(Config, user, res.CredentialId, 0);
                        }

                        if (!authData.UserPresent || !authData.UserVerified)
                        {
                            switch (creds.CredType)
                            {
                            case "none":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.None));
                                break;

                            case "android-key":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.AndroidKey));
                                break;

                            case "android-safetynet":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.AndroidSafetyNet));
                                break;

                            case "fido-u2f":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Fido2U2f));
                                break;

                            case "packed":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Packed));
                                break;

                            case "tpm":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.TPM));
                                break;

                            case "apple":
                                ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Apple));
                                break;

                            default:
                                ctx.PinRequirements = false;
                                break;
                            }
                        }
                        else
                        {
                            ctx.PinRequirements = false;
                        }
                        error = string.Empty;
                        return((int)AuthenticationResponseKind.Biometrics);
                    }
                    catch (Exception ex)
                    {
                        if (isDeserialized)
                        {
                            Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, ex.Message), EventLogEntryType.Error, 5000);
                        }
                        else
                        {
                            Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, jsonResponse), EventLogEntryType.Error, 5000);
                        }
                        error = ex.Message;
                        return((int)AuthenticationResponseKind.Error);
                    }
                }
                else
                {
                    Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !"), EventLogEntryType.Error, 5000);
                    error = string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !");
                    return((int)AuthenticationResponseKind.Error);
                }
            }
            catch (Exception e)
            {
                Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), EventLogEntryType.Error, 5000);
                error = e.Message;
                return((int)AuthenticationResponseKind.Error);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// SetLoginAssertionResult method implementation
        /// </summary>
        private int SetLoginAssertionResult(AuthenticationContext ctx, string jsonResponse)
        {
            try
            {
                string jsonOptions = ctx.AssertionOptions;
                if (string.IsNullOrEmpty(jsonOptions))
                {
                    throw new ArgumentNullException(jsonOptions);
                }
                if (string.IsNullOrEmpty(jsonResponse))
                {
                    throw new ArgumentNullException(jsonResponse);
                }

                MFAWebAuthNUser user = RuntimeRepository.GetUser(Config, ctx.UPN);
                if (user != null)
                {
                    AssertionOptions options = AssertionOptions.FromJson(jsonOptions);
                    AuthenticatorAssertionRawResponse clientResponse = JsonConvert.DeserializeObject <AuthenticatorAssertionRawResponse>(jsonResponse);

                    // AuthData Flags
                    byte flag          = clientResponse.Response.AuthenticatorData[32];
                    var  userpresent   = (flag & (1 << 0)) != 0;
                    var  userverified  = (flag & (1 << 2)) != 0;
                    var  attestedcred  = (flag & (1 << 6)) != 0;
                    var  hasextenddata = (flag & (1 << 7)) != 0;

                    MFAUserCredential creds = RuntimeRepository.GetCredentialById(Config, user, clientResponse.Id);

                    if (creds == null)
                    {
                        throw new Exception("Unknown credentials");
                    }

                    uint storedCounter = creds.SignatureCounter;

                    bool callback(IsUserHandleOwnerOfCredentialIdParams args)
                    {
                        var storedCreds = RuntimeRepository.GetCredentialsByUserHandle(Config, user, args.UserHandle);

                        return(storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                    }
                    AssertionVerificationResult res = _webathn.SetAssertionResult(clientResponse, options, creds.PublicKey, storedCounter, callback);
                    RuntimeRepository.UpdateCounter(Config, user, res.CredentialId, res.Counter);
                    if (!userpresent || !userverified)
                    {
                        switch (creds.CredType)
                        {
                        case "none":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.None));
                            break;

                        case "android-key":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.AndroidKey));
                            break;

                        case "android-safetynet":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.AndroidSafetyNet));
                            break;

                        case "fido-u2f":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Fido2U2f));
                            break;

                        case "packed":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Packed));
                            break;

                        case "tpm":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.TPM));
                            break;

                        case "apple":
                            ctx.PinRequirements = (this.PinRequirements.HasFlag(WebAuthNPinRequirements.Apple));
                            break;

                        default:
                            ctx.PinRequirements = false;
                            break;
                        }
                    }
                    else
                    {
                        ctx.PinRequirements = false;
                    }
                    return((int)AuthenticationResponseKind.Biometrics);
                }
                else
                {
                    Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, "User does not exists !"), System.Diagnostics.EventLogEntryType.Error, 5000);
                    return((int)AuthenticationResponseKind.Error);
                }
            }
            catch (Exception e)
            {
                Log.WriteEntry(string.Format("{0}\r\n{1}", ctx.UPN, e.Message), System.Diagnostics.EventLogEntryType.Error, 5000);
                return((int)AuthenticationResponseKind.Error);
            }
        }