Repository: mrparkers/terraform-provider-keycloak (go)

Issue:
Openid Client is missing the Advanced section
The resource keycloak_openid_client is missing the Advanced Settings, which are needed to set Access Token Lifespan per client. 

Did i oversaw something or is this missing? 

Pull request:
Add access token lifespan to keycloak oidc client
This pull request fixes #232 

Patch:
diff --git a/docs/resources/keycloak_openid_client.md b/docs/resources/keycloak_openid_client.md
index ae8c9fb..c23f8a3 100644
--- a/docs/resources/keycloak_openid_client.md
+++ b/docs/resources/keycloak_openid_client.md
@@ -57,6 +57,7 @@ is set to `true`.
 - `base_url` - (Optional) Default URL to use when the auth server needs to redirect or link back to the client.
 - `pkce_code_challenge_method` - (Optional) The challenge method to use for Proof Key for Code Exchange. Can be either `plain` or `S256` or set to empty value ``.
 - `full_scope_allowed` - (Optional) - Allow to include all roles mappings in the access token.
+- `access_token_lifespan` - (Optional) - Allow to set the lifespan of the access token
 
 ### Attributes Reference
 
diff --git a/keycloak/openid_client.go b/keycloak/openid_client.go
index 0f64348..dc5ad69 100644
--- a/keycloak/openid_client.go
+++ b/keycloak/openid_client.go
@@ -54,6 +54,7 @@ type OpenidClient struct {
 type OpenidClientAttributes struct {
 	PkceCodeChallengeMethod             string             `json:"pkce.code.challenge.method"`
 	ExcludeSessionStateFromAuthResponse KeycloakBoolQuoted `json:"exclude.session.state.from.auth.response"`
+	AccessTokenLifespan                 string             `json:"access.token.lifespan"`
 }
 
 func (keycloakClient *KeycloakClient) GetOpenidClientServiceAccountUserId(realmId, clientId string) (*User, error) {
diff --git a/provider/resource_keycloak_openid_client.go b/provider/resource_keycloak_openid_client.go
index 48c078a..5608eb8 100644
--- a/provider/resource_keycloak_openid_client.go
+++ b/provider/resource_keycloak_openid_client.go
@@ -104,6 +104,10 @@ func resourceKeycloakOpenidClient() *schema.Resource {
 				Optional:     true,
 				ValidateFunc: validation.StringInSlice(keycloakOpenidClientPkceCodeChallengeMethod, false),
 			},
+			"access_token_lifespan": {
+				Type:     schema.TypeString,
+				Optional: true,
+			},
 			"exclude_session_state_from_auth_response": {
 				Type:     schema.TypeBool,
 				Optional: true,
@@ -187,6 +191,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient,
 		Attributes: keycloak.OpenidClientAttributes{
 			PkceCodeChallengeMethod:             data.Get("pkce_code_challenge_method").(string),
 			ExcludeSessionStateFromAuthResponse: keycloak.KeycloakBoolQuoted(data.Get("exclude_session_state_from_auth_response").(bool)),
+			AccessTokenLifespan:                 data.Get("access_token_lifespan").(string),
 		},
 		ValidRedirectUris: validRedirectUris,
 		WebOrigins:        webOrigins,
@@ -256,6 +261,7 @@ func setOpenidClientData(keycloakClient *keycloak.KeycloakClient, data *schema.R
 	data.Set("authorization_services_enabled", client.AuthorizationServicesEnabled)
 	data.Set("full_scope_allowed", client.FullScopeAllowed)
 	data.Set("consent_required", client.ConsentRequired)
+	data.Set("access_token_lifespan", client.Attributes.AccessTokenLifespan)
 
 	if client.AuthorizationServicesEnabled {
 		data.Set("resource_server_id", client.Id)


Test patch:
diff --git a/provider/resource_keycloak_openid_client_test.go b/provider/resource_keycloak_openid_client_test.go
index a882c4d..b2cc026 100644
--- a/provider/resource_keycloak_openid_client_test.go
+++ b/provider/resource_keycloak_openid_client_test.go
@@ -232,6 +232,32 @@ func TestAccKeycloakOpenidClient_updateInPlace(t *testing.T) {
 	})
 }
 
+func TestAccKeycloakOpenidClient_AccessToken_basic(t *testing.T) {
+	realmName := "terraform-" + acctest.RandString(10)
+	clientId := "terraform-" + acctest.RandString(10)
+
+	accessTokenLifespan := "1800"
+
+	resource.Test(t, resource.TestCase{
+		Providers:    testAccProviders,
+		PreCheck:     func() { testAccPreCheck(t) },
+		CheckDestroy: testAccCheckKeycloakOpenidClientDestroy(),
+		Steps: []resource.TestStep{
+			{
+				Config: testKeycloakOpenidClient_AccessToken_basic(realmName, clientId, accessTokenLifespan),
+				Check:  testAccCheckKeycloakOpenidClientExistsWithCorrectLifespan("keycloak_openid_client.client", accessTokenLifespan),
+			},
+			{
+				ResourceName:            "keycloak_openid_client.client",
+				ImportState:             true,
+				ImportStateVerify:       true,
+				ImportStateIdPrefix:     realmName + "/",
+				ImportStateVerifyIgnore: []string{"exclude_session_state_from_auth_response"},
+			},
+		},
+	})
+}
+
 func testAccCheckKeycloakOpenidClientAdminUrl(resourceName string, adminUrl string) resource.TestCheckFunc {
 	return func(s *terraform.State) error {
 		client, err := getOpenidClientFromState(s, resourceName)
@@ -444,6 +470,21 @@ func testAccCheckKeycloakOpenidClientExistsWithCorrectProtocol(resourceName stri
 	}
 }
 
+func testAccCheckKeycloakOpenidClientExistsWithCorrectLifespan(resourceName string, accessTokenLifespan string) resource.TestCheckFunc {
+	return func(s *terraform.State) error {
+		client, err := getOpenidClientFromState(s, resourceName)
+		if err != nil {
+			return err
+		}
+
+		if client.Attributes.AccessTokenLifespan != accessTokenLifespan {
+			return fmt.Errorf("expected openid client to have access token lifespan set to %s, but got %s", accessTokenLifespan, client.Attributes.AccessTokenLifespan)
+		}
+
+		return nil
+	}
+}
+
 func testAccCheckKeycloakOpenidClientFetch(resourceName string, client *keycloak.OpenidClient) resource.TestCheckFunc {
 	return func(s *terraform.State) error {
 		fetchedClient, err := getOpenidClientFromState(s, resourceName)
@@ -622,6 +663,21 @@ resource "keycloak_openid_client" "client" {
 	`, realm, clientId)
 }
 
+func testKeycloakOpenidClient_AccessToken_basic(realm, clientId, accessTokenLifespan string) string {
+	return fmt.Sprintf(`
+resource "keycloak_realm" "realm" {
+	realm = "%s"
+}
+
+resource "keycloak_openid_client" "client" {
+	client_id   		  = "%s"
+	realm_id    		  = "${keycloak_realm.realm.id}"
+	access_type 		  = "CONFIDENTIAL"
+	access_token_lifespan = "%s"
+}
+	`, realm, clientId, accessTokenLifespan)
+}
+
 func testKeycloakOpenidClient_accessType(realm, clientId, accessType string) string {
 	return fmt.Sprintf(`
 resource "keycloak_realm" "realm" {