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

OpenID Valid Configuration is being unvalidated by the Provider #1009

Open
Sanhajio opened this issue Oct 23, 2024 · 0 comments
Open

OpenID Valid Configuration is being unvalidated by the Provider #1009

Sanhajio opened this issue Oct 23, 2024 · 0 comments

Comments

@Sanhajio
Copy link

Hello,

I was configuring Keycloak 25.0.6 through , and I needed to update the realm-management default configuration, and I came accross this edge case: I can have BearerOnly: true and ServiceAccountsEnabled: true

I don't have the reasons why there is ValidateOpenidClient, I could propose a PR if there is no obvious reason to keep the validation.

resource "keycloak_openid_client" "realm_management" {
  realm_id                = data.keycloak_openid_client.realm_management.realm_id
  client_id               = data.keycloak_openid_client.realm_management.client_id
  access_type             = data.keycloak_openid_client.realm_management.access_type
  client_authenticator_type = data.keycloak_openid_client.realm_management.client_authenticator_type
  enabled                 = data.keycloak_openid_client.realm_management.enabled
  full_scope_allowed      = data.keycloak_openid_client.realm_management.full_scope_allowed
  service_accounts_enabled = data.keycloak_openid_client.realm_management.service_accounts_enabled
  use_refresh_tokens      = data.keycloak_openid_client.realm_management.use_refresh_tokens
  use_refresh_tokens_client_credentials = data.keycloak_openid_client.realm_management.use_refresh_tokens_client_credentials
  standard_flow_enabled   = data.keycloak_openid_client.realm_management.standard_flow_enabled
  oauth2_device_authorization_grant_enabled = data.keycloak_openid_client.realm_management.oauth2_device_authorization_grant_enabled
  consent_required        = data.keycloak_openid_client.realm_management.consent_required
  base_url                = data.keycloak_openid_client.realm_management.base_url
  root_url                = data.keycloak_openid_client.realm_management.root_url
  admin_url               = data.keycloak_openid_client.realm_management.admin_url
  client_secret           = data.keycloak_openid_client.realm_management.client_secret
  valid_redirect_uris     = data.keycloak_openid_client.realm_management.valid_redirect_uris
  valid_post_logout_redirect_uris = data.keycloak_openid_client.realm_management.valid_post_logout_redirect_uris
  web_origins             = data.keycloak_openid_client.realm_management.web_origins
  frontchannel_logout_enabled = data.keycloak_openid_client.realm_management.frontchannel_logout_enabled

  authorization {
    allow_remote_resource_management = false
    policy_enforcement_mode          = "ENFORCING"
    decision_strategy                = "UNANIMOUS"
  }

  depends_on = [keycloak_realm.realm]
}
  • The go code that validates the openIdClient configuration
func (keycloakClient *KeycloakClient) ValidateOpenidClient(ctx context.Context, client *OpenidClient) error {
	if client.BearerOnly && (client.StandardFlowEnabled || client.ImplicitFlowEnabled || client.DirectAccessGrantsEnabled || client.ServiceAccountsEnabled) {
		return fmt.Errorf("validation error: Keycloak cannot issue tokens for bearer-only clients; no oauth2 flows can be enabled for this client")
	}

	if (client.StandardFlowEnabled || client.ImplicitFlowEnabled) && len(client.ValidRedirectUris) == 0 {
		return fmt.Errorf("validation error: standard (authorization code) and implicit flows require at least one valid redirect uri")
	}

	if client.ServiceAccountsEnabled && client.PublicClient {
		return fmt.Errorf("validation error: service accounts (client credentials flow) cannot be enabled on public clients")
	}

	serverInfo, err := keycloakClient.GetServerInfo(ctx)
	if err != nil {
		return err
	}

	if client.Attributes.LoginTheme != "" && !serverInfo.ThemeIsInstalled("login", client.Attributes.LoginTheme) {
		return fmt.Errorf("validation error: theme \"%s\" does not exist on the server", client.Attributes.LoginTheme)
	}

	return nil
}

Keycloak error when setting bearerOnly: true and serviceAccountEnabled: false

