Repository: mrparkers/terraform-provider-keycloak
Pull request #246 (2020-03-04 15:53:52)

Add client auth policies
moved @yspotts  pr https://github.com/mrparkers/terraform-provider-keycloak/pull/221


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index db8e072..fa9f6b5 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -27,6 +27,7 @@ defaults:
     - image: circleci/golang:1.13.5
 
   keycloak_env: &keycloak_env
+    command: ["-b", "0.0.0.0", "-Dkeycloak.profile.feature.upload_scripts=enabled"]
     environment:
       DB_VENDOR: H2
       KEYCLOAK_LOGLEVEL: DEBUG
@@ -67,6 +68,7 @@ jobs:
         <<: *keycloak_env
     <<: *testacc_job
 
+
   test-8.0.1:
     docker:
       - <<: *go_image
@@ -74,6 +76,7 @@ jobs:
         <<: *keycloak_env
     <<: *testacc_job
 
+
   build-and-release:
     docker:
       - <<: *go_image
diff --git a/docker-compose.yml b/docker-compose.yml
index afe716b..ea5ced0 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -17,7 +17,8 @@ services:
     ports:
     - 8389:389
   keycloak:
-    image: jboss/keycloak:8.0.1
+    image:  jboss/keycloak:8.0.1
+    command: -b 0.0.0.0 -Dkeycloak.profile.feature.upload_scripts=enabled
     depends_on:
     - postgres
     - openldap
@@ -35,3 +36,4 @@ services:
     - 8080:8080
     volumes:
     - ./custom-user-federation-example/build/libs:/opt/jboss/keycloak/providers/
+
diff --git a/docs/resources/keycloak_authentication_execution_config.md b/docs/resources/keycloak_authentication_execution_config.md
new file mode 100644
index 0000000..ce47731
--- /dev/null
+++ b/docs/resources/keycloak_authentication_execution_config.md
@@ -0,0 +1,53 @@
+# keycloak_authentication_execution_config
+
+Allows for managing an authentication execution configuration.
+
+### Example Usage
+
+```hcl
+resource "keycloak_realm" "realm" {
+	realm   = "my-realm"
+	enabled = true
+}
+
+resource "keycloak_authentication_flow" "flow" {
+	realm_id = "${keycloak_realm.realm.id}"
+	alias    = "my-flow-alias"
+}
+
+resource "keycloak_authentication_execution" "execution" {
+	realm_id          = "${keycloak_realm.realm.id}"
+	parent_flow_alias = "${keycloak_authentication_flow.flow.alias}"
+	authenticator     = "identity-provider-redirector"
+}
+
+resource "keycloak_authentication_execution_config" "config" {
+	realm_id     = "${keycloak_realm.realm.id}"
+	execution_id = "${keycloak_authentication_execution.execution.id}"
+	alias        = "my-config-alias"
+	config = {
+		defaultProvider = "my-config-default-idp"
+	}
+}
+```
+
+### Argument Reference
+
+The following arguments are supported:
+
+- `realm_id` - (Required) The realm the authentication execution exists in.
+- `execution_id` - (Required) The authentication execution this configuration is attached to.
+- `alias` - (Required) The name of the configuration.
+- `config` - (Optional) The configuration. Keys are specific to each configurable authentication execution and not checked when applying.
+
+### Import
+
+Configurations can be imported using the format `{{realm}}/{{authenticationExecutionId}}/{{authenticationExecutionConfigId}}`.
+If the `authenticationExecutionId` is incorrect, the import will still be successful.
+A subsequent apply will change the `authenticationExecutionId` to the correct one, which causes the configuration to be replaced.
+
+Example:
+
+```bash
+$ terraform import keycloak_authentication_execution_config.config my-realm/be081463-ddbf-4b42-9eff-9c97886f24ff/30559fcf-6fb8-45ea-8c46-2b86f46ebc17
+```
diff --git a/docs/resources/keycloak_ldap_msad_lds_user_account_control_mapper.md b/docs/resources/keycloak_ldap_msad_lds_user_account_control_mapper.md
new file mode 100644
index 0000000..4a119a4
--- /dev/null
+++ b/docs/resources/keycloak_ldap_msad_lds_user_account_control_mapper.md
@@ -0,0 +1,60 @@
+# keycloak_ldap_msad_lds_user_account_control_mapper
+
+Allows for creating and managing MSAD-LDS user account control mappers for Keycloak
+users federated via LDAP.
+
+The MSAD-LDS (Microsoft Active Directory Lightweight Directory Service) user account control mapper is specific
+to LDAP user federation providers that are pulling from AD-LDS, and it can propagate
+AD-LDS user state to Keycloak in order to enforce settings like expired passwords
+or disabled accounts.
+
+### Example Usage
+
+```hcl
+resource "keycloak_realm" "realm" {
+    realm   = "test"
+    enabled = true
+}
+
+resource "keycloak_ldap_user_federation" "ldap_user_federation" {
+	name                    = "ad"
+	realm_id                = "${keycloak_realm.realm.id}"
+
+	username_ldap_attribute = "cn"
+	rdn_ldap_attribute      = "cn"
+	uuid_ldap_attribute     = "objectGUID"
+	user_object_classes     = [
+		"person",
+		"organizationalPerson",
+		"user"
+	]
+	connection_url          = "ldap://my-ad-server"
+	users_dn                = "dc=example,dc=org"
+	bind_dn                 = "cn=admin,dc=example,dc=org"
+	bind_credential         = "admin"
+}
+
+resource "keycloak_ldap_msad_lds_user_account_control_mapper" "msad_lds_user_account_control_mapper" {
+	realm_id                 = "${keycloak_realm.realm.id}"
+	ldap_user_federation_id  = "${keycloak_ldap_user_federation.ldap_user_federation.id}"
+	name                     = "msad-lds-user-account-control-mapper"
+}
+```
+
+### Argument Reference
+
+The following arguments are supported:
+
+- `realm_id` - (Required) The realm that this LDAP mapper will exist in.
+- `ldap_user_federation_id` - (Required) The ID of the LDAP user federation provider to attach this mapper to.
+- `name` - (Required) Display name of this mapper when displayed in the console.
+
+### Import
+
+LDAP mappers can be imported using the format `{{realm_id}}/{{ldap_user_federation_id}}/{{ldap_mapper_id}}`.
+The ID of the LDAP user federation provider and the mapper can be found within
+the Keycloak GUI, and they are typically GUIDs:
+
+```bash
+$ terraform import keycloak_ldap_msad_lds_user_account_control_mapper.msad_lds_user_account_control_mapper my-realm/af2a6ca3-e4d7-49c3-b08b-1b3c70b4b860/3d923ece-1a91-4bf7-adaf-3b82f2a12b67
+```
diff --git a/example/client_authorization_policys.tf b/example/client_authorization_policys.tf
new file mode 100644
index 0000000..b269fc2
--- /dev/null
+++ b/example/client_authorization_policys.tf
@@ -0,0 +1,174 @@
+resource keycloak_realm_authorization test {
+  realm                = "%s"
+  enabled              = true
+  display_name         = "foo"
+  account_theme        = "base"
+  access_code_lifespan = "30m"
+}
+
+resource keycloak_openid_client_authorization_authorization test {
+  client_id                = "test-openid-client"
+  name                     = "test-openid-client"
+  realm_id                 = "${keycloak_realm_authorization.test.id}"
+  description              = "a test openid client"
+  standard_flow_enabled    = true
+  service_accounts_enabled = true
+  access_type              = "CONFIDENTIAL"
+  client_secret            = "secret"
+  valid_redirect_uris = [
+    "http://localhost:5555/callback",
+  ]
+  authorization {
+    policy_enforcement_mode = "ENFORCING"
+  }
+}
+
+# 
+# create aggregate_policy
+# 
+
+resource keycloak_role_aggregate test {
+  realm_id = "${keycloak_realm_authorization.test.id}"
+  name     = "aggregate_policy_role"
+}
+
+resource keycloak_openid_client_authorization_role_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "keycloak_openid_client_authorization_role_policy"
+  decision_strategy  = "UNANIMOUS"
+  logic              = "POSITIVE"
+  type               = "role"
+  role {
+    id       = "${keycloak_role_aggregate.test.id}"
+    required = false
+  }
+}
+
+resource keycloak_openid_client_authorization_aggregate_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "keycloak_openid_client_authorization_aggregate_policy"
+  decision_strategy  = "UNANIMOUS"
+  logic              = "POSITIVE"
+  policies           = ["${keycloak_openid_client_authorization_role_policy.test.id}"]
+}
+
+# 
+# create client policy 
+# 
+
+resource keycloak_openid_client_authorization_client_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "keycloak_openid_client_authorization_client_policy"
+  decision_strategy  = "AFFIRMATIVE"
+  logic              = "POSITIVE"
+  clients            = ["${keycloak_openid_client_authorization.test.resource_server_id}"]
+}
+
+# 
+# create group policy
+# 
+
+resource keycloak_group test {
+  realm_id = "${keycloak_realm_authorization.test.id}"
+  name     = "foo"
+}
+
+resource keycloak_openid_client_authorization_group_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "client_group_policy_test"
+  groups {
+    id              = "${keycloak_group.test.id}"
+    path            = "${keycloak_group.test.path}"
+    extend_children = false
+  }
+  logic             = "POSITIVE"
+  decision_strategy = "UNANIMOUS"
+}
+
+
+# 
+# create JS policy
+# 
+
+resource keycloak_openid_client_authorization_js_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "client_js_policy_test"
+  logic              = "POSITIVE"
+  decision_strategy  = "UNANIMOUS"
+  code               = "test"
+  description        = "description"
+}
+
+
+# 
+#  create role policy
+# 
+
+resource keycloak_role test {
+  realm_id = "${keycloak_realm_authorization.test.id}"
+  name     = "new_role"
+}
+
+resource keycloak_openid_client_authorization_role_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "keycloak_openid_client_authorization_role_policy"
+  decision_strategy  = "AFFIRMATIVE"
+  logic              = "POSITIVE"
+  type               = "role"
+  role {
+    id       = "${keycloak_role.test.id}"
+    required = false
+  }
+}
+
+# 
+# create time policy
+# 
+
+resource keycloak_openid_client_authorization_time_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "%s"
+  not_on_or_after    = "2500-12-12 01:01:11"
+  not_before         = "2400-12-12 01:01:11"
+  day_month          = "1"
+  day_month_end      = "2"
+  year               = "2500"
+  year_end           = "2501"
+  month              = "1"
+  month_end          = "5"
+  hour               = "1"
+  hour_end           = "5"
+  minute             = "10"
+  minute_end         = "30"
+  logic              = "POSITIVE"
+  decision_strategy  = "UNANIMOUS"
+}
+
+# 
+# create user policy
+# 
+
+resource keycloak_user test {
+  realm_id = "${keycloak_realm_authorization.test.id}"
+  username = "test-user"
+
+  email      = "test-user@fakedomain.com"
+  first_name = "Testy"
+  last_name  = "Tester"
+}
+
+resource keycloak_openid_client_authorization_user_policy test {
+  resource_server_id = "${keycloak_openid_client_authorization.test.resource_server_id}"
+  realm_id           = "${keycloak_realm_authorization.test.id}"
+  name               = "client_user_policy_test"
+  users              = ["${keycloak_user.test.id}"]
+  logic              = "POSITIVE"
+  decision_strategy  = "UNANIMOUS"
+}
diff --git a/example/main.tf b/example/main.tf
index 6207cc1..40a4981 100644
--- a/example/main.tf
+++ b/example/main.tf
@@ -278,6 +278,12 @@ resource "keycloak_ldap_msad_user_account_control_mapper" "msad_uac_mapper" {
   ldap_user_federation_id = "${keycloak_ldap_user_federation.openldap.id}"
 }
 
