This library is meant to help R developers to easily implement authentication and authorization in their applications using Keycloak.
Keycloak is an open source Identity and Access Management solution (supported by RedHat) aimed at modern applications and services. It makes it easy to secure applications and services with little to no code.
Keycloak Auth R is an R package that provides a simple interface to Keycloak's REST API. It allows developers to easily implement authentication and authorization in their applications.
This package is not yet available on CRAN. You can install it from GitHub using the remotes
package:
remotes::install_github("andyquinterom/keycloakAuthR")
This package is still in development. Many features are not yet implemented and the API is subject to change. However, the basic functionality is there.
This package exports an R6 class called keycloak_config
that is used to store the
configuration of a Keycloak server. You can create a new instance of this class
using keycloak_config$new(...)
.
The keycloak_config$new
method accepts the following arguments:
base_url
: The base URL of the auth endpoint of the Keycloak server.realm
: The name of the realm to use.client_id
: The client ID to use.client_secret
: The client secret to use.
With these parameters the class is able to generate the URLs needed to interact with the Keycloak server.
The keycloak_config
class implements some methods that can be used to interact with
the Keycloak server. The most important ones are:
get_login_url
: Returns the URL that can be used to initiate the login process.redirect_uri
: The URL to redirect to after the login process is complete.
get_logout_url
: Returns the URL that can be used to initiate the logout process.redirect_uri
: This argument is optional. If provided, the user will be redirected to this URL after the logout process is complete.
request_token
: Requests a token from the Keycloak server. If successful, alist
with anaccess_token
,refresh_token
(if enabled), and other information is returned.authorization_code
: The authorization code obtained after the login process is complete.redirect_uri
: The URL to redirect to after the login process is complete.
decode_token
: Decodes a token and throws and error if the token's signature is invalid. This method should not really be used directly, instead use the methods inside thekeycloak_access_token
class.token
: The token to decode.
refresh_jwks
: Refreshes the JWKS (JSON Web Key Set) used to verify the signature of tokens. This method is called automatically when needed, but it can also be called manually.
This package exports an R6 class called keycloak_access_token
that is used to store
information about an access token. You can create a new instance of this class using
keycloak_access_token$new(...)
.
The keycloak_access_token$new
method accepts the following arguments:
token
: The access token to store (this value can be taken from the list returned by therequest_token
method inside thekeycloak_config
class).config
: An instance of thekeycloak_config
class.refresh_token
(optional): The refresh token to store (this value can be taken from the list returned by therequest_token
method inside thekeycloak_config
class).
The keycloak_access_token
class implements some methods that can be used to interact with
the access token. The most important ones are:
is_valid
: ReturnsTRUE
if the token is valid,FALSE
otherwise.get_bearer
: Returns the bearer token that can be used to authenticate requests to other services.get_access_token
: Returns the access token.get_refresh_token
: Returns the refresh token.get_realm_roles
: Returns the realm roles assigned to the user.get_resource_roles
: Returns the resource/client roles assigned to the user.has_realm_role
: ReturnsTRUE
if the user has the specified realm role,FALSE
otherwise.has_resource_role
: ReturnsTRUE
if the user has the specified resource/client role,FALSE
otherwise.expires_in
: Returns the number of seconds until the token expires.expires_at
: Returns the date and time when the token expires.is_expired
: ReturnsTRUE
if the token is expired,FALSE
otherwise.get_preferred_username
: Returns the preferred username of the user.get_email
: Returns the email of the user.get_name
: Returns the name of the user.get_given_name
: Returns the given name of the user.get_family_name
: Returns the family name of the user.is_email_verified
: ReturnsTRUE
if the user's email is verified,FALSE
otherwise.
Working with Shiny is really simple. You just need to create an instance of the
keycloak_config
class. This instance can be passed on to different functions
that the library exports.
To enable authentication in your Shiny App, you need to start the
keycloak_shiny_login_server
module. This module will handle the login process
and will return a reactive with an instance of the keycloak_access_token
class.
This reactive can be used to check if the user is logged in and to get information
about the user.
The keycloak_shiny_login_server
module accepts the following arguments:
config
: An instance of thekeycloak_config
class.redirect_uri
: The URL to redirect to after the login process is complete.auto_redirect
(optional): IfTRUE
, the user will be redirected to the login page automatically if they are not logged in. Defaults toTRUE
.
To log a user out, you need to call the keycloak_shiny_signout
function inside
a reactive context.
The implementation of the login and logout process handles tokens automatically with httpOnly cookies. This means that you don't need to worry about storing tokens in the browser's local storage or in cookies.
Here's a simple example:
library(keycloakAuthR)
library(shiny)
config <- keycloak_config$new(
Sys.getenv("KEYCLOAK_URL"),
realm = Sys.getenv("KEYCLOAK_REALM"),
client_id = Sys.getenv("KEYCLOAK_CLIENT_ID"),
client_secret = Sys.getenv("KEYCLOAK_CLIENT_SECRET")
)
ui <- fluidPage(
uiOutput("secret_message")
)
server <- function(input, output, session) {
token <- keycloak_shiny_login_server(config, "http://localhost:3838", auto_redirect = FALSE)
output$secret_message <- renderUI({
if (token()$is_valid()) {
tags$div(
tags$h1("Secret message"),
tags$p("This is a secret message that only logged in users can see."),
actionButton("logout", "Logout")
)
} else {
tags$a(
href = config$get_login_url("http://localhost:3838"),
tags$h1("Login")
)
}
})
observeEvent(input$logout, {
keycloak_shiny_signout(config, redirect_uri = "http://localhost:3838")
})
}
shinyApp(ui, server)