diff --git a/README-pwpolicy.md b/README-pwpolicy.md
index 7e1eb8982766be7bba90e92d367ebf020ab69dd8..7fd051643b6514be4ae07fa7d3c72e7160f9bb5f 100644
--- a/README-pwpolicy.md
+++ b/README-pwpolicy.md
@@ -87,6 +87,36 @@ Example playbook to ensure maxlife is set to 49 in global policy:
       maxlife: 49
 ```
 
+Example playbook to ensure password grace period is set to 3 in global policy:
+
+```yaml
+---
+- name: Playbook to handle pwpolicies
+  hosts: ipaserver
+  become: true
+
+  tasks:
+  # Ensure maxlife is set to 49 in global policy
+  - ipapwpolicy:
+      ipaadmin_password: SomeADMINpassword
+      gracelimit: 3
+```
+
+Example playbook to ensure password grace period is set to unlimited in global policy:
+
+```yaml
+---
+- name: Playbook to handle pwpolicies
+  hosts: ipaserver
+  become: true
+
+  tasks:
+  # Ensure maxlife is set to 49 in global policy
+  - ipapwpolicy:
+      ipaadmin_password: SomeADMINpassword
+      gracelimit: -1
+```
+
 
 Variables
 =========
@@ -107,6 +137,11 @@ Variable | Description | Required
 `maxfail` \| `krbpwdmaxfailure` | Consecutive failures before lockout. (int) | no
 `failinterval` \| `krbpwdfailurecountinterval` | Period after which failure count will be reset in seconds. (int) | no
 `lockouttime` \| `krbpwdlockoutduration` | Period for which lockout is enforced in seconds. (int) | no
+`maxrepeat` \| `ipapwdmaxrepeat` | Maximum number of same consecutive characters. Requires IPA 4.9+ (int) | no
+`maxsequence` \| `ipapwdmaxsequence` |  The maximum length of monotonic character sequences (abcd). Requires IPA 4.9+ (int) | no
+`dictcheck` \| `ipapwdictcheck` | Check if the password is a dictionary word. Requires IPA 4.9+ (int) | no
+`usercheck` \| `ipapwdusercheck` | Check if the password contains the username. Requires IPA 4.9+ (int) | no
+`gracelimit` \| `passwordgracelimit` |  Number of LDAP authentications allowed after expiration. Requires IPA 4.9.10 (int) | no
 `state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
 
 
diff --git a/playbooks/pwpolicy/pwpolicy_grace_limit.yml b/playbooks/pwpolicy/pwpolicy_grace_limit.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e1ed3076f2add621e8f7dca74acf20791a8b2a5a
--- /dev/null
+++ b/playbooks/pwpolicy/pwpolicy_grace_limit.yml
@@ -0,0 +1,11 @@
+---
+- name: Playbook to manage password policy
+  hosts: ipaserver
+  become: no
+  gather_facts: no
+
+  tasks:
+  - name: Set password policy grace limit.
+    ipapwpolicy:
+      ipaadmin_password: SomeADMINpassword
+      gracelimit: 3
diff --git a/playbooks/pwpolicy/pwpolicy_password_check.yml b/playbooks/pwpolicy/pwpolicy_password_check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6ae237e06b7629938d33b824807c7b3c6e0ae2d7
--- /dev/null
+++ b/playbooks/pwpolicy/pwpolicy_password_check.yml
@@ -0,0 +1,14 @@
+---
+- name: Playbook to manage password policy
+  hosts: ipaserver
+  become: no
+  gather_facts: no
+
+  tasks:
+  - name: Set password checking parameters.
+    ipapwpolicy:
+      ipaadmin_password: SomeADMINpassword
+      maxrepeat: 2
+      maxsequence: 3
+      dictcheck: yes
+      usercheck: yes
diff --git a/plugins/modules/ipapwpolicy.py b/plugins/modules/ipapwpolicy.py
index c29bb27b770047baec7e88aae0cad15a7ce6131b..4398c4e8f96d309ca8004f8bf43f75e7be9130d5 100644
--- a/plugins/modules/ipapwpolicy.py
+++ b/plugins/modules/ipapwpolicy.py
@@ -2,6 +2,7 @@
 
 # Authors:
 #   Thomas Woerner <twoerner@redhat.com>
+#   Rafael Guterres Jeffman <rjeffman@redhat.com>
 #
 # Copyright (C) 2019-2022 Red Hat
 # see file 'COPYING' for use and warranty information
@@ -88,6 +89,41 @@ options:
     type: int
     required: false
     aliases: ["krbpwdlockoutduration"]
