(Updated)
If you are developing an internal Spi, you can access the same private apis Keycloak uses to generate access token from token request. You can quikly look into keycloak default implementation of ClientCredentialsGrantType.java. But I should warn you that there are some drawbacks on using those internal APIs, besides the fact that keycloak could change it any moment, those apis are tricky and heavly coupled. Another point way more critial is that keycloak have no clue about the URI/domain that it is running without an active Http Connection. In short, if you are in a session not started from a browser it is impossible to catch the correct context.getUri().
So, to answer you the above code will work only if are in a Http based session. Otherwise you shall provide the correct issuer Uri or simulate an Connection on context.setConnection().
var realm = context.getRealm();
var clientUser = userProvider.getServiceAccount(client);
RootAuthenticationSessionModel rootAuthSession = authSessionManager.createAuthenticationSession(realm, false);
AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
authSession.setAuthenticatedUser(clientUser);
authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(context.getUri().getBaseUri(), realm.getName()));
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, "openid email");
var userSession = session.sessions()
.createUserSession(
authSession.getParentSession().getId(),
realm,
clientUser,
clientUser.getUsername(),
null,
ServiceAccountConstants.CLIENT_AUTH,
false, null, null, UserSessionModel.SessionPersistenceState.PERSISTENT);
var clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);
accessToken = ((TokenManager) session.tokens()).responseBuilder(
realm, client, new EventBuilder(realm, session), session, userSession, clientSessionCtx)
.generateAccessToken()
.getAccessToken();
I strongly suggest you to just make an HttpRequest to obtain credentials from keycloak public apis like the follow code:
var auth = client.getClientId() + ":" + client.getSecret();
var encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
var body = "grant_type=client_credentials";
var request = HttpRequest
.newBuilder(tokenEndpoint)
.setHeader("Content-Type", "application/x-www-form-urlencoded")
.setHeader("Authorization", "Basic " + encodedAuth)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
var jsonResponse = JsonSerialization.readValue(response.body(), JsonNode.class);
accessToken = TokenVerifier.create(jsonResponse.get("access_token").asText(), AccessToken.class).getToken();