2024-10-23 17:11:09,053 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-418) Uncaught server error: java.lang.RuntimeException: Client does not have a service account.
        at org.keycloak.authorization.admin.ResourceServerService.create(ResourceServerService.java:85)
        at org.keycloak.authorization.admin.AuthorizationService.enable(AuthorizationService.java:67)
        at org.keycloak.services.resources.admin.ClientResource.updateAuthorizationSettings(ClientResource.java:844)
        at org.keycloak.services.resources.admin.ClientResource.updateClientFromRep(ClientResource.java:838)
        at org.keycloak.services.resources.admin.ClientResource.update(ClientResource.java:155)
        at org.keycloak.services.resources.admin.ClientResource$quarkusrestinvoker$update_c18fc2ee235fe1638ccf09830bdd635e799b1172.invoke(Unknown Source)
        at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
        at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:1583)
  • realm-management-validated-not-working.json
{
    "id": "ab9d6477-9648-4039-be0b-faefa1d58411",
    "clientId": "realm-management",
    "name": "${client_realm-management}",
    "protocol": "openid-connect",
    "clientAuthenticatorType": "client-secret",
    "enabled": true,
    "description": "",
    "publicClient": false,
    "bearerOnly": true,
    "standardFlowEnabled": true,
    "implicitFlowEnabled": false,
    "directAccessGrantsEnabled": false,
    "serviceAccountsEnabled": false,
    "frontchannelLogout": false,
    "authorizationServicesEnabled": true,
    "redirectUris": [],
    "webOrigins": [],
    "adminUrl": "",
    "baseUrl": "",
    "fullScopeAllowed": false,
    "attributes": {
        "access.token.lifespan": "",
        "backchannel.logout.revoke.offline.tokens": "false",
        "backchannel.logout.session.required": "true",
        "backchannel.logout.url": "",
        "client.offline.session.idle.timeout": "",
        "client.offline.session.max.lifespan": "",
        "client.session.idle.timeout": "",
        "client.session.max.lifespan": "",
        "client_credentials.use_refresh_token": "false",
        "consent.screen.text": "",
        "display.on.consent.screen": "false",
        "exclude.session.state.from.auth.response": "false",
        "frontchannel.logout.url": "",
        "login_theme": "",
        "oauth2.device.authorization.grant.enabled": "false",
        "oauth2.device.code.lifespan": "",
        "oauth2.device.polling.interval": "",
        "pkce.code.challenge.method": "",
        "post.logout.redirect.uris": "",
        "use.refresh.tokens": "false"
    },
    "authorizationSettings": {
        "policyEnforcementMode": "ENFORCING",
        "decisionStrategy": "UNANIMOUS"
    },
    "consentRequired": false,
    "authenticationFlowBindingOverrides": {
        "browser": "",
        "direct_grant": ""
    }
}
  • realm-management-not-validated-working.json
{
    "id": "ab9d6477-9648-4039-be0b-faefa1d58411",
    "clientId": "realm-management",
    "name": "${client_realm-management}",
    "protocol": "openid-connect",
    "clientAuthenticatorType": "client-secret",
    "enabled": true,
    "description": "",
    "publicClient": false,
    "bearerOnly": true,
    "standardFlowEnabled": true,
    "implicitFlowEnabled": false,
    "directAccessGrantsEnabled": false,
    "serviceAccountsEnabled": true,
    "frontchannelLogout": false,
    "authorizationServicesEnabled": true,
    "redirectUris": [],
    "webOrigins": [],
    "adminUrl": "",
    "baseUrl": "",
    "fullScopeAllowed": false,
    "attributes": {
        "access.token.lifespan": "",
        "backchannel.logout.revoke.offline.tokens": "false",
        "backchannel.logout.session.required": "true",
        "backchannel.logout.url": "",
        "client.offline.session.idle.timeout": "",
        "client.offline.session.max.lifespan": "",
        "client.session.idle.timeout": "",
        "client.session.max.lifespan": "",
        "client_credentials.use_refresh_token": "false",
        "consent.screen.text": "",
        "display.on.consent.screen": "false",
        "exclude.session.state.from.auth.response": "false",
        "frontchannel.logout.url": "",
        "login_theme": "",
        "oauth2.device.authorization.grant.enabled": "false",
        "oauth2.device.code.lifespan": "",
        "oauth2.device.polling.interval": "",
        "pkce.code.challenge.method": "",
        "post.logout.redirect.uris": "",
        "use.refresh.tokens": "false"
    },
    "authorizationSettings": {
        "policyEnforcementMode": "ENFORCING",
        "decisionStrategy": "UNANIMOUS"
    },
    "consentRequired": false,
    "authenticationFlowBindingOverrides": {
        "browser": "",
        "direct_grant": ""
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant