Keycloak4s
Keycloak4s is a Scala client for the Keycloak Admin API
Install / Use
/learn @fullfacing/Keycloak4sREADME
keycloak4s
A Scala-based middleware API for Keycloak<br/> Supports version 19.0.1
keycloak4s is an opinionated Scala-built API that serves as a bridge between any Scala project and a Keycloak server. It allows access to the server's Admin API, and provides adapters that validates Keycloak's bearer tokens. It authorizes requests via a JSON config file inspired by their [policy enforcement configuration][Policy-Configuration].
The project is split into the following modules, each as a separate dependency:
-
keycloak4s-core: Contains core functionality and shared models across other modules. -
keycloak4s-admin: Allows access to Keycloak's [Admin API][Admin-API]. Utilizes SoftwareMill's sttp and Cats Effect's Concurrent which respectively allows for customization of the HTTP client. -
keycloak4s-admin-monix: A more concrete implementation of keycloak-admin using [Monix][Monix]. Contains additional reactive streaming functionality. -
keycloak4s-auth-akka-http: A client adapter capable of validating Keycloak's bearer tokens, and providing authorization for [Akka-HTTP][Akka-Http] requests. -
keycloak4s-admin-ce3: Admin module upgraded to Cats Effect 3
Contents
- Installation
- Module: keycloak4s-core
- Module: keycloak4s-admin
- Module: keycloak4s-admin-monix
- Module: keycloak4s-auth-akka-http
- Logging
- Error Messages
Installation
Each module can be pulled into a project separately using the following SBT dependencies:
- keycloak4s-core:
"com.fullfacing" %% "keycloak4s-core" % "3.2.4" - keycloak4s-admin:
"com.fullfacing" %% "keycloak4s-admin" % "3.2.4" - keycloak4s-admin-monix:
"com.fullfacing" %% "keycloak4s-admin-monix" % "3.2.4" - keycloak4s-admin-monix-bio:
"com.fullfacing" %% "keycloak4s-admin-monix-bio" % "3.2.4" - keycloak4s-auth-akka-http:
"com.fullfacing" %% "keycloak4s-auth-akka-http" % "3.2.4"
Cats 3 modules
- keycloak4s-core-ce3:
"com.fullfacing" %% "keycloak4s-core-ce3" % "3.2.1" - keycloak4s-admin-ce3:
"com.fullfacing" %% "keycloak4s-admin-ce3" % "3.2.1"
The core module is a dependency for all other modules, and is automatically pulled in when using any other module.
Module: keycloak4s-core <a name="keycloak4s-core"></a>
The core module shares common functionality (such as logging and error handling) and data models with its dependent modules.
It is important to note that the KeycloakConfig model contains the Keycloak server information. This information will be required often. Included in this set of information, is the following:
- The Keycloak server's URL scheme, host and port.
- The name of the Keycloak realm to be targeted.
- The name, client ID and client secret of the Keycloak realm providing authorization (client-credential grant) OR the client ID along with the username and password of the authorized user (password grant).
Example:
import com.fullfacing.keycloak4s.core.models.KeycloakConfig
import com.fullfacing.keycloak4s.core.models.ConfigWithAuth
val authConfig = KeycloakConfig.Secret(
realm = "master",
clientId = "admin-cli",
clientSecret = "b753f3ba-c4e7-4f3f-ac16-a074d4d89353"
)
val keycloakConfig = ConfigWithAuth(
scheme = "http",
host = "fullfacing.com/keycloak",
port = 8080,
realm = "demo",
authn = authConfig,
basePath = List("auth")
)
Module: keycloak4s-admin <a name="keycloak4s-admin"></a>
The module uses the client credential flow behind the scenes to simplify access to Keycloak's [Admin API][Admin-API]. In order to make calls to it, a client needs to be created with the correct server details and credentials to connect to the Keycloak server, followed by a service handler that can invoke the calls. The process can be broken down into the following steps:
1 - Create a KeycloakConfig<br/> Refer to the keycloak4s-core segment for details on KeycloakConfig. Please note that the authorization realm must be a service account-enabled admin client.
2 - Create a KeycloakClient<br/> The KeycloakClient handles the HTTP calls to the KeycloakServer. It requires a KeycloakConfig, and an sttp backend (the KeycloakClient and the sttp backend must match parametric types). Alternatively, the Akka/Monix module can be used for a concrete implementation. For more information, refer to the Module: keycloak4s-admin-monix module of this document.
Example:
implicit val backend: SttpBackend[Task, Observable[ByteBuffer]] = AsyncHttpClientBackend()
implicit val keycloakClient: KeycloakClient[Task, Observable[ByteBuffer]] = new KeycloakClient[Task, Observable[ByteBuffer]](config)
3 - Create a service handler<br/> In this context, a service handler contains the admin calls that are relevant to a specific aspect of Keycloak. For example, the Users service contains calls that creates, retrieves and manipulates Keycloak Users. Please note: When creating a service handler, an implicit KeycloakClient must be in scope.
Example:
val usersService = Keycloak.Users[Task, Observable[ByteBuffer]]
val rolesService = Keycloak.Roles[Task, Observable[ByteBuffer]]
4 - Invoke the calls<br/> The relevant admin API calls can be invoked from a service handler. This will automatically handle calls for access, and refresh tokens in the background through the client credentials flow.
Example:
val newUser = User.Create(username = "ff_keycloak_user_01", enabled = true)
val newGroup = Group.Create(name = "ff_keycloak_group_01")
for {
u <- EitherT(usersService.createAndRetrieve(newUser))
g <- EitherT(groupsService.createAndRetrieve(newGroup))
_ <- EitherT(usersService.addToGroup(u.id, g.id))
} yield (u, g)
The majority of the functions in a service handler corresponds directly with an admin API route. However, a few are composite functions created for convenience. An example of this can be seen in the aforementioned example where thecreateAndRetrieve function chains a create- and a fetch call.
Module: keycloak4s-admin-monix <a name="keycloak4s-admin-monix"></a>
keycloak4s-admin-monix can be used as an alternative to keycloak4s-admin. This module is typed to Monix with [Tasks][Task] as the response wrapper and [Observables][Observable] as the streaming type. This removes the need to set up the types for KeycloakClient or the service handlers, apart from the type of byte collection used by the backend for streaming. Additionally, this module contains reactive streaming variants of the fetch calls, which allows for batch retrieval and processing.
The steps to make these calls remains the same as in the keycloak4s-admin. The following example provides the specific pre-built sttp backend. For more information, refer to Module: keycloak4s-admin in this document.
Example:
implicit val backend: SttpBackend[Task, Observable[ByteString]] = AkkaMonixHttpBackend()
implicit val monixClient: KeycloakClient[ByteString] = new KeycloakClient(...) // truncated, see keycloak4s-core segment for details
val usersService = Keycloak.Users[ByteString]
usersService.fetch()
To use the streaming variants of this module simply replace any fetch call with fetchS, which takes an additional batchSize parameter. The function returns an [Observable][Observable] and operates in batches by calling to retrieve the specified batch size, processing the batched results, then making the call for the next batch.
Example:
val usersService = Keycloak.Users
// return the IDs of all disabled Users
usersService.fetchS(batchSize = 20)
.dropWhile(!_.enabled)
.map(_.id)
.toListL
A fetchL variant is also available which performs the same batch streaming, but automatically converts the Observable to a List of Task when the stream has completed.
Module: keycloak4s-auth-akka-http <a name="keycloak4s-akka-http"></a>
Please note: This module is especially opinionated and was designed with our company's needs in mind. However, an effort was made to keep it as abstract as possible to allow for repurposed use. Feedback on its usability is encouraged.
This module is a client adapter for Akka-HTTP that allows the service to validate Keycloak's bearer tokens (through the use of [Nimbus JOSE
Related Skills
bluebubbles
337.3kUse when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="bluebubbles".
gh-issues
337.3kFetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]
healthcheck
337.3kHost security hardening and risk-tolerance configuration for OpenClaw deployments
node-connect
337.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