+resource "keycloak_ldap_msad_lds_user_account_control_mapper" "msad_lds_uac_mapper" {
+  name                    = "msad-lds-uac-mapper"
+  realm_id                = "${keycloak_ldap_user_federation.openldap.realm_id}"
+  ldap_user_federation_id = "${keycloak_ldap_user_federation.openldap.id}"
+}
+
 resource "keycloak_ldap_full_name_mapper" "full_name_mapper" {
   name                    = "full-name-mapper"
   realm_id                = "${keycloak_ldap_user_federation.openldap.realm_id}"
@@ -461,6 +467,15 @@ resource keycloak_oidc_identity_provider oidc {
   client_secret     = "example_token"
 }
 
+resource keycloak_oidc_google_identity_provider google {
+  realm                                   = "${keycloak_realm.test.id}"
+  client_id                               = "myclientid.apps.googleusercontent.com"
+  client_secret                           = "myclientsecret"
+  hosted_domain                           = "mycompany.com"
+  request_refresh_token                   = true
+  accepts_prompt_none_forward_from_client = false
+}
+
 resource keycloak_oidc_identity_provider custom_oidc_idp {
   realm             = "${keycloak_realm.test.id}"
   provider_id       = "customIdp"
@@ -699,3 +714,12 @@ resource "keycloak_authentication_execution" "browser-copy-otp" {
   requirement = "REQUIRED"
   depends_on = ["keycloak_authentication_execution.browser-copy-auth-username-password-form"]
 }
+
+resource "keycloak_authentication_execution_config" "config" {
+  realm_id     = "${keycloak_realm.test.id}"
+  execution_id = "${keycloak_authentication_execution.browser-copy-idp-redirect.id}"
+  alias        = "idp-XXX-config"
+  config = {
+    defaultProvider = "idp-XXX"
+  }
+}
diff --git a/keycloak/authentication_execution_config.go b/keycloak/authentication_execution_config.go
new file mode 100644
index 0000000..8966c1b
--- /dev/null
+++ b/keycloak/authentication_execution_config.go
@@ -0,0 +1,38 @@
+package keycloak
+
+import (
+	"fmt"
+)
+
+// https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_authenticatorconfigrepresentation
+type AuthenticationExecutionConfig struct {
+	RealmId     string            `json:"-"`
+	ExecutionId string            `json:"-"`
+	Id          string            `json:"id"`
+	Alias       string            `json:"alias"`
+	Config      map[string]string `json:"config"`
+}
+
+// https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_newexecutionconfig
+func (keycloakClient *KeycloakClient) NewAuthenticationExecutionConfig(config *AuthenticationExecutionConfig) (string, error) {
+	_, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/authentication/executions/%s/config", config.RealmId, config.ExecutionId), config)
+	if err != nil {
+		return "", err
+	}
+	return getIdFromLocationHeader(location), nil
+}
+
+// https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_getauthenticatorconfig
+func (keycloakClient *KeycloakClient) GetAuthenticationExecutionConfig(config *AuthenticationExecutionConfig) error {
+	return keycloakClient.get(fmt.Sprintf("/realms/%s/authentication/config/%s", config.RealmId, config.Id), config, nil)
+}
+
+// https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_updateauthenticatorconfig
+func (keycloakClient *KeycloakClient) UpdateAuthenticationExecutionConfig(config *AuthenticationExecutionConfig) error {
+	return keycloakClient.put(fmt.Sprintf("/realms/%s/authentication/config/%s", config.RealmId, config.Id), config)
+}
+
+// https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_removeauthenticatorconfig
+func (keycloakClient *KeycloakClient) DeleteAuthenticationExecutionConfig(config *AuthenticationExecutionConfig) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/authentication/config/%s", config.RealmId, config.Id), nil)
+}
diff --git a/keycloak/identity_provider.go b/keycloak/identity_provider.go
index da7935b..9644a7d 100644
--- a/keycloak/identity_provider.go
+++ b/keycloak/identity_provider.go
@@ -39,6 +39,11 @@ type IdentityProviderConfig struct {
 	LoginHint                        string                 `json:"loginHint,omitempty"`
 	UILocales                        KeycloakBoolQuoted     `json:"uiLocales,omitempty"`
 	LogoutUrl                        string                 `json:"logoutUrl,omitempty"`
+	DefaultScope                     string                 `json:"defaultScope,omitempty"`
+	AcceptsPromptNoneForwFrmClt      KeycloakBoolQuoted     `json:"acceptsPromptNoneForwardFromClient,omitempty"`
+	HostedDomain                     string                 `json:"hostedDomain,omitempty"`
+	UserIp                           KeycloakBoolQuoted     `json:"userIp,omitempty"`
+	OfflineAccess                    KeycloakBoolQuoted     `json:"offlineAccess,omitempty"`
 	ExtraConfig                      map[string]interface{} `json:"-"`
 }
 
diff --git a/keycloak/keycloak_client.go b/keycloak/keycloak_client.go
index a1013c2..fce3701 100644
--- a/keycloak/keycloak_client.go
+++ b/keycloak/keycloak_client.go
@@ -6,7 +6,6 @@ import (
 	"crypto/x509"
 	"encoding/json"
 	"fmt"
-	"golang.org/x/net/publicsuffix"
 	"io"
 	"io/ioutil"
 	"log"
@@ -16,6 +15,8 @@ import (
 	"net/url"
 	"strings"
 	"time"
+
+	"golang.org/x/net/publicsuffix"
 )
 
 type KeycloakClient struct {
diff --git a/keycloak/ldap_msad_lds_user_account_control_mapper.go b/keycloak/ldap_msad_lds_user_account_control_mapper.go
new file mode 100644
index 0000000..9b3ecb5
--- /dev/null
+++ b/keycloak/ldap_msad_lds_user_account_control_mapper.go
@@ -0,0 +1,61 @@
+package keycloak
+
+import (
+	"fmt"
+)
+
+type LdapMsadLdsUserAccountControlMapper struct {
+	Id                   string
+	Name                 string
+	RealmId              string
+	LdapUserFederationId string
+}
+
+func convertFromLdapMsadLdsUserAccountControlMapperToComponent(ldapMsadLdsUserAccountControlMapper *LdapMsadLdsUserAccountControlMapper) *component {
+	return &component{
+		Id:           ldapMsadLdsUserAccountControlMapper.Id,
+		Name:         ldapMsadLdsUserAccountControlMapper.Name,
+		ProviderId:   "msad-lds-user-account-control-mapper",
+		ProviderType: "org.keycloak.storage.ldap.mappers.LDAPStorageMapper",
+		ParentId:     ldapMsadLdsUserAccountControlMapper.LdapUserFederationId,
+	}
+}
+
+func convertFromComponentToLdapMsadLdsUserAccountControlMapper(component *component, realmId string) (*LdapMsadLdsUserAccountControlMapper, error) {
+	return &LdapMsadLdsUserAccountControlMapper{
+		Id:                   component.Id,
+		Name:                 component.Name,
+		RealmId:              realmId,
+		LdapUserFederationId: component.ParentId,
+	}, nil
+}
+
+func (keycloakClient *KeycloakClient) NewLdapMsadLdsUserAccountControlMapper(ldapMsadLdsUserAccountControlMapper *LdapMsadLdsUserAccountControlMapper) error {
+	_, location, err := keycloakClient.post(fmt.Sprintf("/realms/%s/components", ldapMsadLdsUserAccountControlMapper.RealmId), convertFromLdapMsadLdsUserAccountControlMapperToComponent(ldapMsadLdsUserAccountControlMapper))
+	if err != nil {
+		return err
+	}
+
+	ldapMsadLdsUserAccountControlMapper.Id = getIdFromLocationHeader(location)
+
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) GetLdapMsadLdsUserAccountControlMapper(realmId, id string) (*LdapMsadLdsUserAccountControlMapper, error) {
+	var component *component
+
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/components/%s", realmId, id), &component, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return convertFromComponentToLdapMsadLdsUserAccountControlMapper(component, realmId)
+}
+
+func (keycloakClient *KeycloakClient) UpdateLdapMsadLdsUserAccountControlMapper(ldapMsadLdsUserAccountControlMapper *LdapMsadLdsUserAccountControlMapper) error {
+	return keycloakClient.put(fmt.Sprintf("/realms/%s/components/%s", ldapMsadLdsUserAccountControlMapper.RealmId, ldapMsadLdsUserAccountControlMapper.Id), convertFromLdapMsadLdsUserAccountControlMapperToComponent(ldapMsadLdsUserAccountControlMapper))
+}
+
+func (keycloakClient *KeycloakClient) DeleteLdapMsadLdsUserAccountControlMapper(realmId, id string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/components/%s", realmId, id), nil)
+}
diff --git a/keycloak/openid_client_authorization_aggregate_policy.go b/keycloak/openid_client_authorization_aggregate_policy.go
new file mode 100644
index 0000000..e2acc7b
--- /dev/null
+++ b/keycloak/openid_client_authorization_aggregate_policy.go
@@ -0,0 +1,68 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationAggregatePolicy struct {
+	Id               string   `json:"id,omitempty"`
+	RealmId          string   `json:"-"`
+	ResourceServerId string   `json:"-"`
+	Name             string   `json:"name"`
+	DecisionStrategy string   `json:"decisionStrategy"`
+	Logic            string   `json:"logic"`
+	Policies         []string `json:"policies"`
+	Type             string   `json:"type"`
+	Description      string   `json:"description"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationAggregatePolicy(policy *OpenidClientAuthorizationAggregatePolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/aggregate", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationAggregatePolicy(policy *OpenidClientAuthorizationAggregatePolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/aggregate/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationAggregatePolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/aggregate/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationAggregatePolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationAggregatePolicy, error) {
+
+	policy := OpenidClientAuthorizationAggregatePolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/aggregate/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	var keycloakPolicies []map[string]interface{}
+	errTwo := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/%s/associatedPolicies", realmId, resourceServerId, policyId), &keycloakPolicies, nil)
+	if errTwo != nil {
+		return nil, err
+	}
+
+	for i := 0; i < len(keycloakPolicies); i++ {
+		policy.Policies = append(policy.Policies, keycloakPolicies[i]["id"].(string))
+	}
+
+	return &policy, nil
+}
diff --git a/keycloak/openid_client_authorization_client_policy.go b/keycloak/openid_client_authorization_client_policy.go
new file mode 100644
index 0000000..09b2c98
--- /dev/null
+++ b/keycloak/openid_client_authorization_client_policy.go
@@ -0,0 +1,57 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationClientPolicy struct {
+	Id               string   `json:"id,omitempty"`
+	RealmId          string   `json:"-"`
+	ResourceServerId string   `json:"-"`
+	Name             string   `json:"name"`
+	DecisionStrategy string   `json:"decisionStrategy"`
+	Logic            string   `json:"logic"`
+	Type             string   `json:"type"`
+	Clients          []string `json:"clients"`
+	Description      string   `json:"description"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationClientPolicy(policy *OpenidClientAuthorizationClientPolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/client", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationClientPolicy(policy *OpenidClientAuthorizationClientPolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/client/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationClientPolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/client/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationClientPolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationClientPolicy, error) {
+
+	policy := OpenidClientAuthorizationClientPolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/client/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &policy, nil
+}
diff --git a/keycloak/openid_client_authorization_group_policy.go b/keycloak/openid_client_authorization_group_policy.go
new file mode 100644
index 0000000..a21d860
--- /dev/null
+++ b/keycloak/openid_client_authorization_group_policy.go
@@ -0,0 +1,64 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationGroupPolicy struct {
+	Id               string                           `json:"id,omitempty"`
+	RealmId          string                           `json:"-"`
+	ResourceServerId string                           `json:"-"`
+	Name             string                           `json:"name"`
+	DecisionStrategy string                           `json:"decisionStrategy"`
+	Logic            string                           `json:"logic"`
+	Type             string                           `json:"type"`
+	GroupsClaim      string                           `json:"groupsClaim"`
+	Groups           []OpenidClientAuthorizationGroup `json:"groups,omitempty"`
+	Description      string                           `json:"description"`
+}
+
+type OpenidClientAuthorizationGroup struct {
+	Id             string `json:"id,omitempty"`
+	Path           string `json:"path,omitempty"`
+	ExtendChildren bool   `json:"extendChildren,omitempty"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationGroupPolicy(policy *OpenidClientAuthorizationGroupPolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/group", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationGroupPolicy(policy *OpenidClientAuthorizationGroupPolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/group/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationGroupPolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/role/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationGroupPolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationGroupPolicy, error) {
+
+	policy := OpenidClientAuthorizationGroupPolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/group/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &policy, nil
+}
diff --git a/keycloak/openid_client_authorization_js_policy.go b/keycloak/openid_client_authorization_js_policy.go
new file mode 100644
index 0000000..fe0ae65
--- /dev/null
+++ b/keycloak/openid_client_authorization_js_policy.go
@@ -0,0 +1,57 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationJSPolicy struct {
+	Id               string `json:"id,omitempty"`
+	RealmId          string `json:"-"`
+	ResourceServerId string `json:"-"`
+	Name             string `json:"name"`
+	DecisionStrategy string `json:"decisionStrategy"`
+	Logic            string `json:"logic"`
+	Type             string `json:"type"`
+	Code             string `json:"code"`
+	Description      string `json:"description"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationJSPolicy(policy *OpenidClientAuthorizationJSPolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/js", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationJSPolicy(policy *OpenidClientAuthorizationJSPolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/js/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationJSPolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/js/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationJSPolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationJSPolicy, error) {
+
+	policy := OpenidClientAuthorizationJSPolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/js/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &policy, nil
+}
diff --git a/keycloak/openid_client_authorization_role_policy.go b/keycloak/openid_client_authorization_role_policy.go
new file mode 100644
index 0000000..de04d5a
--- /dev/null
+++ b/keycloak/openid_client_authorization_role_policy.go
@@ -0,0 +1,62 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationRolePolicy struct {
+	Id               string                          `json:"id,omitempty"`
+	RealmId          string                          `json:"-"`
+	ResourceServerId string                          `json:"-"`
+	Name             string                          `json:"name"`
+	DecisionStrategy string                          `json:"decisionStrategy"`
+	Logic            string                          `json:"logic"`
+	Type             string                          `json:"type"`
+	Roles            []OpenidClientAuthorizationRole `json:"roles,omitempty"`
+	Description      string                          `json:"description"`
+}
+
+type OpenidClientAuthorizationRole struct {
+	Id       string `json:"id,omitempty"`
+	Required bool   `json:"required"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationRolePolicy(policy *OpenidClientAuthorizationRolePolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/role", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationRolePolicy(policy *OpenidClientAuthorizationRolePolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/role/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationRolePolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/role/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationRolePolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationRolePolicy, error) {
+
+	policy := OpenidClientAuthorizationRolePolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/role/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &policy, nil
+}
diff --git a/keycloak/openid_client_authorization_time_policy.go b/keycloak/openid_client_authorization_time_policy.go
new file mode 100644
index 0000000..965dd55
--- /dev/null
+++ b/keycloak/openid_client_authorization_time_policy.go
@@ -0,0 +1,68 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationTimePolicy struct {
+	Id               string `json:"id,omitempty"`
+	RealmId          string `json:"-"`
+	ResourceServerId string `json:"-"`
+	Name             string `json:"name"`
+	DecisionStrategy string `json:"decisionStrategy"`
+	Logic            string `json:"logic"`
+	Type             string `json:"type"`
+	NotBefore        string `json:"notBefore"`
+	NotOnOrAfter     string `json:"notOnOrAfter"`
+	DayMonth         string `json:"dayMonth"`
+	DayMonthEnd      string `json:"dayMonthEnd"`
+	Month            string `json:"month"`
+	MonthEnd         string `json:"monthEnd"`
+	Year             string `json:"year"`
+	YearEnd          string `json:"yearEnd"`
+	Hour             string `json:"hour"`
+	HourEnd          string `json:"hourEnd"`
+	Minute           string `json:"minute"`
+	MinuteEnd        string `json:"minuteEnd"`
+	Description      string `json:"description"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationTimePolicy(policy *OpenidClientAuthorizationTimePolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/time", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationTimePolicy(policy *OpenidClientAuthorizationTimePolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/time/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationTimePolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/time/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationTimePolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationTimePolicy, error) {
+
+	policy := OpenidClientAuthorizationTimePolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/time/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &policy, nil
+}
diff --git a/keycloak/openid_client_authorization_user_policy.go b/keycloak/openid_client_authorization_user_policy.go
new file mode 100644
index 0000000..7fe44d8
--- /dev/null
+++ b/keycloak/openid_client_authorization_user_policy.go
@@ -0,0 +1,57 @@
+package keycloak
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type OpenidClientAuthorizationUserPolicy struct {
+	Id               string   `json:"id,omitempty"`
+	RealmId          string   `json:"-"`
+	ResourceServerId string   `json:"-"`
+	Name             string   `json:"name"`
+	DecisionStrategy string   `json:"decisionStrategy"`
+	Logic            string   `json:"logic"`
+	Type             string   `json:"type"`
+	Users            []string `json:"users"`
+	Description      string   `json:"description"`
+}
+
+func (keycloakClient *KeycloakClient) NewOpenidClientAuthorizationUserPolicy(policy *OpenidClientAuthorizationUserPolicy) error {
+	body, _, err := keycloakClient.post(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/user", policy.RealmId, policy.ResourceServerId), policy)
+	if err != nil {
+		return err
+	}
+	err = json.Unmarshal(body, &policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) UpdateOpenidClientAuthorizationUserPolicy(policy *OpenidClientAuthorizationUserPolicy) error {
+	err := keycloakClient.put(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/user/%s", policy.RealmId, policy.ResourceServerId, policy.Id), policy)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (keycloakClient *KeycloakClient) DeleteOpenidClientAuthorizationUserPolicy(realmId, resourceServerId, policyId string) error {
+	return keycloakClient.delete(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/user/%s", realmId, resourceServerId, policyId), nil)
+}
+
+func (keycloakClient *KeycloakClient) GetOpenidClientAuthorizationUserPolicy(realmId, resourceServerId, policyId string) (*OpenidClientAuthorizationUserPolicy, error) {
+
+	policy := OpenidClientAuthorizationUserPolicy{
+		Id:               policyId,
+		ResourceServerId: resourceServerId,
+		RealmId:          realmId,
+	}
+	err := keycloakClient.get(fmt.Sprintf("/realms/%s/clients/%s/authz/resource-server/policy/user/%s", realmId, resourceServerId, policyId), &policy, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &policy, nil
+}
diff --git a/provider/data_source_keycloak_openid_client_authorization_policy.go b/provider/data_source_keycloak_openid_client_authorization_policy.go
index 12b1405..4dc9568 100644
--- a/provider/data_source_keycloak_openid_client_authorization_policy.go
+++ b/provider/data_source_keycloak_openid_client_authorization_policy.go
@@ -2,6 +2,7 @@ package provider
 
 import (
 	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
 	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
 )
 
@@ -31,8 +32,9 @@ func dataSourceKeycloakOpenidClientAuthorizationPolicy() *schema.Resource {
 				Computed: true,
 			},
 			"logic": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
 			},
 			"policies": {
 				Type:     schema.TypeSet,
diff --git a/provider/generic_resource_policy_import.go b/provider/generic_resource_policy_import.go
new file mode 100644
index 0000000..ca4d2b8
--- /dev/null
+++ b/provider/generic_resource_policy_import.go
@@ -0,0 +1,20 @@
+package provider
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+)
+
+func genericResourcePolicyImport(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) {
+	parts := strings.Split(d.Id(), "/")
+	if len(parts) != 3 {
+		return nil, fmt.Errorf("Invalid import. Supported import formats: {{realmId}}/{{resourceServerId}}/{{authorizationResourceId}}")
+	}
+	d.Set("realm_id", parts[0])
+	d.Set("resource_server_id", parts[1])
+	d.SetId(parts[3])
+
+	return []*schema.ResourceData{d}, nil
+}
diff --git a/provider/keycloak_policy_helpers.go b/provider/keycloak_policy_helpers.go
new file mode 100644
index 0000000..033662d
--- /dev/null
+++ b/provider/keycloak_policy_helpers.go
@@ -0,0 +1,5 @@
+package provider
+
+var (
+	keycloakPolicyLogicTypes = []string{"POSITIVE", "NEGATIVE"}
+)
diff --git a/provider/provider.go b/provider/provider.go
index 522cb2e..cedf783 100644
--- a/provider/provider.go
+++ b/provider/provider.go
@@ -32,6 +32,7 @@ func KeycloakProvider() *schema.Provider {
 			"keycloak_ldap_group_mapper":                               resourceKeycloakLdapGroupMapper(),
 			"keycloak_ldap_hardcoded_role_mapper":                      resourceKeycloakLdapHardcodedRoleMapper(),
 			"keycloak_ldap_msad_user_account_control_mapper":           resourceKeycloakLdapMsadUserAccountControlMapper(),
+			"keycloak_ldap_msad_lds_user_account_control_mapper":       resourceKeycloakLdapMsadLdsUserAccountControlMapper(),
 			"keycloak_ldap_full_name_mapper":                           resourceKeycloakLdapFullNameMapper(),
 			"keycloak_custom_user_federation":                          resourceKeycloakCustomUserFederation(),
 			"keycloak_openid_user_attribute_protocol_mapper":           resourceKeycloakOpenIdUserAttributeProtocolMapper(),
@@ -54,8 +55,16 @@ func KeycloakProvider() *schema.Provider {
 			"keycloak_attribute_to_role_identity_provider_mapper":      resourceKeycloakAttributeToRoleIdentityProviderMapper(),
 			"keycloak_user_template_importer_identity_provider_mapper": resourceKeycloakUserTemplateImporterIdentityProviderMapper(),
 			"keycloak_saml_identity_provider":                          resourceKeycloakSamlIdentityProvider(),
+			"keycloak_oidc_google_identity_provider":                   resourceKeycloakOidcGoogleIdentityProvider(),
 			"keycloak_oidc_identity_provider":                          resourceKeycloakOidcIdentityProvider(),
 			"keycloak_openid_client_authorization_resource":            resourceKeycloakOpenidClientAuthorizationResource(),
+			"keycloak_openid_client_group_policy":                      resourceKeycloakOpenidClientAuthorizationGroupPolicy(),
+			"keycloak_openid_client_role_policy":                       resourceKeycloakOpenidClientAuthorizationRolePolicy(),
+			"keycloak_openid_client_aggregate_policy":                  resourceKeycloakOpenidClientAuthorizationAggregatePolicy(),
+			"keycloak_openid_client_js_policy":                         resourceKeycloakOpenidClientAuthorizationJSPolicy(),
+			"keycloak_openid_client_time_policy":                       resourceKeycloakOpenidClientAuthorizationTimePolicy(),
+			"keycloak_openid_client_user_policy":                       resourceKeycloakOpenidClientAuthorizationUserPolicy(),
+			"keycloak_openid_client_client_policy":                     resourceKeycloakOpenidClientAuthorizationClientPolicy(),
 			"keycloak_openid_client_authorization_scope":               resourceKeycloakOpenidClientAuthorizationScope(),
 			"keycloak_openid_client_authorization_permission":          resourceKeycloakOpenidClientAuthorizationPermission(),
 			"keycloak_openid_client_service_account_role":              resourceKeycloakOpenidClientServiceAccountRole(),
@@ -64,6 +73,7 @@ func KeycloakProvider() *schema.Provider {
 			"keycloak_authentication_flow":                             resourceKeycloakAuthenticationFlow(),
 			"keycloak_authentication_subflow":                          resourceKeycloakAuthenticationSubFlow(),
 			"keycloak_authentication_execution":                        resourceKeycloakAuthenticationExecution(),
+			"keycloak_authentication_execution_config":                 resourceKeycloakAuthenticationExecutionConfig(),
 		},
 		Schema: map[string]*schema.Schema{
 			"client_id": {
diff --git a/provider/resource_keycloak_authentication_execution_config.go b/provider/resource_keycloak_authentication_execution_config.go
new file mode 100644
index 0000000..76d0bfe
--- /dev/null
+++ b/provider/resource_keycloak_authentication_execution_config.go
@@ -0,0 +1,137 @@
+package provider
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakAuthenticationExecutionConfig() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakAuthenticationExecutionConfigCreate,
+		Read:   resourceKeycloakAuthenticationExecutionConfigRead,
+		Delete: resourceKeycloakAuthenticationExecutionConfigDelete,
+		Update: resourceKeycloakAuthenticationExecutionConfigUpdate,
+		Importer: &schema.ResourceImporter{
+			State: resourceKeycloakAuthenticationExecutionConfigImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+				ForceNew: true,
+			},
+			"execution_id": {
+				Type:     schema.TypeString,
+				Required: true,
+				ForceNew: true,
+			},
+			"alias": {
+				Type:     schema.TypeString,
+				Required: true,
+				ForceNew: true,
+			},
+			"config": {
+				Type:     schema.TypeMap,
+				Elem:     &schema.Schema{Type: schema.TypeString},
+				Required: true,
+			},
+		},
+	}
+}
+
+func getAuthenticationExecutionConfigFromData(data *schema.ResourceData) *keycloak.AuthenticationExecutionConfig {
+	config := make(map[string]string)
+	for key, value := range data.Get("config").(map[string]interface{}) {
+		config[key] = value.(string)
+	}
+	return &keycloak.AuthenticationExecutionConfig{
+		Id:          data.Id(),
+		RealmId:     data.Get("realm_id").(string),
+		ExecutionId: data.Get("execution_id").(string),
+		Alias:       data.Get("alias").(string),
+		Config:      config,
+	}
+}
+
+func setAuthenticationExecutionConfigData(data *schema.ResourceData, config *keycloak.AuthenticationExecutionConfig) {
+	data.SetId(config.Id)
+	data.Set("realm_id", config.RealmId)
+	data.Set("execution_id", config.ExecutionId)
+	data.Set("alias", config.Alias)
+	data.Set("config", config.Config)
+}
+
+func resourceKeycloakAuthenticationExecutionConfigCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	config := getAuthenticationExecutionConfigFromData(data)
+
+	id, err := keycloakClient.NewAuthenticationExecutionConfig(config)
+	if err != nil {
+		return err
+	}
+
+	data.SetId(id)
+
+	return resourceKeycloakAuthenticationExecutionConfigRead(data, meta)
+}
+
+func resourceKeycloakAuthenticationExecutionConfigRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	config := &keycloak.AuthenticationExecutionConfig{
+		RealmId:     data.Get("realm_id").(string),
+		ExecutionId: data.Get("execution_id").(string),
+		Id:          data.Id(),
+	}
+
+	err := keycloakClient.GetAuthenticationExecutionConfig(config)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setAuthenticationExecutionConfigData(data, config)
+
+	return nil
+}
+
+func resourceKeycloakAuthenticationExecutionConfigUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	config := getAuthenticationExecutionConfigFromData(data)
+
+	err := keycloakClient.UpdateAuthenticationExecutionConfig(config)
+	if err != nil {
+		return err
+	}
+
+	return resourceKeycloakAuthenticationExecutionConfigRead(data, meta)
+}
+
+func resourceKeycloakAuthenticationExecutionConfigDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	config := &keycloak.AuthenticationExecutionConfig{
+		RealmId: data.Get("realm_id").(string),
+		Id:      data.Id(),
+	}
+
+	return keycloakClient.DeleteAuthenticationExecutionConfig(config)
+}
+
+func resourceKeycloakAuthenticationExecutionConfigImport(data *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) {
+	parts := strings.Split(data.Id(), "/")
+
+	if len(parts) != 3 || parts[0] == "" || parts[1] == "" || parts[2] == "" {
+		return nil, fmt.Errorf("invalid import. Supported import formats: {{realm}}/{{authenticationExecutionId}}/{{authenticationExecutionConfigId}}")
+	}
+
+	data.Set("realm_id", parts[0])
+	data.Set("execution_id", parts[1])
+	data.SetId(parts[2])
+
+	return []*schema.ResourceData{data}, nil
+}
diff --git a/provider/resource_keycloak_ldap_msad_lds_user_account_control_mapper.go b/provider/resource_keycloak_ldap_msad_lds_user_account_control_mapper.go
new file mode 100644
index 0000000..aab21da
--- /dev/null
+++ b/provider/resource_keycloak_ldap_msad_lds_user_account_control_mapper.go
@@ -0,0 +1,111 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakLdapMsadLdsUserAccountControlMapper() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakLdapMsadLdsUserAccountControlMapperCreate,
+		Read:   resourceKeycloakLdapMsadLdsUserAccountControlMapperRead,
+		Update: resourceKeycloakLdapMsadLdsUserAccountControlMapperUpdate,
+		Delete: resourceKeycloakLdapMsadLdsUserAccountControlMapperDelete,
+		// This resource can be imported using {{realm}}/{{provider_id}}/{{mapper_id}}. The Provider and Mapper IDs are displayed in the GUI
+		Importer: &schema.ResourceImporter{
+			State: resourceKeycloakLdapGenericMapperImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"name": {
+				Type:        schema.TypeString,
+				Required:    true,
+				Description: "Display name of the mapper when displayed in the console.",
+			},
+			"realm_id": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: "The realm in which the ldap user federation provider exists.",
+			},
+			"ldap_user_federation_id": {
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: "The ldap user federation provider to attach this mapper to.",
+			},
+		},
+	}
+}
+
+func getLdapMsadLdsUserAccountControlMapperFromData(data *schema.ResourceData) *keycloak.LdapMsadLdsUserAccountControlMapper {
+	return &keycloak.LdapMsadLdsUserAccountControlMapper{
+		Id:                   data.Id(),
+		Name:                 data.Get("name").(string),
+		RealmId:              data.Get("realm_id").(string),
+		LdapUserFederationId: data.Get("ldap_user_federation_id").(string),
+	}
+}
+
+func setLdapMsadLdsUserAccountControlMapperData(data *schema.ResourceData, ldapMsadLdsUserAccountControlMapper *keycloak.LdapMsadLdsUserAccountControlMapper) {
+	data.SetId(ldapMsadLdsUserAccountControlMapper.Id)
+
+	data.Set("id", ldapMsadLdsUserAccountControlMapper.Id)
+	data.Set("name", ldapMsadLdsUserAccountControlMapper.Name)
+	data.Set("realm_id", ldapMsadLdsUserAccountControlMapper.RealmId)
+	data.Set("ldap_user_federation_id", ldapMsadLdsUserAccountControlMapper.LdapUserFederationId)
+}
+
+func resourceKeycloakLdapMsadLdsUserAccountControlMapperCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	ldapMsadLdsUserAccountControlMapper := getLdapMsadLdsUserAccountControlMapperFromData(data)
+
+	err := keycloakClient.NewLdapMsadLdsUserAccountControlMapper(ldapMsadLdsUserAccountControlMapper)
+	if err != nil {
+		return err
+	}
+
+	setLdapMsadLdsUserAccountControlMapperData(data, ldapMsadLdsUserAccountControlMapper)
+
+	return resourceKeycloakLdapMsadLdsUserAccountControlMapperRead(data, meta)
+}
+
+func resourceKeycloakLdapMsadLdsUserAccountControlMapperRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	id := data.Id()
+
+	ldapMsadLdsUserAccountControlMapper, err := keycloakClient.GetLdapMsadLdsUserAccountControlMapper(realmId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setLdapMsadLdsUserAccountControlMapperData(data, ldapMsadLdsUserAccountControlMapper)
+
+	return nil
+}
+
+func resourceKeycloakLdapMsadLdsUserAccountControlMapperUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	ldapMsadLdsUserAccountControlMapper := getLdapMsadLdsUserAccountControlMapperFromData(data)
+
+	err := keycloakClient.UpdateLdapMsadLdsUserAccountControlMapper(ldapMsadLdsUserAccountControlMapper)
+	if err != nil {
+		return err
+	}
+
+	setLdapMsadLdsUserAccountControlMapperData(data, ldapMsadLdsUserAccountControlMapper)
+
+	return nil
+}
+
+func resourceKeycloakLdapMsadLdsUserAccountControlMapperDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteLdapMsadLdsUserAccountControlMapper(realmId, id)
+}
diff --git a/provider/resource_keycloak_oidc_google_identity_provider.go b/provider/resource_keycloak_oidc_google_identity_provider.go
new file mode 100644
index 0000000..02c76ec
--- /dev/null
+++ b/provider/resource_keycloak_oidc_google_identity_provider.go
@@ -0,0 +1,134 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOidcGoogleIdentityProvider() *schema.Resource {
+	oidcGoogleSchema := map[string]*schema.Schema{
+		"alias": {
+			Type:        schema.TypeString,
+			Computed:    true,
+			Description: "The alias uniquely identifies an identity provider and it is also used to build the redirect uri. In case of google this is computed and always google",
+		},
+		"display_name": {
+			Type:        schema.TypeString,
+			Computed:    true,
+			Description: "Not used by this provider, Will be implicitly Google",
+		},
+		"provider_id": {
+			Type:        schema.TypeString,
+			Optional:    true,
+			Default:     "google",
+			Description: "provider id, is always google, unless you have a extended custom implementation",
+		},
+		"client_id": {
+			Type:        schema.TypeString,
+			Required:    true,
+			Description: "Client ID.",
+		},
+		"client_secret": {
+			Type:        schema.TypeString,
+			Required:    true,
+			Sensitive:   true,
+			Description: "Client Secret.",
+		},
+		"hosted_domain": { //hostedDomain
+			Type:        schema.TypeString,
+			Optional:    true,
+			Description: "Set 'hd' query parameter when logging in with Google. Google will list accounts only for this domain. Keycloak validates that the returned identity token has a claim for this domain. When '*' is entered, any hosted account can be used.",
+		},
+		"use_user_ip_param": { //userIp
+			Type:        schema.TypeBool,
+			Optional:    true,
+			Default:     false,
+			Description: "Set 'userIp' query parameter when invoking on Google's User Info service.  This will use the user's ip address.  Useful if Google is throttling access to the User Info service.",
+		},
+		"request_refresh_token": { //offlineAccess
+			Type:        schema.TypeBool,
+			Optional:    true,
+			Default:     false,
+			Description: "Set 'access_type' query parameter to 'offline' when redirecting to google authorization endpoint, to get a refresh token back. Useful if planning to use Token Exchange to retrieve Google token to access Google APIs when the user is not at the browser.",
+		},
+		"default_scopes": { //defaultScope
+			Type:        schema.TypeString,
+			Optional:    true,
+			Default:     "openid profile email",
+			Description: "The scopes to be sent when asking for authorization. See the documentation for possible values, separator and default value'. Default: 'openid profile email'",
+		},
+		"accepts_prompt_none_forward_from_client": { // acceptsPromptNoneForwardFromClient
+			Type:        schema.TypeBool,
+			Optional:    true,
+			Default:     false,
+			Description: "This is just used together with Identity Provider Authenticator or when kc_idp_hint points to this identity provider. In case that client sends a request with prompt=none and user is not yet authenticated, the error will not be directly returned to client, but the request with prompt=none will be forwarded to this identity provider.",
+		},
+		"disable_user_info": { //disableUserInfo
+			Type:        schema.TypeBool,
+			Optional:    true,
+			Default:     false,
+			Description: "Disable usage of User Info service to obtain additional user information?  Default is to use this OIDC service.",
+		},
+		"hide_on_login_page": {
+			Type:        schema.TypeBool,
+			Optional:    true,
+			Default:     false,
+			Description: "Hide On Login Page.",
+		},
+		"extra_config": {
+			Type:     schema.TypeMap,
+			Optional: true,
+		},
+	}
+	oidcResource := resourceKeycloakIdentityProvider()
+	oidcResource.Schema = mergeSchemas(oidcResource.Schema, oidcGoogleSchema)
+	oidcResource.Create = resourceKeycloakIdentityProviderCreate(getOidcGoogleIdentityProviderFromData, setOidcGoogleIdentityProviderData)
+	oidcResource.Read = resourceKeycloakIdentityProviderRead(setOidcGoogleIdentityProviderData)
+	oidcResource.Update = resourceKeycloakIdentityProviderUpdate(getOidcGoogleIdentityProviderFromData, setOidcGoogleIdentityProviderData)
+	return oidcResource
+}
+
+func getOidcGoogleIdentityProviderFromData(data *schema.ResourceData) (*keycloak.IdentityProvider, error) {
+	rec, _ := getIdentityProviderFromData(data)
+	rec.ProviderId = data.Get("provider_id").(string)
+	rec.Alias = "google"
+
+	extraConfig := map[string]interface{}{}
+	if v, ok := data.GetOk("extra_config"); ok {
+		for key, value := range v.(map[string]interface{}) {
+			extraConfig[key] = value
+		}
+	}
+
+	rec.Config = &keycloak.IdentityProviderConfig{
+		ClientId:                    data.Get("client_id").(string),
+		ClientSecret:                data.Get("client_secret").(string),
+		HideOnLoginPage:             keycloak.KeycloakBoolQuoted(data.Get("hide_on_login_page").(bool)),
+		HostedDomain:                data.Get("hosted_domain").(string),
+		UserIp:                      keycloak.KeycloakBoolQuoted(data.Get("use_user_ip_param").(bool)),
+		OfflineAccess:               keycloak.KeycloakBoolQuoted(data.Get("request_refresh_token").(bool)),
+		DefaultScope:                data.Get("default_scopes").(string),
+		AcceptsPromptNoneForwFrmClt: keycloak.KeycloakBoolQuoted(data.Get("accepts_prompt_none_forward_from_client").(bool)),
+		ExtraConfig:                 extraConfig,
+		UseJwksUrl:                  keycloak.KeycloakBoolQuoted(true),
+		DisableUserInfo:             keycloak.KeycloakBoolQuoted(data.Get("disable_user_info").(bool)),
+	}
+
+	return rec, nil
+}
+
+func setOidcGoogleIdentityProviderData(data *schema.ResourceData, identityProvider *keycloak.IdentityProvider) error {
+	setIdentityProviderData(data, identityProvider)
+	data.Set("provider_id", identityProvider.ProviderId)
+	data.Set("client_id", identityProvider.Config.ClientId)
+	data.Set("hide_on_login_page", identityProvider.Config.HideOnLoginPage)
+	data.Set("hosted_domain", identityProvider.Config.HostedDomain)
+	data.Set("use_user_ip_param", identityProvider.Config.UserIp)
+	data.Set("request_refresh_token", identityProvider.Config.OfflineAccess)
+	data.Set("default_scopes", identityProvider.Config.DefaultScope)
+	data.Set("accepts_prompt_none_forward_from_client", identityProvider.Config.AcceptsPromptNoneForwFrmClt)
+	data.Set("extra_config", identityProvider.Config.ExtraConfig)
+	data.Set("use_jwks_url", identityProvider.Config.UseJwksUrl)
+	data.Set("disable_user_info", identityProvider.Config.DisableUserInfo)
+	return nil
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_aggregate_policy.go b/provider/resource_keycloak_openid_client_authorization_aggregate_policy.go
new file mode 100644
index 0000000..9aa659b
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_aggregate_policy.go
@@ -0,0 +1,141 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationAggregatePolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationAggregatePolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationAggregatePolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationAggregatePolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationAggregatePolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"policies": {
+				Type:     schema.TypeSet,
+				Elem:     &schema.Schema{Type: schema.TypeString},
+				Required: true,
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationAggregatePolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationAggregatePolicy {
+	var policies []string
+
+	if v, ok := data.GetOk("policies"); ok {
+		for _, policy := range v.(*schema.Set).List() {
+			policies = append(policies, policy.(string))
+		}
+	}
+
+	resource := keycloak.OpenidClientAuthorizationAggregatePolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "aggregate",
+		Policies:         policies,
+		Description:      data.Get("description").(string),
+	}
+	return &resource
+}
+
+func setOpenidClientAuthorizationAggregatePolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationAggregatePolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("policies", policy.Policies)
+	data.Set("description", policy.Description)
+}
+
+func resourceKeycloakOpenidClientAuthorizationAggregatePolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationAggregatePolicyResourceFromData(data)
+	err := keycloakClient.NewOpenidClientAuthorizationAggregatePolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationAggregatePolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationAggregatePolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationAggregatePolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationAggregatePolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationAggregatePolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationAggregatePolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+	resource := getOpenidClientAuthorizationAggregatePolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationAggregatePolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationAggregatePolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationAggregatePolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationAggregatePolicy(realmId, resourceServerId, id)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_client_policy.go b/provider/resource_keycloak_openid_client_authorization_client_policy.go
new file mode 100644
index 0000000..1e2bb7c
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_client_policy.go
@@ -0,0 +1,143 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationClientPolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationClientPolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationClientPolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationClientPolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationClientPolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"clients": {
+				Type:     schema.TypeSet,
+				Elem:     &schema.Schema{Type: schema.TypeString},
+				Required: true,
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationClientAuthorizationClientPolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationClientPolicy {
+	var clients []string
+
+	if v, ok := data.GetOk("clients"); ok {
+		for _, client := range v.(*schema.Set).List() {
+			clients = append(clients, client.(string))
+		}
+	}
+
+	resource := keycloak.OpenidClientAuthorizationClientPolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "client",
+		Clients:          clients,
+		Description:      data.Get("description").(string),
+	}
+	return &resource
+}
+
+func setOpenidClientAuthorizationClientAuthorizationClientPolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationClientPolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("description", policy.Description)
+	data.Set("clients", policy.Clients)
+}
+
+func resourceKeycloakOpenidClientAuthorizationClientPolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationClientAuthorizationClientPolicyResourceFromData(data)
+
+	err := keycloakClient.NewOpenidClientAuthorizationClientPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationClientAuthorizationClientPolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationClientPolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationClientPolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationClientPolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationClientAuthorizationClientPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationClientPolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationClientAuthorizationClientPolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationClientPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationClientAuthorizationClientPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationClientPolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationClientPolicy(realmId, resourceServerId, id)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_group_policy.go b/provider/resource_keycloak_openid_client_authorization_group_policy.go
new file mode 100644
index 0000000..e2dd202
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_group_policy.go
@@ -0,0 +1,171 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationGroupPolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationGroupPolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationGroupPolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationGroupPolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationGroupPolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"groups_claim": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"groups": {
+				Type:     schema.TypeList,
+				Required: true,
+				MinItems: 1,
+				Elem: &schema.Resource{
+					Schema: map[string]*schema.Schema{
+						"id": {
+							Type:     schema.TypeString,
+							Required: true,
+						},
+						"path": {
+							Type:     schema.TypeString,
+							Required: true,
+						},
+						"extend_children": {
+							Type:     schema.TypeBool,
+							Required: true,
+						},
+					},
+				},
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationGroupPolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationGroupPolicy {
+	var groups []keycloak.OpenidClientAuthorizationGroup
+	if v, ok := data.Get("groups").([]interface{}); ok {
+		for _, group := range v {
+			groupMap := group.(map[string]interface{})
+			tempGroup := keycloak.OpenidClientAuthorizationGroup{
+				Id:             groupMap["id"].(string),
+				Path:           groupMap["path"].(string),
+				ExtendChildren: groupMap["extend_children"].(bool),
+			}
+			groups = append(groups, tempGroup)
+		}
+	}
+
+	resource := keycloak.OpenidClientAuthorizationGroupPolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "group",
+		GroupsClaim:      data.Get("groups_claim").(string),
+		Groups:           groups,
+		Description:      data.Get("description").(string),
+	}
+
+	return &resource
+}
+
+func setOpenidClientAuthorizationGroupPolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationGroupPolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("description", policy.Description)
+	data.Set("groups_claim", policy.GroupsClaim)
+	data.Set("groups", policy.Groups)
+}
+
+func resourceKeycloakOpenidClientAuthorizationGroupPolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationGroupPolicyResourceFromData(data)
+
+	err := keycloakClient.NewOpenidClientAuthorizationGroupPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationGroupPolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationGroupPolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationGroupPolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationGroupPolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationGroupPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationGroupPolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationGroupPolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationGroupPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationGroupPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationGroupPolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationGroupPolicy(realmId, resourceServerId, id)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_js_policy.go b/provider/resource_keycloak_openid_client_authorization_js_policy.go
new file mode 100644
index 0000000..f052e65
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_js_policy.go
@@ -0,0 +1,139 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationJSPolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationJSPolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationJSPolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationJSPolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationJSPolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"type": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"code": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationJSPolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationJSPolicy {
+
+	resource := keycloak.OpenidClientAuthorizationJSPolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "js",
+		Code:             data.Get("code").(string),
+		Description:      data.Get("description").(string),
+	}
+	return &resource
+}
+
+func setOpenidClientAuthorizationJSPolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationJSPolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("description", policy.Description)
+	data.Set("code", policy.Code)
+}
+
+func resourceKeycloakOpenidClientAuthorizationJSPolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationJSPolicyResourceFromData(data)
+
+	err := keycloakClient.NewOpenidClientAuthorizationJSPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationJSPolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationJSPolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationJSPolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationJSPolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationJSPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationJSPolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationJSPolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationJSPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationJSPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationJSPolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationJSPolicy(realmId, resourceServerId, id)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_role_policy.go b/provider/resource_keycloak_openid_client_authorization_role_policy.go
new file mode 100644
index 0000000..09b9b23
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_role_policy.go
@@ -0,0 +1,165 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationRolePolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationRolePolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationRolePolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationRolePolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationRolePolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"type": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"role": {
+				Type:     schema.TypeList,
+				Required: true,
+				MinItems: 1,
+				Elem: &schema.Resource{
+					Schema: map[string]*schema.Schema{
+						"id": {
+							Type:     schema.TypeString,
+							Required: true,
+						},
+						"required": {
+							Type:     schema.TypeBool,
+							Required: true,
+						},
+					},
+				},
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationRolePolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationRolePolicy {
+	var rolesList []keycloak.OpenidClientAuthorizationRole
+	if v, ok := data.Get("role").([]interface{}); ok {
+		for _, role := range v {
+			roleMap := role.(map[string]interface{})
+			tempRole := keycloak.OpenidClientAuthorizationRole{
+				Id:       roleMap["id"].(string),
+				Required: roleMap["required"].(bool),
+			}
+			rolesList = append(rolesList, tempRole)
+		}
+	}
+
+	resource := keycloak.OpenidClientAuthorizationRolePolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "role",
+		Roles:            rolesList,
+		Description:      data.Get("description").(string),
+	}
+
+	return &resource
+}
+
+func setOpenidClientAuthorizationRolePolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationRolePolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("type", policy.Type)
+	data.Set("description", policy.Description)
+	data.Set("roles", policy.Roles)
+}
+
+func resourceKeycloakOpenidClientAuthorizationRolePolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationRolePolicyResourceFromData(data)
+
+	err := keycloakClient.NewOpenidClientAuthorizationRolePolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationRolePolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationRolePolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationRolePolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationRolePolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationRolePolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationRolePolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationRolePolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationRolePolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationRolePolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationRolePolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationRolePolicy(realmId, resourceServerId, id)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_time_policy.go b/provider/resource_keycloak_openid_client_authorization_time_policy.go
new file mode 100644
index 0000000..6f8e0d1
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_time_policy.go
@@ -0,0 +1,202 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationTimePolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationTimePolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationTimePolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationTimePolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationTimePolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"not_before": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"not_on_or_after": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"day_month": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"day_month_end": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"month": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"month_end": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"year": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"year_end": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"hour": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"hour_end": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"minute": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"minute_end": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationTimePolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationTimePolicy {
+
+	resource := keycloak.OpenidClientAuthorizationTimePolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "time",
+		NotBefore:        data.Get("not_before").(string),
+		NotOnOrAfter:     data.Get("not_on_or_after").(string),
+		DayMonth:         data.Get("day_month").(string),
+		DayMonthEnd:      data.Get("day_month_end").(string),
+		Month:            data.Get("month").(string),
+		MonthEnd:         data.Get("month_end").(string),
+		Year:             data.Get("year").(string),
+		YearEnd:          data.Get("year_end").(string),
+		Hour:             data.Get("hour").(string),
+		HourEnd:          data.Get("hour_end").(string),
+		Minute:           data.Get("minute").(string),
+		MinuteEnd:        data.Get("minute_end").(string),
+		Description:      data.Get("description").(string),
+	}
+	return &resource
+}
+
+func setOpenidClientAuthorizationTimePolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationTimePolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("type", policy.Type)
+	data.Set("description", policy.Description)
+	data.Set("not_on_or_after", policy.NotOnOrAfter)
+	data.Set("not_before", policy.NotBefore)
+	data.Set("day_month", policy.DayMonth)
+	data.Set("day_month_end", policy.DayMonthEnd)
+	data.Set("month", policy.Month)
+	data.Set("month_end", policy.MonthEnd)
+	data.Set("year", policy.Year)
+	data.Set("year_end", policy.YearEnd)
+	data.Set("hour", policy.Hour)
+	data.Set("hour_end", policy.HourEnd)
+	data.Set("minute", policy.Minute)
+	data.Set("minute_end", policy.MinuteEnd)
+}
+
+func resourceKeycloakOpenidClientAuthorizationTimePolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationTimePolicyResourceFromData(data)
+
+	err := keycloakClient.NewOpenidClientAuthorizationTimePolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationTimePolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationTimePolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationTimePolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationTimePolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationTimePolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationTimePolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationTimePolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationTimePolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationTimePolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationTimePolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationTimePolicy(realmId, resourceServerId, id)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_user_policy.go b/provider/resource_keycloak_openid_client_authorization_user_policy.go
new file mode 100644
index 0000000..1d25f17
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_user_policy.go
@@ -0,0 +1,142 @@
+package provider
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func resourceKeycloakOpenidClientAuthorizationUserPolicy() *schema.Resource {
+	return &schema.Resource{
+		Create: resourceKeycloakOpenidClientAuthorizationUserPolicyCreate,
+		Read:   resourceKeycloakOpenidClientAuthorizationUserPolicyRead,
+		Delete: resourceKeycloakOpenidClientAuthorizationUserPolicyDelete,
+		Update: resourceKeycloakOpenidClientAuthorizationUserPolicyUpdate,
+		Importer: &schema.ResourceImporter{
+			State: genericResourcePolicyImport,
+		},
+		Schema: map[string]*schema.Schema{
+			"resource_server_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"realm_id": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"name": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"decision_strategy": {
+				Type:     schema.TypeString,
+				Required: true,
+			},
+			"logic": {
+				Type:         schema.TypeString,
+				Optional:     true,
+				ValidateFunc: validation.StringInSlice(keycloakPolicyLogicTypes, false),
+			},
+			"description": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
+			"users": {
+				Type:     schema.TypeSet,
+				Elem:     &schema.Schema{Type: schema.TypeString},
+				Required: true,
+			},
+		},
+	}
+}
+
+func getOpenidClientAuthorizationUserPolicyResourceFromData(data *schema.ResourceData) *keycloak.OpenidClientAuthorizationUserPolicy {
+	var users []string
+	if v, ok := data.GetOk("users"); ok {
+		for _, user := range v.(*schema.Set).List() {
+			users = append(users, user.(string))
+		}
+	}
+
+	resource := keycloak.OpenidClientAuthorizationUserPolicy{
+		Id:               data.Id(),
+		ResourceServerId: data.Get("resource_server_id").(string),
+		RealmId:          data.Get("realm_id").(string),
+		DecisionStrategy: data.Get("decision_strategy").(string),
+		Logic:            data.Get("logic").(string),
+		Name:             data.Get("name").(string),
+		Type:             "user",
+		Users:            users,
+		Description:      data.Get("description").(string),
+	}
+	return &resource
+}
+
+func setOpenidClientAuthorizationUserPolicyResourceData(data *schema.ResourceData, policy *keycloak.OpenidClientAuthorizationUserPolicy) {
+	data.SetId(policy.Id)
+
+	data.Set("resource_server_id", policy.ResourceServerId)
+	data.Set("realm_id", policy.RealmId)
+	data.Set("name", policy.Name)
+	data.Set("decision_strategy", policy.DecisionStrategy)
+	data.Set("logic", policy.Logic)
+	data.Set("description", policy.Description)
+	data.Set("users", policy.Users)
+}
+
+func resourceKeycloakOpenidClientAuthorizationUserPolicyCreate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationUserPolicyResourceFromData(data)
+
+	err := keycloakClient.NewOpenidClientAuthorizationUserPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationUserPolicyResourceData(data, resource)
+
+	return resourceKeycloakOpenidClientAuthorizationUserPolicyRead(data, meta)
+}
+
+func resourceKeycloakOpenidClientAuthorizationUserPolicyRead(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	resource, err := keycloakClient.GetOpenidClientAuthorizationUserPolicy(realmId, resourceServerId, id)
+	if err != nil {
+		return handleNotFoundError(err, data)
+	}
+
+	setOpenidClientAuthorizationUserPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationUserPolicyUpdate(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	resource := getOpenidClientAuthorizationUserPolicyResourceFromData(data)
+
+	err := keycloakClient.UpdateOpenidClientAuthorizationUserPolicy(resource)
+	if err != nil {
+		return err
+	}
+
+	setOpenidClientAuthorizationUserPolicyResourceData(data, resource)
+
+	return nil
+}
+
+func resourceKeycloakOpenidClientAuthorizationUserPolicyDelete(data *schema.ResourceData, meta interface{}) error {
+	keycloakClient := meta.(*keycloak.KeycloakClient)
+
+	realmId := data.Get("realm_id").(string)
+	resourceServerId := data.Get("resource_server_id").(string)
+	id := data.Id()
+
+	return keycloakClient.DeleteOpenidClientAuthorizationUserPolicy(realmId, resourceServerId, id)
+}


Test patch:
diff --git a/provider/resource_keycloak_authentication_execution_config_test.go b/provider/resource_keycloak_authentication_execution_config_test.go
new file mode 100644
index 0000000..b0e19dc
--- /dev/null
+++ b/provider/resource_keycloak_authentication_execution_config_test.go
@@ -0,0 +1,253 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestAccKeycloakAuthenticationExecutionConfig_basic(t *testing.T) {
+	realmName := "terraform-r-" + acctest.RandString(10)
+	var config1, config2 keycloak.AuthenticationExecutionConfig
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakAuthenticationExecutionConfigDestroy,
+		Steps: []resource.TestStep{
+			{
+				Config: testAccKeycloakAuthenticationExecutionConfig(realmName),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakAuthenticationExecutionConfigExists("keycloak_authentication_execution_config.config", &config1),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "realm_id", realmName),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "alias", "some-config-alias"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.%", "1"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.defaultProvider", "some-config-default-idp"),
+				),
+			},
+			{
+				Config: testAccKeycloakAuthenticationExecutionConfigUpdatedConfig(realmName),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakAuthenticationExecutionConfigExists("keycloak_authentication_execution_config.config", &config2),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "realm_id", realmName),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "alias", "some-config-alias"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.%", "1"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.defaultProvider", "some-updated-config-default-idp"),
+					testAccCheckKeycloakAuthenticationExecutionConfigForceNew(&config1, &config2, false),
+				),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakAuthenticationExecutionConfig_updateForcesNew(t *testing.T) {
+	realmName := "terraform-r-" + acctest.RandString(10)
+	var config1, config2 keycloak.AuthenticationExecutionConfig
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakAuthenticationExecutionConfigDestroy,
+		Steps: []resource.TestStep{
+			{
+				Config: testAccKeycloakAuthenticationExecutionConfig(realmName),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakAuthenticationExecutionConfigExists("keycloak_authentication_execution_config.config", &config1),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "realm_id", realmName),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "alias", "some-config-alias"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.%", "1"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.defaultProvider", "some-config-default-idp"),
+				),
+			},
+			{
+				Config: testAccKeycloakAuthenticationExecutionConfigUpdatedAlias(realmName),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakAuthenticationExecutionConfigExists("keycloak_authentication_execution_config.config", &config2),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "realm_id", realmName),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "alias", "some-updated-config-alias"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.%", "1"),
+					resource.TestCheckResourceAttr("keycloak_authentication_execution_config.config", "config.defaultProvider", "some-config-default-idp"),
+					testAccCheckKeycloakAuthenticationExecutionConfigForceNew(&config1, &config2, true),
+				),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakAuthenticationExecutionConfig_import(t *testing.T) {
+	realmName := "terraform-r-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakAuthenticationExecutionConfigDestroy,
+		Steps: []resource.TestStep{
+			{
+				Config: testAccKeycloakAuthenticationExecutionConfig(realmName),
+			},
+			{
+				ResourceName:      "keycloak_authentication_execution_config.config",
+				ImportState:       true,
+				ImportStateVerify: true,
+				ImportStateIdFunc: getExecutionConfigImportId("keycloak_authentication_execution_config.config"),
+			},
+		},
+	})
+}
+
+func getExecutionConfigImportId(resourceName string) resource.ImportStateIdFunc {
+	return func(s *terraform.State) (string, error) {
+		rs, ok := s.RootModule().Resources[resourceName]
+		if !ok {
+			return "", fmt.Errorf("resource %s not found", resourceName)
+		}
+
+		realmId := rs.Primary.Attributes["realm_id"]
+		executionId := rs.Primary.Attributes["execution_id"]
+		id := rs.Primary.ID
+
+		return fmt.Sprintf("%s/%s/%s", realmId, executionId, id), nil
+	}
+}
+
+func testAccCheckKeycloakAuthenticationExecutionConfigExists(resourceName string, config *keycloak.AuthenticationExecutionConfig) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		rs, ok := s.RootModule().Resources[resourceName]
+		if !ok {
+			return fmt.Errorf("resource %s not found in state", resourceName)
+		}
+
+		config.RealmId = rs.Primary.Attributes["realm_id"]
+		config.ExecutionId = rs.Primary.Attributes["execution_id"]
+		config.Id = rs.Primary.ID
+
+		keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+		if err := keycloakClient.GetAuthenticationExecutionConfig(config); err != nil {
+			return fmt.Errorf("error fetching authentication execution config: %v", err)
+		}
+
+		return nil
+	}
+}
+
+func testAccCheckKeycloakAuthenticationExecutionConfigDestroy(s *terraform.State) error {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	for _, rs := range s.RootModule().Resources {
+		if rs.Type != "keycloak_authentication_execution_config" {
+			continue
+		}
+
+		config := &keycloak.AuthenticationExecutionConfig{
+			RealmId: rs.Primary.Attributes["realm_id"],
+			Id:      rs.Primary.ID,
+		}
+		if err := keycloakClient.GetAuthenticationExecutionConfig(config); err == nil {
+			return fmt.Errorf("authentication execution config still exists")
+		} else if !keycloak.ErrorIs404(err) {
+			return fmt.Errorf("could not fetch authentication execution config: %v", err)
+		}
+	}
+
+	return nil
+}
+
+func testAccCheckKeycloakAuthenticationExecutionConfigForceNew(old, new *keycloak.AuthenticationExecutionConfig, wantNew bool) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		if wantNew {
+			if old.Id == new.Id {
+				return fmt.Errorf("expecting authentication execution config ID to differ, got %+v and %+v", old, new)
+			}
+		} else {
+			if old.Id != new.Id {
+				return fmt.Errorf("expecting authentication execution config ID to be equal, got %+v and %+v", old, new)
+			}
+		}
+		return nil
+	}
+}
+
+func testAccKeycloakAuthenticationExecutionConfig(realm string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_authentication_flow" "flow" {
+	realm_id = "${keycloak_realm.realm.id}"
+	alias    = "some-flow-alias"
+}
+
+resource "keycloak_authentication_execution" "execution" {
+	realm_id          = "${keycloak_realm.realm.id}"
+	parent_flow_alias = "${keycloak_authentication_flow.flow.alias}"
+	authenticator     = "identity-provider-redirector"
+}
+
+resource "keycloak_authentication_execution_config" "config" {
+	realm_id     = "${keycloak_realm.realm.id}"
+	execution_id = "${keycloak_authentication_execution.execution.id}"
+	alias        = "some-config-alias"
+	config = {
+		defaultProvider = "some-config-default-idp"
+	}
+}`, realm)
+}
+
+func testAccKeycloakAuthenticationExecutionConfigUpdatedConfig(realm string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_authentication_flow" "flow" {
+	realm_id = "${keycloak_realm.realm.id}"
+	alias    = "some-flow-alias"
+}
+
+resource "keycloak_authentication_execution" "execution" {
+	realm_id          = "${keycloak_realm.realm.id}"
+	parent_flow_alias = "${keycloak_authentication_flow.flow.alias}"
+	authenticator     = "identity-provider-redirector"
+}
+
+resource "keycloak_authentication_execution_config" "config" {
+	realm_id     = "${keycloak_realm.realm.id}"
+	execution_id = "${keycloak_authentication_execution.execution.id}"
+	alias        = "some-config-alias"
+	config = {
+		defaultProvider = "some-updated-config-default-idp"
+	}
+}`, realm)
+}
+
+func testAccKeycloakAuthenticationExecutionConfigUpdatedAlias(realm string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_authentication_flow" "flow" {
+	realm_id = "${keycloak_realm.realm.id}"
+	alias    = "some-flow-alias"
+}
+
+resource "keycloak_authentication_execution" "execution" {
+	realm_id          = "${keycloak_realm.realm.id}"
+	parent_flow_alias = "${keycloak_authentication_flow.flow.alias}"
+	authenticator     = "identity-provider-redirector"
+}
+
+resource "keycloak_authentication_execution_config" "config" {
+	realm_id     = "${keycloak_realm.realm.id}"
+	execution_id = "${keycloak_authentication_execution.execution.id}"
+	alias        = "some-updated-config-alias"
+	config = {
+		defaultProvider = "some-config-default-idp"
+	}
+}`, realm)
+}
diff --git a/provider/resource_keycloak_ldap_msad_lds_user_account_control_mapper_test.go b/provider/resource_keycloak_ldap_msad_lds_user_account_control_mapper_test.go
new file mode 100644
index 0000000..69b288d
--- /dev/null
+++ b/provider/resource_keycloak_ldap_msad_lds_user_account_control_mapper_test.go
@@ -0,0 +1,277 @@
+package provider
+
+import (
+	"fmt"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+	"testing"
+)
+
+func TestAccKeycloakLdapMsadLdsUserAccountControlMapper_basic(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	msadLdsUacMapperName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakLdapMsadLdsUserAccountControlMapper_basic(realmName, msadLdsUacMapperName),
+				Check:  testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperExists("keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper"),
+			},
+			{
+				ResourceName:      "keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper",
+				ImportState:       true,
+				ImportStateVerify: true,
+				ImportStateIdFunc: getLdapGenericMapperImportId("keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper"),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakLdapMsadLdsUserAccountControlMapper_createAfterManualDestroy(t *testing.T) {
+	var mapper = &keycloak.LdapMsadLdsUserAccountControlMapper{}
+
+	realmName := "terraform-" + acctest.RandString(10)
+	msadLdsUacMapperName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakLdapMsadLdsUserAccountControlMapper_basic(realmName, msadLdsUacMapperName),
+				Check:  testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperFetch("keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper", mapper),
+			},
+			{
+				PreConfig: func() {
+					keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+					err := keycloakClient.DeleteLdapMsadLdsUserAccountControlMapper(mapper.RealmId, mapper.Id)
+					if err != nil {
+						t.Fatal(err)
+					}
+				},
+				Config: testKeycloakLdapMsadLdsUserAccountControlMapper_basic(realmName, msadLdsUacMapperName),
+				Check:  testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperExists("keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper"),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakLdapMsadLdsUserAccountControlMapper_updateLdapUserFederation(t *testing.T) {
+	realmOne := "terraform-" + acctest.RandString(10)
+	realmTwo := "terraform-" + acctest.RandString(10)
+	msadLdsUacMapperName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakLdapMsadLdsUserAccountControlMapper_updateLdapUserFederationBefore(realmOne, realmTwo, msadLdsUacMapperName),
+				Check:  testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperExists("keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper"),
+			},
+			{
+				Config: testKeycloakLdapMsadLdsUserAccountControlMapper_updateLdapUserFederationAfter(realmOne, realmTwo, msadLdsUacMapperName),
+				Check:  testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperExists("keycloak_ldap_msad_lds_user_account_control_mapper.uac_mapper"),
+			},
+		},
+	})
+}
+
+func testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getLdapMsadLdsUserAccountControlMapperFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperFetch(resourceName string, mapper *keycloak.LdapMsadLdsUserAccountControlMapper) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		fetchedMapper, err := getLdapMsadLdsUserAccountControlMapperFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		mapper.Id = fetchedMapper.Id
+		mapper.RealmId = fetchedMapper.RealmId
+
+		return nil
+	}
+}
+
+func testAccCheckKeycloakLdapMsadLdsUserAccountControlMapperDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_ldap_msad_lds_user_account_control_mapper" {
+				continue
+			}
+
+			id := rs.Primary.ID
+			realm := rs.Primary.Attributes["realm_id"]
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			ldapMsadLdsUserAccountControlMapper, _ := keycloakClient.GetLdapMsadLdsUserAccountControlMapper(realm, id)
+			if ldapMsadLdsUserAccountControlMapper != nil {
+				return fmt.Errorf("ldap msad-lds uac mapper with id %s still exists", id)
+			}
+		}
+
+		return nil
+	}
+}
+
+func getLdapMsadLdsUserAccountControlMapperFromState(s *terraform.State, resourceName string) (*keycloak.LdapMsadLdsUserAccountControlMapper, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	id := rs.Primary.ID
+	realm := rs.Primary.Attributes["realm_id"]
+
+	ldapMsadLdsUserAccountControlMapper, err := keycloakClient.GetLdapMsadLdsUserAccountControlMapper(realm, id)
+	if err != nil {
+		return nil, fmt.Errorf("error getting ldap msad-lds uac mapper with id %s: %s", id, err)
+	}
+
+	return ldapMsadLdsUserAccountControlMapper, nil
+}
+
+func testKeycloakLdapMsadLdsUserAccountControlMapper_basic(realm, msadLdsUacMapperName string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+resource "keycloak_ldap_user_federation" "openldap" {
+	name                    = "openldap"
+	realm_id                = "${keycloak_realm.realm.id}"
+	enabled                 = true
+	username_ldap_attribute = "cn"
+	rdn_ldap_attribute      = "cn"
+	uuid_ldap_attribute     = "entryDN"
+	user_object_classes     = [
+		"simpleSecurityObject",
+		"organizationalRole"
+	]
+	connection_url          = "ldap://openldap"
+	users_dn                = "dc=example,dc=org"
+	bind_dn                 = "cn=admin,dc=example,dc=org"
+	bind_credential         = "admin"
+}
+resource "keycloak_ldap_msad_lds_user_account_control_mapper" "uac_mapper" {
+	name                               = "%s"
+	realm_id                           = "${keycloak_realm.realm.id}"
+	ldap_user_federation_id            = "${keycloak_ldap_user_federation.openldap.id}"
+}
+	`, realm, msadLdsUacMapperName)
+}
+
+func testKeycloakLdapMsadLdsUserAccountControlMapper_updateLdapUserFederationBefore(realmOne, realmTwo, msadLdsUacMapperName string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm_one" {
+	realm = "%s"
+}
+resource "keycloak_realm" "realm_two" {
+	realm = "%s"
+}
+resource "keycloak_ldap_user_federation" "openldap_one" {
+	name                    = "openldap"
+	realm_id                = "${keycloak_realm.realm_one.id}"
+	enabled                 = true
+	username_ldap_attribute = "cn"
+	rdn_ldap_attribute      = "cn"
+	uuid_ldap_attribute     = "entryDN"
+	user_object_classes     = [
+		"simpleSecurityObject",
+		"organizationalRole"
+	]
+	connection_url          = "ldap://openldap"
+	users_dn                = "dc=example,dc=org"
+	bind_dn                 = "cn=admin,dc=example,dc=org"
+	bind_credential         = "admin"
+}
+resource "keycloak_ldap_user_federation" "openldap_two" {
+	name                    = "openldap"
+	realm_id                = "${keycloak_realm.realm_two.id}"
+	enabled                 = true
+	username_ldap_attribute = "cn"
+	rdn_ldap_attribute      = "cn"
+	uuid_ldap_attribute     = "entryDN"
+	user_object_classes     = [
+		"simpleSecurityObject",
+		"organizationalRole"
+	]
+	connection_url          = "ldap://openldap"
+	users_dn                = "dc=example,dc=org"
+	bind_dn                 = "cn=admin,dc=example,dc=org"
+	bind_credential         = "admin"
+}
+resource "keycloak_ldap_msad_lds_user_account_control_mapper" "uac_mapper" {
+	name                               = "%s"
+	realm_id                           = "${keycloak_realm.realm_one.id}"
+	ldap_user_federation_id            = "${keycloak_ldap_user_federation.openldap_one.id}"
+}
+	`, realmOne, realmTwo, msadLdsUacMapperName)
+}
+
+func testKeycloakLdapMsadLdsUserAccountControlMapper_updateLdapUserFederationAfter(realmOne, realmTwo, msadLdsUacMapperName string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm_one" {
+	realm = "%s"
+}
+resource "keycloak_realm" "realm_two" {
+	realm = "%s"
+}
+resource "keycloak_ldap_user_federation" "openldap_one" {
+	name                    = "openldap"
+	realm_id                = "${keycloak_realm.realm_one.id}"
+	enabled                 = true
+	username_ldap_attribute = "cn"
+	rdn_ldap_attribute      = "cn"
+	uuid_ldap_attribute     = "entryDN"
+	user_object_classes     = [
+		"simpleSecurityObject",
+		"organizationalRole"
+	]
+	connection_url          = "ldap://openldap"
+	users_dn                = "dc=example,dc=org"
+	bind_dn                 = "cn=admin,dc=example,dc=org"
+	bind_credential         = "admin"
+}
+resource "keycloak_ldap_user_federation" "openldap_two" {
+	name                    = "openldap"
+	realm_id                = "${keycloak_realm.realm_two.id}"
+	enabled                 = true
+	username_ldap_attribute = "cn"
+	rdn_ldap_attribute      = "cn"
+	uuid_ldap_attribute     = "entryDN"
+	user_object_classes     = [
+		"simpleSecurityObject",
+		"organizationalRole"
+	]
+	connection_url          = "ldap://openldap"
+	users_dn                = "dc=example,dc=org"
+	bind_dn                 = "cn=admin,dc=example,dc=org"
+	bind_credential         = "admin"
+}
+resource "keycloak_ldap_msad_lds_user_account_control_mapper" "uac_mapper" {
+	name                               = "%s"
+	realm_id                           = "${keycloak_realm.realm_two.id}"
+	ldap_user_federation_id            = "${keycloak_ldap_user_federation.openldap_two.id}"
+}
+	`, realmOne, realmTwo, msadLdsUacMapperName)
+}
diff --git a/provider/resource_keycloak_oidc_google_identity_provider_test.go b/provider/resource_keycloak_oidc_google_identity_provider_test.go
new file mode 100644
index 0000000..0d8fcf4
--- /dev/null
+++ b/provider/resource_keycloak_oidc_google_identity_provider_test.go
@@ -0,0 +1,278 @@
+package provider
+
+import (
+	"fmt"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+	"testing"
+)
+
+func TestAccKeycloakOidcGoogleIdentityProvider_basic(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakOidcGoogleIdentityProviderDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_basic(realmName),
+				Check:  testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google"),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakOidcGoogleIdentityProvider_custom(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	customConfigValue := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakOidcGoogleIdentityProviderDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_custom(realmName, customConfigValue),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google_custom"),
+					testAccCheckKeycloakOidcGoogleIdentityProviderHasCustomConfigValue("keycloak_oidc_google_identity_provider.google_custom", customConfigValue),
+				),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakOidcGoogleIdentityProvider_createAfterManualDestroy(t *testing.T) {
+	var idp = &keycloak.IdentityProvider{}
+
+	realmName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakOidcGoogleIdentityProviderDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_basic(realmName),
+				Check:  testAccCheckKeycloakOidcGoogleIdentityProviderFetch("keycloak_oidc_google_identity_provider.google", idp),
+			},
+			{
+				PreConfig: func() {
+					keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+					err := keycloakClient.DeleteIdentityProvider(idp.Realm, idp.Alias)
+					if err != nil {
+						t.Fatal(err)
+					}
+				},
+				Config: testKeycloakOidcGoogleIdentityProvider_basic(realmName),
+				Check:  testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google"),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakOidcGoogleIdentityProvider_basicUpdateRealm(t *testing.T) {
+	firstRealm := "terraform-" + acctest.RandString(10)
+	secondRealm := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakOidcGoogleIdentityProviderDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_basic(firstRealm),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google"),
+					resource.TestCheckResourceAttr("keycloak_oidc_google_identity_provider.google", "realm", firstRealm),
+				),
+			},
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_basic(secondRealm),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google"),
+					resource.TestCheckResourceAttr("keycloak_oidc_google_identity_provider.google", "realm", secondRealm),
+				),
+			},
+		},
+	})
+}
+
+func TestAccKeycloakOidcGoogleIdentityProvider_basicUpdateAll(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	firstEnabled := randomBool()
+
+	firstOidc := &keycloak.IdentityProvider{
+		Realm:   realmName,
+		Alias:   acctest.RandString(10),
+		Enabled: firstEnabled,
+		Config: &keycloak.IdentityProviderConfig{
+			HostedDomain:                "mycompany.com",
+			AcceptsPromptNoneForwFrmClt: false,
+			ClientId:                    acctest.RandString(10),
+			ClientSecret:                acctest.RandString(10),
+		},
+	}
+
+	secondOidc := &keycloak.IdentityProvider{
+		Realm:   realmName,
+		Alias:   acctest.RandString(10),
+		Enabled: !firstEnabled,
+		Config: &keycloak.IdentityProviderConfig{
+			HostedDomain:                "mycompany.com",
+			AcceptsPromptNoneForwFrmClt: false,
+			ClientId:                    acctest.RandString(10),
+			ClientSecret:                acctest.RandString(10),
+		},
+	}
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakOidcGoogleIdentityProviderDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_basicFromInterface(firstOidc),
+				Check:  testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google"),
+			},
+			{
+				Config: testKeycloakOidcGoogleIdentityProvider_basicFromInterface(secondOidc),
+				Check:  testAccCheckKeycloakOidcGoogleIdentityProviderExists("keycloak_oidc_google_identity_provider.google"),
+			},
+		},
+	})
+}
+
+func testAccCheckKeycloakOidcGoogleIdentityProviderExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getKeycloakOidcGoogleIdentityProviderFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testAccCheckKeycloakOidcGoogleIdentityProviderFetch(resourceName string, idp *keycloak.IdentityProvider) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		fetchedOidc, err := getKeycloakOidcGoogleIdentityProviderFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		idp.Alias = fetchedOidc.Alias
+		idp.Realm = fetchedOidc.Realm
+
+		return nil
+	}
+}
+
+func testAccCheckKeycloakOidcGoogleIdentityProviderHasCustomConfigValue(resourceName, customConfigValue string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		fetchedOidc, err := getKeycloakOidcGoogleIdentityProviderFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		if fetchedOidc.Config.ExtraConfig["dummyConfig"].(string) != customConfigValue {
+			return fmt.Errorf("expected custom oidc provider to have config with a custom key 'dummyConfig' with a value %s, but value was %s", customConfigValue, fetchedOidc.Config.ExtraConfig["dummyConfig"].(string))
+		}
+
+		return nil
+	}
+}
+
+func testAccCheckKeycloakOidcGoogleIdentityProviderDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_oidc_google_identity_provider" {
+				continue
+			}
+
+			id := rs.Primary.ID
+			realm := rs.Primary.Attributes["realm"]
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			idp, _ := keycloakClient.GetIdentityProvider(realm, id)
+			if idp != nil {
+				return fmt.Errorf("oidc config with id %s still exists", id)
+			}
+		}
+
+		return nil
+	}
+}
+
+func getKeycloakOidcGoogleIdentityProviderFromState(s *terraform.State, resourceName string) (*keycloak.IdentityProvider, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm"]
+	alias := rs.Primary.Attributes["alias"]
+
+	idp, err := keycloakClient.GetIdentityProvider(realm, alias)
+	if err != nil {
+		return nil, fmt.Errorf("error getting oidc identity provider config with alias %s: %s", alias, err)
+	}
+
+	return idp, nil
+}
+
+func testKeycloakOidcGoogleIdentityProvider_basic(realm string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_oidc_google_identity_provider" "google" {
+	realm             = "${keycloak_realm.realm.id}"
+	client_id         = "example_id"
+	client_secret     = "example_token"
+}
+	`, realm)
+}
+
+func testKeycloakOidcGoogleIdentityProvider_custom(realm, customConfigValue string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_oidc_google_identity_provider" "google_custom" {
+	realm             = "${keycloak_realm.realm.id}"
+	provider_id       = "customGoogleIdp"
+	client_id         = "example_id"
+	client_secret     = "example_token"
+	extra_config      = {
+		dummyConfig = "%s"
+	}
+}
+	`, realm, customConfigValue)
+}
+
+func testKeycloakOidcGoogleIdentityProvider_basicFromInterface(idp *keycloak.IdentityProvider) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_oidc_google_identity_provider" "google" {
+	realm             						= "${keycloak_realm.realm.id}"
+	enabled           						= %t
+	hosted_domain	  						= "%s"
+	accepts_prompt_none_forward_from_client	= %t
+	client_id         						= "%s"
+	client_secret     						= "%s"
+}
+	`, idp.Realm, idp.Enabled, idp.Config.HostedDomain, idp.Config.AcceptsPromptNoneForwFrmClt, idp.Config.ClientId, idp.Config.ClientSecret)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_aggregate_policy_test.go b/provider/resource_keycloak_openid_client_authorization_aggregate_policy_test.go
new file mode 100644
index 0000000..9e26331
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_aggregate_policy_test.go
@@ -0,0 +1,127 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationAggregatePolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationAggregatePolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationAggregatePolicy_basic(realmName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationAggregatePolicyExists("keycloak_openid_client_aggregate_policy.test"),
+			},
+		},
+	})
+}
+
+func getResourceKeycloakOpenidClientAuthorizationAggregatePolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationAggregatePolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationAggregatePolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth aggregate policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationAggregatePolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_aggregate_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationAggregatePolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationAggregatePolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationAggregatePolicyFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationAggregatePolicy_basic(realm, clientId string) string {
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+
+	resource "keycloak_role" "test" {
+    realm_id    = "${keycloak_realm.test.id}"
+    name        = "aggregate_policy_role"
+	}
+
+	resource keycloak_openid_client_role_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "keycloak_openid_client_role_policy"
+		decision_strategy = "UNANIMOUS"
+		logic = "POSITIVE"
+		type = "role"
+		role  {
+			id = "${keycloak_role.test.id}" 
+			required = false
+		}
+	}
+	
+	resource keycloak_openid_client_aggregate_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "keycloak_openid_client_aggregate_policy"
+		decision_strategy = "UNANIMOUS"
+		logic = "POSITIVE"
+		policies = ["${keycloak_openid_client_role_policy.test.id}"]
+	}
+	`, realm, clientId)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_client_policy_test.go b/provider/resource_keycloak_openid_client_authorization_client_policy_test.go
new file mode 100644
index 0000000..c7cb31c
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_client_policy_test.go
@@ -0,0 +1,112 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationClientPolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+	roleName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationClientPolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationClientPolicy_basic(realmName, roleName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationClientPolicyExists("keycloak_openid_client_client_policy.test"),
+			},
+		},
+	})
+}
+
+func getResourceKeycloakOpenidClientAuthorizationClientPolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationClientPolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationClientPolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth role policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationClientPolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_client_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm_id"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationClientPolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationClientPolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationClientPolicyFromState(s, resourceName)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationClientPolicy_basic(realm, roleName, clientId string) string {
+
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+	
+	resource keycloak_openid_client_client_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "keycloak_openid_client_client_policy"
+		decision_strategy = "AFFIRMATIVE"
+		logic = "POSITIVE"
+		clients = ["${keycloak_openid_client.test.resource_server_id}"]
+	}
+	`, realm, clientId)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_group_policy_test.go b/provider/resource_keycloak_openid_client_authorization_group_policy_test.go
new file mode 100644
index 0000000..05ac43b
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_group_policy_test.go
@@ -0,0 +1,119 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationGroupPolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationGroupPolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationGroupPolicy_basic(realmName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationGroupPolicyExists("keycloak_openid_client_group_policy.test"),
+			},
+		},
+	})
+}
+
+func getResourceKeycloakOpenidClientAuthorizationGroupPolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationGroupPolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationGroupPolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth role policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationGroupPolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_group_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm_id"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationGroupPolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationGroupPolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationGroupPolicyFromState(s, resourceName)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationGroupPolicy_basic(realm, clientId string) string {
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+
+	resource "keycloak_group" "test" {
+		realm_id = "${keycloak_realm.test.id}"
+		name     = "foo"
+	}
+
+	resource keycloak_openid_client_group_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "client_group_policy_test"
+		groups {
+			id = "${keycloak_group.test.id}"
+			path = "${keycloak_group.test.path}"
+			extend_children = false
+		}
+		logic = "POSITIVE"
+		decision_strategy = "UNANIMOUS"
+	}
+	`, realm, clientId)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_js_policy_test.go b/provider/resource_keycloak_openid_client_authorization_js_policy_test.go
new file mode 100644
index 0000000..664891a
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_js_policy_test.go
@@ -0,0 +1,111 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationJSPolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationJSPolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationJSPolicy_basic(realmName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationJSPolicyExists("keycloak_openid_client_js_policy.test"),
+			},
+		},
+	})
+}
+
+func getResourceKeycloakOpenidClientAuthorizationJSPolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationJSPolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationJSPolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth role policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationJSPolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_js_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm_id"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationJSPolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationJSPolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationJSPolicyFromState(s, resourceName)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationJSPolicy_basic(realm, clientId string) string {
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+
+	resource keycloak_openid_client_js_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "client_js_policy_test"
+		logic = "POSITIVE"
+		decision_strategy = "UNANIMOUS"
+		code = "test"
+		description = "description"
+	}
+	`, realm, clientId)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_role_policy_test.go b/provider/resource_keycloak_openid_client_authorization_role_policy_test.go
new file mode 100644
index 0000000..9a73af6
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_role_policy_test.go
@@ -0,0 +1,121 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationRolePolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+	roleName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationRolePolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationRolePolicy_basic(realmName, roleName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationRolePolicyExists("keycloak_openid_client_role_policy.test"),
+			},
+		},
+	})
+}
+
+func testResourceKeycloakOpenidClientAuthorizationRolePolicy_basic(realm, roleName, clientId string) string {
+
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+	
+	resource "keycloak_role" "test" {
+    realm_id    = "${keycloak_realm.test.id}"
+    name        = "%s"
+	}
+
+	resource keycloak_openid_client_role_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "keycloak_openid_client_role_policy"
+		decision_strategy = "AFFIRMATIVE"
+		logic = "POSITIVE"
+		type = "role"
+		role  {
+			id = "${keycloak_role.test.id}" 
+			required = false
+		}
+	}
+	`, realm, roleName, clientId)
+}
+
+func getResourceKeycloakOpenidClientAuthorizationRolePolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationRolePolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationRolePolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth role policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationRolePolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_role_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm_id"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationRolePolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationRolePolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationRolePolicyFromState(s, resourceName)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_time_policy_test.go b/provider/resource_keycloak_openid_client_authorization_time_policy_test.go
new file mode 100644
index 0000000..fb27b52
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_time_policy_test.go
@@ -0,0 +1,123 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationTimePolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+	policyName := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationTimePolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationTimePolicy_basic(realmName, policyName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationTimePolicyExists("keycloak_openid_client_time_policy.test"),
+			},
+		},
+	})
+}
+
+func getResourceKeycloakOpenidClientAuthorizationTimePolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationTimePolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationTimePolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth role policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationTimePolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_time_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm_id"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationTimePolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationTimePolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationTimePolicyFromState(s, resourceName)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationTimePolicy_basic(realm, policyName, clientId string) string {
+
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+
+	resource keycloak_openid_client_time_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "%s"
+		not_on_or_after = "2500-12-12 01:01:11"
+		not_before = "2400-12-12 01:01:11"
+		day_month = "1"
+		day_month_end = "2"
+		year = "2500"
+		year_end = "2501"
+		month = "1"
+		month_end = "5"
+		hour = "1"
+		hour_end = "5"
+		minute = "10"
+		minute_end = "30"
+		logic = "POSITIVE"
+		decision_strategy = "UNANIMOUS"
+	}
+	`, realm, clientId, policyName)
+}
diff --git a/provider/resource_keycloak_openid_client_authorization_user_policy_test.go b/provider/resource_keycloak_openid_client_authorization_user_policy_test.go
new file mode 100644
index 0000000..6e75f6c
--- /dev/null
+++ b/provider/resource_keycloak_openid_client_authorization_user_policy_test.go
@@ -0,0 +1,119 @@
+package provider
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
+	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/terraform"
+	"github.com/mrparkers/terraform-provider-keycloak/keycloak"
+)
+
+func TestResourceKeycloakOpenidClientAuthorizationUserPolicy(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testResourceKeycloakOpenidClientAuthorizationUserPolicyDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testResourceKeycloakOpenidClientAuthorizationUserPolicy_basic(realmName, clientId),
+				Check:  testResourceKeycloakOpenidClientAuthorizationUserPolicyExists("keycloak_openid_client_user_policy.test"),
+			},
+		},
+	})
+}
+
+func getResourceKeycloakOpenidClientAuthorizationUserPolicyFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientAuthorizationUserPolicy, error) {
+	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+	rs, ok := s.RootModule().Resources[resourceName]
+	if !ok {
+		return nil, fmt.Errorf("resource not found: %s", resourceName)
+	}
+
+	realm := rs.Primary.Attributes["realm_id"]
+	resourceServerId := rs.Primary.Attributes["resource_server_id"]
+	policyId := rs.Primary.ID
+
+	policy, err := keycloakClient.GetOpenidClientAuthorizationUserPolicy(realm, resourceServerId, policyId)
+	if err != nil {
+		return nil, fmt.Errorf("error getting openid client auth role policy config with alias %s: %s", resourceServerId, err)
+	}
+
+	return policy, nil
+}
+
+func testResourceKeycloakOpenidClientAuthorizationUserPolicyDestroy() resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		for _, rs := range s.RootModule().Resources {
+			if rs.Type != "keycloak_openid_client_user_policy" {
+				continue
+			}
+
+			realm := rs.Primary.Attributes["realm_id"]
+			resourceServerId := rs.Primary.Attributes["resource_server_id"]
+			policyId := rs.Primary.ID
+
+			keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+			policy, _ := keycloakClient.GetOpenidClientAuthorizationUserPolicy(realm, resourceServerId, policyId)
+			if policy != nil {
+				return fmt.Errorf("policy config with id %s still exists", policyId)
+			}
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationUserPolicyExists(resourceName string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		_, err := getResourceKeycloakOpenidClientAuthorizationUserPolicyFromState(s, resourceName)
+
+		if err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func testResourceKeycloakOpenidClientAuthorizationUserPolicy_basic(realm, clientId string) string {
+	return fmt.Sprintf(`
+	resource keycloak_realm test {
+		realm = "%s"
+	}
+	
+	resource keycloak_openid_client test {
+		client_id                = "%s"
+		realm_id                 = "${keycloak_realm.test.id}"
+		access_type              = "CONFIDENTIAL"
+		service_accounts_enabled = true
+		authorization {
+			policy_enforcement_mode = "ENFORCING"
+		}
+	}
+
+	resource keycloak_user test {
+		realm_id = "${keycloak_realm.test.id}"
+		username = "test-user"
+	
+		email      = "test-user@fakedomain.com"
+		first_name = "Testy"
+		last_name  = "Tester"
+	}
+
+	resource keycloak_openid_client_user_policy test {
+		resource_server_id = "${keycloak_openid_client.test.resource_server_id}"
+		realm_id = "${keycloak_realm.test.id}"
+		name = "client_user_policy_test"
+		users = ["${keycloak_user.test.id}"]
+		logic = "POSITIVE"
+		decision_strategy = "UNANIMOUS"
+	}
+	`, realm, clientId)
+}