Repository: mrparkers/terraform-provider-keycloak
Pull request #256 (2020-03-19 18:15:08)

Allow changing the email verification state
Add the email_verified flag for users.

languitar: Now also with correct formatting ;-)

Patch:
diff --git a/docs/resources/keycloak_user.md b/docs/resources/keycloak_user.md
index 03de8b1..2c37622 100644
--- a/docs/resources/keycloak_user.md
+++ b/docs/resources/keycloak_user.md
@@ -18,7 +18,7 @@ resource "keycloak_user" "user" {
     realm_id   = "${keycloak_realm.realm.id}"
     username   = "bob"
     enabled    = true
-    
+
     email      = "bob@domain.com"
     first_name = "Bob"
     last_name  = "Bobson"
@@ -28,7 +28,7 @@ resource "keycloak_user" "user_with_initial_password" {
     realm_id   = "${keycloak_realm.realm.id}"
     username   = "alice"
     enabled    = true
-    
+
     email      = "alice@domain.com"
     first_name = "Alice"
     last_name  = "Aliceberg"
@@ -52,6 +52,7 @@ The following arguments are supported:
     - `temporary` (Optional) If set to `true`, the initial password is set up for renewal on first use. Default to `false`.
 - `enabled` - (Optional) When false, this user cannot log in. Defaults to `true`.
 - `email` - (Optional) The user's email.
+- `email_verified` - (Optional) Whether the email address was validated or not. Default to `false`.
 - `first_name` - (Optional) The user's first name.
 - `last_name` - (Optional) The user's last name.
 
diff --git a/example/roles.tf b/example/roles.tf
index 1056194..da22957 100644
--- a/example/roles.tf
+++ b/example/roles.tf
@@ -15,6 +15,13 @@ resource "keycloak_openid_client" "pet_api" {
   access_type = "BEARER-ONLY"
 }
 
+// Optional client scope for mapping additional client role
+resource "keycloak_openid_client_scope" "extended_pet_details" {
+  realm_id  = "${keycloak_realm.roles_example.id}"
+  name      = "extended-pet-details"
+  description = "Optional scope offering additional information when getting pets"
+}
+
 resource "keycloak_role" "pet_api_create_pet" {
   name        = "create-pet"
   realm_id    = "${keycloak_realm.roles_example.id}"
@@ -43,6 +50,20 @@ resource "keycloak_role" "pet_api_delete_pet" {
   description = "Ability to delete a pet"
 }
 
+resource "keycloak_role" "pet_api_read_pet_details" {
+  name        = "read-pet-with-details"
+  realm_id    = "${keycloak_realm.roles_example.id}"
+  client_id   = "${keycloak_openid_client.pet_api.id}"
+  description = "Ability to read / list pets with further details"
+}
+
+// Map a role from the "pet_api" api client to the "extended_pet_details" client scope
+resource "keycloak_generic_client_role_mapper" "pet_api_read_pet_details_role_mapping" {
+  realm_id  = "${keycloak_realm.roles_example.id}"
+  client_scope_id = "${keycloak_openid_client_scope.extended_pet_details.id}"
+  role_id   = "${keycloak_role.pet_api_read_pet_details.id}"
+}
+
 resource "keycloak_role" "pet_api_admin" {
   name      = "admin"
   realm_id  = "${keycloak_realm.roles_example.id}"
@@ -76,6 +97,18 @@ resource "keycloak_openid_client" "pet_app" {
   valid_redirect_uris = [
     "http://localhost:5555/openid-callback",
   ]
+
+  // disable full scope, roles are assigned via keycloak_generic_client_role_mapper
+  full_scope_allowed = false
+}
+
+resource "keycloak_openid_client_optional_scopes" "pet_app_optional_scopes" {
+  realm_id       = "${keycloak_realm.roles_example.id}"
+  client_id      = "${keycloak_openid_client.pet_app.id}"
+
+  optional_scopes = [
+    "${keycloak_openid_client_scope.extended_pet_details.name}"
+  ]
 }
 
 // The app will always need access to the API, so this audience should be used regardless of auth type
@@ -96,13 +129,37 @@ resource "keycloak_openid_hardcoded_role_protocol_mapper" "pet_app_pet_api_read_
   role_id = "${keycloak_role.pet_api_read_pet.id}"
 }
 
-// Map a role from the "pet_api" api client to the "pet_app" consumer client
+// Map all roles from the "pet_api" api client to the "pet_app" consumer client, read_pet_details comes via client scope
 resource "keycloak_generic_client_role_mapper" "pet_app_pet_api_read_role_mapping" {
   realm_id  = "${keycloak_realm.roles_example.id}"
   client_id = "${keycloak_openid_client.pet_app.id}"
   role_id   = "${keycloak_role.pet_api_read_pet.id}"
 }
 
+resource "keycloak_generic_client_role_mapper" "pet_app_pet_api_delete_role_mapping" {
+  realm_id  = "${keycloak_realm.roles_example.id}"
+  client_id = "${keycloak_openid_client.pet_app.id}"
+  role_id   = "${keycloak_role.pet_api_delete_pet.id}"
+}
+
+resource "keycloak_generic_client_role_mapper" "pet_app_pet_api_create_role_mapping" {
+  realm_id  = "${keycloak_realm.roles_example.id}"
+  client_id = "${keycloak_openid_client.pet_app.id}"
+  role_id   = "${keycloak_role.pet_api_create_pet.id}"
+}
+
+resource "keycloak_generic_client_role_mapper" "pet_app_pet_api_update_role_mapping" {
+  realm_id  = "${keycloak_realm.roles_example.id}"
+  client_id = "${keycloak_openid_client.pet_app.id}"
+  role_id   = "${keycloak_role.pet_api_update_pet.id}"
+}
+
+resource "keycloak_generic_client_role_mapper" "pet_app_pet_api_admin_role_mapping" {
+  realm_id  = "${keycloak_realm.roles_example.id}"
+  client_id = "${keycloak_openid_client.pet_app.id}"
+  role_id   = "${keycloak_role.pet_api_admin.id}"
+}
+
 // Users and groups
 
 resource "keycloak_group" "pet_api_base" {
@@ -133,6 +190,7 @@ resource "keycloak_group_roles" "admin_roles" {
 
   role_ids = [
     "${keycloak_role.pet_api_read_pet.id}",
+    "${keycloak_role.pet_api_read_pet_details.id}",
     "${keycloak_role.pet_api_delete_pet.id}",
     "${keycloak_role.pet_api_create_pet.id}",
     "${data.keycloak_role.realm_offline_access.id}",
@@ -145,6 +203,7 @@ resource "keycloak_group_roles" "front_desk_roles" {
 
   role_ids = [
     "${keycloak_role.pet_api_read_pet.id}",
+    "${keycloak_role.pet_api_read_pet_details.id}",
     "${keycloak_role.pet_api_create_pet.id}",
     "${data.keycloak_role.realm_offline_access.id}",
   ]
diff --git a/keycloak/role_scope_mapping.go b/keycloak/role_scope_mapping.go
index 5cfdffa..4aabd4f 100644
--- a/keycloak/role_scope_mapping.go
+++ b/keycloak/role_scope_mapping.go
@@ -4,12 +4,16 @@ import (
 	"fmt"
 )
 
-func roleScopeMappingUrl(realmId, clientId string, role *Role) string {
-	return fmt.Sprintf("/realms/%s/clients/%s/scope-mappings/clients/%s", realmId, clientId, role.ClientId)
+func roleScopeMappingUrl(realmId, clientId string, clientScopeId string, role *Role) string {
+	if clientId != "" {
+		return fmt.Sprintf("/realms/%s/clients/%s/scope-mappings/clients/%s", realmId, clientId, role.ClientId)
+	} else {
+		return fmt.Sprintf("/realms/%s/client-scopes/%s/scope-mappings/clients/%s", realmId, clientScopeId, role.ClientId)
+	}
 }
 
-func (keycloakClient *KeycloakClient) CreateRoleScopeMapping(realmId string, clientId string, role *Role) error {
-	roleUrl := roleScopeMappingUrl(realmId, clientId, role)
+func (keycloakClient *KeycloakClient) CreateRoleScopeMapping(realmId string, clientId string, clientScopeId string, role *Role) error {
+	roleUrl := roleScopeMappingUrl(realmId, clientId, clientScopeId, role)
 
 	_, _, err := keycloakClient.post(roleUrl, []Role{*role})
 	if err != nil {
@@ -19,8 +23,8 @@ func (keycloakClient *KeycloakClient) CreateRoleScopeMapping(realmId string, cli
 	return nil
 }
 
-func (keycloakClient *KeycloakClient) GetRoleScopeMapping(realmId string, clientId string, role *Role) (*Role, error) {
-	roleUrl := roleScopeMappingUrl(realmId, clientId, role)
+func (keycloakClient *KeycloakClient) GetRoleScopeMapping(realmId string, clientId string, clientScopeId string, role *Role) (*Role, error) {
+	roleUrl := roleScopeMappingUrl(realmId, clientId, clientScopeId, role)
 	var roles []Role
 
 	err := keycloakClient.get(roleUrl, &roles, nil)
@@ -37,7 +41,7 @@ func (keycloakClient *KeycloakClient) GetRoleScopeMapping(realmId string, client
 	return nil, nil
 }
 
-func (keycloakClient *KeycloakClient) DeleteRoleScopeMapping(realmId string, clientId string, role *Role) error {
-	roleUrl := roleScopeMappingUrl(realmId, clientId, role)
+func (keycloakClient *KeycloakClient) DeleteRoleScopeMapping(realmId string, clientId string, clientScopeId string, role *Role) error {
+	roleUrl := roleScopeMappingUrl(realmId, clientId, clientScopeId, role)
 	return keycloakClient.delete(roleUrl, nil)
 }
diff --git a/keycloak/user.go b/keycloak/user.go
index 6126a3b..bd28a7f 100644
--- a/keycloak/user.go
+++ b/keycloak/user.go
@@ -18,6 +18,7 @@ type User struct {
 
 	Username            string              `json:"username"`
 	Email               string              `json:"email"`
+	EmailVerified       bool                `json:"emailVerified"`
 	FirstName           string              `json:"firstName"`
 	LastName            string              `json:"lastName"`
 	Enabled             bool                `json:"enabled"`
diff --git a/provider/resource_keycloak_generic_client_role_mapper.go b/provider/resource_keycloak_generic_client_role_mapper.go
index f2e1043..9b39c87 100644
--- a/provider/resource_keycloak_generic_client_role_mapper.go
+++ b/provider/resource_keycloak_generic_client_role_mapper.go
@@ -15,19 +15,30 @@ func resourceKeycloakGenericClientRoleMapper() *schema.Resource {
 
 		Schema: map[string]*schema.Schema{
 			"realm_id": {
-				Type:     schema.TypeString,
-				Required: true,
-				ForceNew: true,
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: "The realm id where the associated client or client scope exists.",
 			},
 			"client_id": {
-				Type:     schema.TypeString,
-				Required: true,
-				ForceNew: true,
+				Type:          schema.TypeString,
+				Optional:      true,
+				ForceNew:      true,
+				Description:   "The destination client of the client role. Cannot be used at the same time as client_scope_id.",
+				ConflictsWith: []string{"client_scope_id"},
+			},
+			"client_scope_id": {
+				Type:          schema.TypeString,
+				Optional:      true,
+				ForceNew:      true,
+				Description:   "The destination client scope of the client role. Cannot be used at the same time as client_id.",
+				ConflictsWith: []string{"client_id"},
 			},
 			"role_id": {
-				Type:     schema.TypeString,
-				Required: true,
-				ForceNew: true,
+				Type:        schema.TypeString,
+				Required:    true,
+				ForceNew:    true,
+				Description: "Id of the role to assign",
 			},
 		},
 	}
@@ -38,6 +49,7 @@ func resourceKeycloakGenericClientRoleMapperCreate(data *schema.ResourceData, me
 
 	realmId := data.Get("realm_id").(string)
 	clientId := data.Get("client_id").(string)
+	clientScopeId := data.Get("client_scope_id").(string)
 	roleId := data.Get("role_id").(string)
 
 	role, err := keycloakClient.GetRole(realmId, roleId)
@@ -45,12 +57,16 @@ func resourceKeycloakGenericClientRoleMapperCreate(data *schema.ResourceData, me
 		return err
 	}
 
-	err = keycloakClient.CreateRoleScopeMapping(realmId, clientId, role)
+	err = keycloakClient.CreateRoleScopeMapping(realmId, clientId, clientScopeId, role)
 	if err != nil {
 		return err
 	}
 
-	data.SetId(fmt.Sprintf("%s/client/%s/scope-mappings/%s/%s", realmId, clientId, role.ClientId, role.Id))
+	if clientId != "" {
+		data.SetId(fmt.Sprintf("%s/client/%s/scope-mappings/%s/%s", realmId, clientId, role.ClientId, role.Id))
+	} else {
+		data.SetId(fmt.Sprintf("%s/client-scope/%s/scope-mappings/%s/%s", realmId, clientScopeId, role.ClientId, role.Id))
+	}
 
 	return resourceKeycloakGenericClientRoleMapperRead(data, meta)
 }
@@ -60,6 +76,7 @@ func resourceKeycloakGenericClientRoleMapperRead(data *schema.ResourceData, meta
 
 	realmId := data.Get("realm_id").(string)
 	clientId := data.Get("client_id").(string)
+	clientScopeId := data.Get("client_scope_id").(string)
 	roleId := data.Get("role_id").(string)
 
 	role, err := keycloakClient.GetRole(realmId, roleId)
@@ -67,7 +84,7 @@ func resourceKeycloakGenericClientRoleMapperRead(data *schema.ResourceData, meta
 		return err
 	}
 
-	mappedRole, err := keycloakClient.GetRoleScopeMapping(realmId, clientId, role)
+	mappedRole, err := keycloakClient.GetRoleScopeMapping(realmId, clientId, clientScopeId, role)
 
 	if mappedRole == nil {
 		data.SetId("")
@@ -81,6 +98,7 @@ func resourceKeycloakGenericClientRoleMapperDelete(data *schema.ResourceData, me
 
 	realmId := data.Get("realm_id").(string)
 	clientId := data.Get("client_id").(string)
+	clientScopeId := data.Get("client_scope_id").(string)
 	roleId := data.Get("role_id").(string)
 
 	role, err := keycloakClient.GetRole(realmId, roleId)
@@ -88,5 +106,5 @@ func resourceKeycloakGenericClientRoleMapperDelete(data *schema.ResourceData, me
 		return err
 	}
 
-	return keycloakClient.DeleteRoleScopeMapping(realmId, clientId, role)
+	return keycloakClient.DeleteRoleScopeMapping(realmId, clientId, clientScopeId, role)
 }
diff --git a/provider/resource_keycloak_user.go b/provider/resource_keycloak_user.go
index 9b06059..6c8d1da 100644
--- a/provider/resource_keycloak_user.go
+++ b/provider/resource_keycloak_user.go
@@ -43,6 +43,11 @@ func resourceKeycloakUser() *schema.Resource {
 				Type:     schema.TypeString,
 				Optional: true,
 			},
+			"email_verified": {
+				Type:     schema.TypeBool,
+				Optional: true,
+				Default:  false,
+			},
 			"first_name": {
 				Type:     schema.TypeString,
 				Optional: true,
@@ -127,6 +132,7 @@ func mapFromDataToUser(data *schema.ResourceData) *keycloak.User {
 		RealmId:             data.Get("realm_id").(string),
 		Username:            data.Get("username").(string),
 		Email:               data.Get("email").(string),
+		EmailVerified:       data.Get("email_verified").(bool),
 		FirstName:           data.Get("first_name").(string),
 		LastName:            data.Get("last_name").(string),
 		Enabled:             data.Get("enabled").(bool),
@@ -167,6 +173,7 @@ func mapFromUserToData(data *schema.ResourceData, user *keycloak.User) {
 	data.Set("realm_id", user.RealmId)
 	data.Set("username", user.Username)
 	data.Set("email", user.Email)
+	data.Set("email_verified", user.EmailVerified)
 	data.Set("first_name", user.FirstName)
 	data.Set("last_name", user.LastName)
 	data.Set("enabled", user.Enabled)


Test patch:
diff --git a/provider/resource_keycloak_generic_client_role_mapper_test.go b/provider/resource_keycloak_generic_client_role_mapper_test.go
index 5260f3a..7983f5c 100644
--- a/provider/resource_keycloak_generic_client_role_mapper_test.go
+++ b/provider/resource_keycloak_generic_client_role_mapper_test.go
@@ -27,6 +27,24 @@ func TestGenericRoleMapper_basic(t *testing.T) {
 	})
 }
 
+func TestGenericRoleMapperClientScope_basic(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientName := "client-" + acctest.RandString(10)
+	roleName := "role-" + acctest.RandString(10)
+	clientScopeName := "clientscope-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers: testAccProviders,
+		PreCheck:  func() { testAccPreCheck(t) },
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakGenericRoleMappingClientScope_basic(realmName, clientName, roleName, clientScopeName),
+				Check:  testAccCheckKeycloakScopeMappingExists("keycloak_generic_client_role_mapper.clientscope-with-client-role"),
+			},
+		},
+	})
+}
+
 func TestGenericRoleMapper_createAfterManualDestroy(t *testing.T) {
 	var role = &keycloak.Role{}
 	var childClient = &keycloak.GenericClient{}
@@ -52,7 +70,7 @@ func TestGenericRoleMapper_createAfterManualDestroy(t *testing.T) {
 				PreConfig: func() {
 					keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
 
-					err := keycloakClient.DeleteRoleScopeMapping(childClient.RealmId, childClient.Id, role)
+					err := keycloakClient.DeleteRoleScopeMapping(childClient.RealmId, childClient.Id, "", role)
 					if err != nil {
 						t.Fatal(err)
 					}
@@ -64,6 +82,43 @@ func TestGenericRoleMapper_createAfterManualDestroy(t *testing.T) {
 	})
 }
 
+func TestGenericRoleMapperClientScope_createAfterManualDestroy(t *testing.T) {
+	var role = &keycloak.Role{}
+	var clientScope = &keycloak.OpenidClientScope{}
+
+	realmName := "terraform-" + acctest.RandString(10)
+	clientName := "client-" + acctest.RandString(10)
+	roleName := "role-" + acctest.RandString(10)
+	clientScopeName := "clientscope-" + acctest.RandString(10)
+
+	resource.Test(t, resource.TestCase{
+		Providers: testAccProviders,
+		PreCheck:  func() { testAccPreCheck(t) },
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakGenericRoleMappingClientScope_basic(realmName, clientName, roleName, clientScopeName),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckKeycloakScopeMappingExists("keycloak_generic_client_role_mapper.clientscope-with-client-role"),
+					testAccCheckKeycloakRoleFetch("keycloak_role.role", role),
+					testAccCheckKeycloakOpenidClientScopeFetch("keycloak_openid_client_scope.clientscope", clientScope),
+				),
+			},
+			{
+				PreConfig: func() {
+					keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
+
+					err := keycloakClient.DeleteRoleScopeMapping(clientScope.RealmId, "", clientScope.Id, role)
+					if err != nil {
+						t.Fatal(err)
+					}
+				},
+				Config: testKeycloakGenericRoleMappingClientScope_basic(realmName, clientName, roleName, clientScopeName),
+				Check:  testAccCheckKeycloakScopeMappingExists("keycloak_generic_client_role_mapper.clientscope-with-client-role"),
+			},
+		},
+	})
+}
+
 func testKeycloakGenericRoleMapping_basic(realmName, parentClientName, parentRoleName, childClientName string) string {
 	return fmt.Sprintf(`
 resource "keycloak_realm" "realm" {
@@ -96,6 +151,37 @@ resource "keycloak_generic_client_role_mapper" "child-client-with-parent-client-
 	`, realmName, parentClientName, parentRoleName, childClientName)
 }
 
+func testKeycloakGenericRoleMappingClientScope_basic(realmName, clientName, roleName, clientScopeName string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_openid_client" "client" {
+	realm_id    = "${keycloak_realm.realm.id}"
+	client_id   = "%s"
+	access_type = "PUBLIC"
+}
+
+resource "keycloak_role" "role" {
+  realm_id  = "${keycloak_realm.realm.id}"
+  client_id = "${keycloak_openid_client.client.id}"
+  name      = "%s"
+}
+
+resource "keycloak_openid_client_scope" "clientscope" {
+	realm_id    = "${keycloak_realm.realm.id}"
+	name        = "%s"
+}
+
+resource "keycloak_generic_client_role_mapper" "clientscope-with-client-role" {
+  realm_id  = "${keycloak_realm.realm.id}"
+  client_scope_id = "${keycloak_openid_client_scope.clientscope.id}"
+  role_id   = "${keycloak_role.role.id}"
+}
+	`, realmName, clientName, roleName, clientScopeName)
+}
+
 func testAccCheckKeycloakScopeMappingExists(resourceName string) resource.TestCheckFunc {
 	return func(s *terraform.State) error {
 		_, ok := s.RootModule().Resources[resourceName]
@@ -122,6 +208,20 @@ func testAccCheckKeycloakGenericClientFetch(resourceName string, client *keycloa
 	}
 }
 
+func testAccCheckKeycloakOpenidClientScopeFetch(resourceName string, clientScope *keycloak.OpenidClientScope) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		fetchedClientScope, err := getOpenidClientScopeFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		clientScope.Id = fetchedClientScope.Id
+		clientScope.RealmId = fetchedClientScope.RealmId
+
+		return nil
+	}
+}
+
 func getGenericClientFromState(s *terraform.State, resourceName string) (*keycloak.GenericClient, error) {
 	keycloakClient := testAccProvider.Meta().(*keycloak.KeycloakClient)
 
@@ -140,3 +240,22 @@ func getGenericClientFromState(s *terraform.State, resourceName string) (*keyclo
 
 	return client, nil
 }
+
+func getOpenidClientScopeFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClientScope, 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"]
+
+	client, err := keycloakClient.GetOpenidClientScope(realm, id)
+	if err != nil {
+		return nil, fmt.Errorf("error getting client scope %s: %s", id, err)
+	}
+
+	return client, nil
+}
diff --git a/provider/resource_keycloak_user_test.go b/provider/resource_keycloak_user_test.go
index 9ad2a13..12137fb 100644
--- a/provider/resource_keycloak_user_test.go
+++ b/provider/resource_keycloak_user_test.go
@@ -195,21 +195,23 @@ func TestAccKeycloakUser_updateWithInitialPasswordChangeDoesNotReset(t *testing.
 
 func TestAccKeycloakUser_updateInPlace(t *testing.T) {
 	userOne := &keycloak.User{
-		RealmId:   "terraform-" + acctest.RandString(10),
-		Username:  "terraform-user-" + acctest.RandString(10),
-		Email:     fmt.Sprintf("%s@gmail.com", acctest.RandString(10)),
-		FirstName: acctest.RandString(10),
-		LastName:  acctest.RandString(10),
-		Enabled:   randomBool(),
+		RealmId:       "terraform-" + acctest.RandString(10),
+		Username:      "terraform-user-" + acctest.RandString(10),
+		Email:         fmt.Sprintf("%s@gmail.com", acctest.RandString(10)),
+		FirstName:     acctest.RandString(10),
+		LastName:      acctest.RandString(10),
+		Enabled:       randomBool(),
+		EmailVerified: randomBool(),
 	}
 
 	userTwo := &keycloak.User{
-		RealmId:   userOne.RealmId,
-		Username:  userOne.Username,
-		Email:     fmt.Sprintf("%s@gmail.com", acctest.RandString(10)),
-		FirstName: acctest.RandString(10),
-		LastName:  acctest.RandString(10),
-		Enabled:   randomBool(),
+		RealmId:       userOne.RealmId,
+		Username:      userOne.Username,
+		Email:         fmt.Sprintf("%s@gmail.com", acctest.RandString(10)),
+		FirstName:     acctest.RandString(10),
+		LastName:      acctest.RandString(10),
+		Enabled:       randomBool(),
+		EmailVerified: !userOne.EmailVerified,
 	}
 
 	resourceName := "keycloak_user.user"
@@ -475,13 +477,14 @@ resource "keycloak_realm" "realm" {
 }
 
 resource "keycloak_user" "user" {
-	realm_id   = "${keycloak_realm.realm.id}"
-	username   = "%s"
+	realm_id       = "${keycloak_realm.realm.id}"
+	username       = "%s"
 
-	email      = "%s"
-	first_name = "%s"
-	last_name  = "%s"
-	enabled    = %t
+	email          = "%s"
+	first_name     = "%s"
+	last_name      = "%s"
+	enabled        = %t
+	email_verified = "%t"
 }
-	`, user.RealmId, user.Username, user.Email, user.FirstName, user.LastName, user.Enabled)
+	`, user.RealmId, user.Username, user.Email, user.FirstName, user.LastName, user.Enabled, user.EmailVerified)
 }