+  maxrepeat:
+    description: >
+      Maximum number of same consecutive characters.
+      Requires IPA 4.9+
+    type: int
+    required: false
+    aliases: ["ipapwdmaxrepeat"]
+  maxsequence:
+    description: >
+      The maximum length of monotonic character sequences (abcd).
+      Requires IPA 4.9+
+    type: int
+    required: false
+    aliases: ["ipapwdmaxsequence"]
+  dictcheck:
+    description: >
+      Check if the password is a dictionary word.
+      Requires IPA 4.9+
+    type: bool
+    required: false
+    aliases: ["ipapwdictcheck"]
+  usercheck:
+    description: >
+      Check if the password contains the username.
+      Requires IPA 4.9+
+    type: bool
+    required: false
+    aliases: ["ipapwdusercheck"]
+  gracelimit:
+    description: >
+      Number of LDAP authentications allowed after expiration.
+      Requires IPA 4.10.1+
+    type: int
+    required: false
+    aliases: ["passwordgracelimit"]
   state:
     description: State to ensure
     type: str
@@ -95,6 +131,7 @@ options:
     choices: ["present", "absent"]
 author:
   - Thomas Woerner (@t-woerner)
+  - Rafael Guterres Jeffman (@rjeffman)
 """
 
 EXAMPLES = """
@@ -135,7 +172,8 @@ def find_pwpolicy(module, name):
 
 
 def gen_args(maxlife, minlife, history, minclasses, minlength, priority,
-             maxfail, failinterval, lockouttime):
+             maxfail, failinterval, lockouttime, maxrepeat, maxsequence,
+             dictcheck, usercheck, gracelimit):
     _args = {}
     if maxlife is not None:
         _args["krbmaxpwdlife"] = maxlife
@@ -155,10 +193,47 @@ def gen_args(maxlife, minlife, history, minclasses, minlength, priority,
         _args["krbpwdfailurecountinterval"] = failinterval
     if lockouttime is not None:
         _args["krbpwdlockoutduration"] = lockouttime
+    if maxrepeat is not None:
+        _args["ipapwdmaxrepeat"] = maxrepeat
+    if maxsequence is not None:
+        _args["ipapwdmaxrsequence"] = maxsequence
+    if dictcheck is not None:
+        _args["ipapwddictcheck"] = dictcheck
+    if usercheck is not None:
+        _args["ipapwdusercheck"] = usercheck
+    if gracelimit is not None:
+        _args["passwordgracelimit"] = gracelimit
 
     return _args
 
 
+def check_supported_params(
+    module, maxrepeat, maxsequence, dictcheck, usercheck, gracelimit
+):
+    # All password checking parameters were added by the same commit,
+    # so we only need to test one of them.
+    has_password_check = module.ipa_command_param_exists(
+        "pwpolicy_add", "ipapwdmaxrepeat")
+    # check if gracelimit is supported
+    has_gracelimit = module.ipa_command_param_exists(
+        "pwpolicy_add", "passwordgracelimit")
+
+    # If needed, report unsupported password checking paramteres
+    if not has_password_check:
+        check_password_params = [maxrepeat, maxsequence, dictcheck, usercheck]
+        unsupported = [
+            x for x in check_password_params if x is not None
+        ]
+        if unsupported:
+            module.fail_json(
+                msg="Your IPA version does not support arguments: "
+                    "maxrepeat, maxsequence, dictcheck, usercheck.")
+
+    if gracelimit is not None and not has_gracelimit:
+        module.fail_json(
+            msg="Your IPA version does not support 'gracelimit'.")
+
+
 def main():
     ansible_module = IPAAnsibleModule(
         argument_spec=dict(
@@ -183,6 +258,16 @@ def main():
                               default=None),
             lockouttime=dict(type="int", aliases=["krbpwdlockoutduration"],
                              default=None),
+            maxrepeat=dict(type="int", aliases=["ipapwdmaxrepeat"],
+                           default=None),
+            maxsequence=dict(type="int", aliases=["ipapwdmaxsequence"],
+                             default=None),
+            dictcheck=dict(type="bool", aliases=["ipapwdictcheck"],
+                           default=None),
+            usercheck=dict(type="bool", aliases=["ipapwusercheck"],
+                           default=None),
+            gracelimit=dict(type="int", aliases=["passwordgracelimit"],
+                            default=None),
             # state
             state=dict(type="str", default="present",
                        choices=["present", "absent"]),
@@ -207,6 +292,11 @@ def main():
     maxfail = ansible_module.params_get("maxfail")
     failinterval = ansible_module.params_get("failinterval")
     lockouttime = ansible_module.params_get("lockouttime")
+    maxrepeat = ansible_module.params_get("maxrepeat")
+    maxsequence = ansible_module.params_get("maxsequence")
+    dictcheck = ansible_module.params_get("dictcheck")
+    usercheck = ansible_module.params_get("usercheck")
+    gracelimit = ansible_module.params_get("gracelimit")
 
     # state
     state = ansible_module.params_get("state")
@@ -230,10 +320,16 @@ def main():
                 msg="'global_policy' can not be made absent.")
         invalid = ["maxlife", "minlife", "history", "minclasses",
                    "minlength", "priority", "maxfail", "failinterval",
-                   "lockouttime"]
+                   "lockouttime", "maxrepeat", "maxsequence", "dictcheck",
+                   "usercheck", "gracelimit"]
 
     ansible_module.params_fail_used_invalid(invalid, state)
 
