Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for OIDC Client 'useRefreshTokens' #573

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/resources/openid_client.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ is set to `true`.
- `direct_grant_id` - (Optional) Direct grant flow id (flow needs to exist)
- `login_theme` - (Optional) The client login theme. This will override the default theme for the realm.
- `exclude_session_state_from_auth_response` - (Optional) When `true`, the parameter `session_state` will not be included in OpenID Connect Authentication Response.
- `use_refresh_tokens` - (Optional) If this is `true`, a refresh_token will be created and added to the token response. If this is `false` then no refresh_token will be generated. Defaults to `true`.
- `authorization` - (Optional) When this block is present, fine-grained authorization will be enabled for this client. The client's `access_type` must be `CONFIDENTIAL`, and `service_accounts_enabled` must be `true`. This block has the following arguments:
- `policy_enforcement_mode` - (Required) Dictates how policies are enforced when evaluating authorization requests. Can be one of `ENFORCING`, `PERMISSIVE`, or `DISABLED`.
- `decision_strategy` - (Optional) Dictates how the policies associated with a given permission are evaluated and how a final decision is obtained. Could be one of `AFFIRMATIVE`, `CONSENSUS`, or `UNANIMOUS`. Applies to permissions.
Expand Down
1 change: 1 addition & 0 deletions keycloak/openid_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type OpenidClientAttributes struct {
ClientOfflineSessionMaxLifespan string `json:"client.offline.session.max.lifespan,omitempty"`
ClientSessionIdleTimeout string `json:"client.session.idle.timeout,omitempty"`
ClientSessionMaxLifespan string `json:"client.session.max.lifespan,omitempty"`
UseRefreshTokens KeycloakBoolQuoted `json:"use.refresh.tokens"`
}

type OpenidAuthenticationFlowBindingOverrides struct {
Expand Down
5 changes: 5 additions & 0 deletions provider/data_source_keycloak_openid_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ func dataSourceKeycloakOpenidClient() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"use_refresh_tokens": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
},
}
}
Expand Down
7 changes: 7 additions & 0 deletions provider/resource_keycloak_openid_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ func resourceKeycloakOpenidClient() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"use_refresh_tokens": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
},
CustomizeDiff: customdiff.ComputedIf("service_account_user_id", func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool {
return d.HasChange("service_accounts_enabled")
Expand Down Expand Up @@ -270,6 +275,7 @@ func getOpenidClientFromData(data *schema.ResourceData) (*keycloak.OpenidClient,
ClientOfflineSessionMaxLifespan: data.Get("client_offline_session_max_lifespan").(string),
ClientSessionIdleTimeout: data.Get("client_session_idle_timeout").(string),
ClientSessionMaxLifespan: data.Get("client_session_max_lifespan").(string),
UseRefreshTokens: keycloak.KeycloakBoolQuoted(data.Get("use_refresh_tokens").(bool)),
},
ValidRedirectUris: validRedirectUris,
WebOrigins: webOrigins,
Expand Down Expand Up @@ -357,6 +363,7 @@ func setOpenidClientData(keycloakClient *keycloak.KeycloakClient, data *schema.R

data.Set("access_token_lifespan", client.Attributes.AccessTokenLifespan)
data.Set("login_theme", client.Attributes.LoginTheme)
data.Set("use_refresh_tokens", client.Attributes.UseRefreshTokens)
data.Set("client_offline_session_idle_timeout", client.Attributes.ClientOfflineSessionIdleTimeout)
data.Set("client_offline_session_max_lifespan", client.Attributes.ClientOfflineSessionMaxLifespan)
data.Set("client_session_idle_timeout", client.Attributes.ClientSessionIdleTimeout)
Expand Down
52 changes: 52 additions & 0 deletions provider/resource_keycloak_openid_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,27 @@ func TestAccKeycloakOpenidClient_loginTheme(t *testing.T) {
})
}

func TestAccKeycloakOpenidClient_useRefreshTokens(t *testing.T) {
t.Parallel()
clientId := acctest.RandomWithPrefix("tf-acc")

resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckKeycloakOpenidClientDestroy(),
Steps: []resource.TestStep{
{
Config: testKeycloakOpenidClient_useRefreshTokens(clientId, true),
Check: testAccCheckKeycloakOpenidClientUseRefreshTokens("keycloak_openid_client.client", true),
},
{
Config: testKeycloakOpenidClient_useRefreshTokens(clientId, false),
Check: testAccCheckKeycloakOpenidClientUseRefreshTokens("keycloak_openid_client.client", false),
},
},
})
}

func testAccCheckKeycloakOpenidClientExistsWithCorrectProtocol(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client, err := getOpenidClientFromState(s, resourceName)
Expand Down Expand Up @@ -728,6 +749,21 @@ func testAccCheckKeycloakOpenidClientLoginTheme(resourceName string, loginTheme
}
}

func testAccCheckKeycloakOpenidClientUseRefreshTokens(resourceName string, useRefreshTokens bool) resource.TestCheckFunc {
return func(s *terraform.State) error {
client, err := getOpenidClientFromState(s, resourceName)
if err != nil {
return err
}

if client.Attributes.UseRefreshTokens != keycloak.KeycloakBoolQuoted(useRefreshTokens) {
return fmt.Errorf("expected openid client to have use refresh tokens set to %t, but got %v", useRefreshTokens, client.Attributes.UseRefreshTokens)
}

return nil
}
}

func getOpenidClientFromState(s *terraform.State, resourceName string) (*keycloak.OpenidClient, error) {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
Expand Down Expand Up @@ -1063,3 +1099,19 @@ resource "keycloak_openid_client" "client" {
}
`, testAccRealm.Realm, clientId, loginTheme)
}

func testKeycloakOpenidClient_useRefreshTokens(clientId string, useRefreshTokens bool) string {

return fmt.Sprintf(`
data "keycloak_realm" "realm" {
realm = "%s"
}

resource "keycloak_openid_client" "client" {
client_id = "%s"
realm_id = data.keycloak_realm.realm.id
access_type = "CONFIDENTIAL"
use_refresh_tokens = %t
}
`, testAccRealm.Realm, clientId, useRefreshTokens)
}