Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@graziang
Copy link
Contributor

@graziang graziang commented Aug 22, 2024

Closes #31513

Changes introduced by this PR to support lightweight access tokens for the admin REST APIs:

  • In MgmtPermissions.initIdentity(), the presence of the sub field in the token is evaluated to check if the access token is lightweight. If the sub is missing, the user session is retrieved, and the realm roles and client roles are resolved. All client roles of the user are resolved not just a subset. See the performance analysis for details.

  • The workaround for the security-admin-console and admin-cli clients has been removed. To remove the workaround that was present both in MgmtPermissions.initIdentity() and in ClientRegistrationAuth, a migration was necessary to enable the use of lightweight access tokens and to enable the full scope allowed for these clients. Enabling the full scope allowed is needed to resolve the client roles of the various realm clients in the master realm.

  • A normal audience check for the admin REST APIs is not possible due to the admin-fine-grained-authz feature. With this feature enabled, the permissions to invoke the admin APIs can be granted based on client policies. Should we check the audience only in the case of this feature disabled or feature enabled and negative permission evaluation?

Performance Analysis:
I conducted manual tests with the admin console, preloading 500 realms, and using both the admin user and a user with roles in 5 realms. With a non-lightweight token and with a different client than security-admin-console and admin-cli, the behavior remains the same.

However, when using a lightweight token, it's necessary to resolve the user's roles, and this operation can be more expensive. Resolving the realm roles or client roles using RoleResolveUtil.getResolvedRealmRoles(), RoleResolveUtil.getResolvedClientRoles() or RoleResolveUtil.getAllResolvedRealmRoles() first loads all the user's roles into cache with the RoleResolveUtil.getAndCacheResolvedRoles() method which based on the tests can cause a delay the first time it is invoked. The slowdown is noticeable only in the /serverinfo call which for the first time loads the user's roles in about 1.2 seconds (the same call with the previous behavior takes about 300ms). After this first load, the times of all other requests are in line with the previous behavior, or even better.

One idea to optimize the loading of roles could be to add a query with a join between USER_ROLE_MAPPING and KEYCLOAK_ROLE to obtain only the list of roles for a client and a user or only realm roles for a user. However, this would require a greater impact on the classes and methods currently used to resolve roles.

Alternatively, we could maintain the workaround and introduce only the changes from the first point when using lightweight access tokens for other clients.

@keycloak-github-bot
Copy link

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.model.session.UserSessionPersisterProviderTest#testPersistenceWithLoad

Keycloak CI - Store Model Tests

java.lang.AssertionError: expected:<2> but was:<0>
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.failNotEquals(Assert.java:835)
	at org.junit.Assert.assertEquals(Assert.java:647)
	at org.junit.Assert.assertEquals(Assert.java:633)
...

Report flaky test

Copy link

@keycloak-github-bot keycloak-github-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@mposolda mposolda self-assigned this Sep 2, 2024
Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@graziang Thanks for the PR and the performance analysis! I would say let's go with this approach and we can later evaluate if there are any issues reported and do more performance optimizations as a follow-up if needed.

I've added some minor comments inside.

Besides that, is it possible to add some short notice to migration guide about changed setting of the security-admin-console and admin-cli clients? You can add that behaviour in the admin console should be effectively the same, but can be good to still mention it for the case that someone uses those clients for some other use-cases etc.

try {
if (jwt.getIssuedFor().equals(Constants.ADMIN_CLI_CLIENT_ID)
|| jwt.getIssuedFor().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
return hasRoleInModel(roles);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to remove method hasRoleInModel now from this class?

}

//get client session
ClientModel client = realm.getClientByClientId(issuedFor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it can still happen that userSession is null after this? Same for client and clientSession variables below? Is it possible to handle his better way than NullPointerException? Maybe it is OK to just add debug log message and not set anything into jwt for this case.

}

//get client session
ClientModel client = adminsRealm.getClientByClientId(issuedFor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment like the other place for userSession, client and clientSession null checks.

Copy link

@keycloak-github-bot keycloak-github-bot bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@keycloak-github-bot
Copy link

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.webauthn.registration.passwordless.PwdLessPolicyJsInjectionTest#relyingPartyId

Keycloak CI - WebAuthn IT (chrome)

java.lang.AssertionError: Expected RegisterPage but was Sign in to test (https://localhost:8543/auth/realms/test/protocol/openid-connect/auth?response_type=code&client_id=test-app&redirect_uri=https%3A%2F%2Flocalhost%3A8543%2Fauth%2Frealms%2Fmaster%2Fapp%2Fauth&state=e80b1914-5083-477c-a148-a5717077cc53&scope=openid)
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.assertTrue(Assert.java:42)
	at org.keycloak.testsuite.pages.AbstractPage.assertCurrent(AbstractPage.java:47)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
...

Report flaky test

org.keycloak.testsuite.forms.MultipleTabsLoginTest#expiredAuthenticationAction_currentCodeExpiredExecution

Keycloak CI - Forms IT (chrome)

java.lang.AssertionError: Expected RegisterPage but was Sign in to test (https://localhost:8543/auth/realms/test/protocol/openid-connect/auth?response_type=code&client_id=test-app&redirect_uri=https%3A%2F%2Flocalhost%3A8543%2Fauth%2Frealms%2Fmaster%2Fapp%2Fauth&state=6402344b-a01e-4a65-bc61-1a5801817944&scope=openid)
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.assertTrue(Assert.java:42)
	at org.keycloak.testsuite.pages.AbstractPage.assertCurrent(AbstractPage.java:47)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
...

Report flaky test

org.keycloak.testsuite.forms.ResetPasswordTest#resetPasswordWithSpacesInUsername

Keycloak CI - Forms IT (chrome)

java.lang.AssertionError: Expected LoginPasswordResetPage but was Sign in to test (https://localhost:8543/auth/realms/test/protocol/openid-connect/auth?response_type=code&client_id=test-app&redirect_uri=https%3A%2F%2Flocalhost%3A8543%2Fauth%2Frealms%2Fmaster%2Fapp%2Fauth&state=cbc68d78-e592-4f0c-880f-cec764c2a3d2&scope=openid)
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.assertTrue(Assert.java:42)
	at org.keycloak.testsuite.pages.AbstractPage.assertCurrent(AbstractPage.java:47)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
...

Report flaky test

Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@graziang Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support lightweight access tokens for Admin REST API

2 participants