+    if gracelimit is not None:
+        if gracelimit < -1:
+            ansible_module.fail_json(
+                msg="'gracelimit' must be no less than -1")
+
     # Init
 
     changed = False
@@ -241,6 +337,11 @@ def main():
 
     with ansible_module.ipa_connect():
 
+        check_supported_params(
+            ansible_module, maxrepeat, maxsequence, dictcheck, usercheck,
+            gracelimit
+        )
+
         commands = []
 
         for name in names:
@@ -252,7 +353,8 @@ def main():
                 # Generate args
                 args = gen_args(maxlife, minlife, history, minclasses,
                                 minlength, priority, maxfail, failinterval,
-                                lockouttime)
+                                lockouttime, maxrepeat, maxsequence, dictcheck,
+                                usercheck, gracelimit)
 
                 # Found the pwpolicy
                 if res_find is not None:
diff --git a/tests/pwpolicy/test_pwpolicy.yml b/tests/pwpolicy/test_pwpolicy.yml
index 5ac18d769cf66d3f8b5a65ce60331a16b81eb495..e98689349aa55dfa1ce28d1e605edbf211d26f8a 100644
--- a/tests/pwpolicy/test_pwpolicy.yml
+++ b/tests/pwpolicy/test_pwpolicy.yml
@@ -5,6 +5,9 @@
   gather_facts: false
 
   tasks:
+  - name: Setup FreeIPA test facts.
+    import_tasks: ../env_freeipa_facts.yml
+
   - name: Ensure maxlife of 90 for global_policy
     ipapwpolicy:
       ipaadmin_password: SomeADMINpassword
@@ -117,3 +120,145 @@
       state: absent
     register: result
     failed_when: result.changed or result.failed
+
+  - block:
+    - name: Ensure maxrepeat of 2 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        maxrepeat: 2
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure maxrepeat of 2 for global_policy, again
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        maxrepeat: 2
+      register: result
+      failed_when: result.changed or result.failed
+
+    - name: Ensure maxrepeat of 0 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        maxrepeat: 0
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure maxsequence of 4 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        maxrepeat: 4
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure maxsequence of 4 for global_policy, again
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        maxrepeat: 4
+      register: result
+      failed_when: result.changed or result.failed
+
+    - name: Ensure maxsequence of 0 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        maxrepeat: 0
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure dictcheck is set for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        dictcheck: yes
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure dictcheck is set for global_policy, again
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        dictcheck: yes
+      register: result
+      failed_when: result.changed or result.failed
+
+    - name: Ensure dictcheck is not set for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        dictcheck: no
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure usercheck is set for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        usercheck: yes
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure usercheck is set for global_policy, again
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        usercheck: yes
+      register: result
+      failed_when: result.changed or result.failed
+
+    - name: Ensure usercheck is not set for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        usercheck: no
+      register: result
+      failed_when: not result.changed or result.failed
+
+    when: ipa_version is version("4.9", ">=")
+
+  - block:
+    - name: Ensure grace limit is set to 10 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        gracelimit: 10
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure grace limit is set to 0 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        gracelimit: 0
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure grace limit is set to 0 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        gracelimit: 0
+      register: result
+      failed_when: result.changed or result.failed
+
+    - name: Ensure grace limit is set to 0 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        gracelimit: -1
+      register: result
+      failed_when: not result.changed or result.failed
+
+    - name: Ensure grace limit is not set to -2 for global_policy
+      ipapwpolicy:
+        ipaadmin_password: SomeADMINpassword
+        ipaapi_context: "{{ ipa_context | default(omit) }}"
+        gracelimit: -2
+      register: result
+      failed_when: not result.failed and "must be at least -1" not in result.msg
+
+    when: ipa_version is version("4.9.10", ">=")