Redis cache for faster auth
This commit is contained in:
parent
3ab65d1c51
commit
7c8e79c199
4 changed files with 36 additions and 2 deletions
|
@ -4,3 +4,5 @@ keycloak_token_url=https://keycloak.example.com/auth/realms/master/protocol/open
|
||||||
realm=master
|
realm=master
|
||||||
users_path=/srv/dav/public
|
users_path=/srv/dav/public
|
||||||
base_uri=/
|
base_uri=/
|
||||||
|
redis_host=localhost
|
||||||
|
redis_port=6379
|
||||||
|
|
|
@ -6,9 +6,11 @@ This project is meant to be a WebDav Server using Keycloak roles for it's [Princ
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- PHP
|
- PHP
|
||||||
|
- [phpredis](https://github.com/phpredis/phpredis)
|
||||||
- Composer
|
- Composer
|
||||||
- A running keycloak instance
|
- A running keycloak instance
|
||||||
- A Client with `Direct access grants` enabled
|
- A Client with `Direct access grants` enabled
|
||||||
|
- A running Redis Instance
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,14 @@ require 'vendor/autoload.php';
|
||||||
$dotenv = Dotenv::createImmutable(__DIR__);
|
$dotenv = Dotenv::createImmutable(__DIR__);
|
||||||
$dotenv->load();
|
$dotenv->load();
|
||||||
|
|
||||||
|
|
||||||
|
$redis_client = new Redis();
|
||||||
|
$redis_client->connect($_ENV['redis_host'], intval($_ENV['redis_port']));
|
||||||
|
|
||||||
$principalBackend = new RolesBackend();
|
$principalBackend = new RolesBackend();
|
||||||
|
|
||||||
// Set Auth
|
// Set Auth
|
||||||
$authBackend = new Keycloak\KeycloakAuth($principalBackend,$_ENV['client_id'], $_ENV['client_secret'], $_ENV['keycloak_token_url'] );
|
$authBackend = new Keycloak\KeycloakAuth($redis_client, $principalBackend,$_ENV['client_id'], $_ENV['client_secret'], $_ENV['keycloak_token_url'] );
|
||||||
$authBackend->setRealm($_ENV['realm']);
|
$authBackend->setRealm($_ENV['realm']);
|
||||||
$authPlugin = new DAV\Auth\Plugin($authBackend);
|
$authPlugin = new DAV\Auth\Plugin($authBackend);
|
||||||
|
|
||||||
|
|
|
@ -3,27 +3,49 @@
|
||||||
namespace Keycloak;
|
namespace Keycloak;
|
||||||
|
|
||||||
use Principal\RolesBackend;
|
use Principal\RolesBackend;
|
||||||
|
use Redis;
|
||||||
use Sabre\DAV\Auth\Backend\AbstractBasic;
|
use Sabre\DAV\Auth\Backend\AbstractBasic;
|
||||||
|
|
||||||
class KeycloakAuth extends AbstractBasic
|
class KeycloakAuth extends AbstractBasic
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private Redis $redis_client;
|
||||||
private RolesBackend $principal_backend;
|
private RolesBackend $principal_backend;
|
||||||
private string $client_id;
|
private string $client_id;
|
||||||
private string $client_secret;
|
private string $client_secret;
|
||||||
private string $keycloakTokenUrl;
|
private string $keycloakTokenUrl;
|
||||||
|
|
||||||
public function __construct(RolesBackend $principal_backend, string $client_id,
|
public function __construct(Redis $redis_client, RolesBackend $principal_backend, string $client_id,
|
||||||
string $client_secret, string $keycloakTokenUrl)
|
string $client_secret, string $keycloakTokenUrl)
|
||||||
{
|
{
|
||||||
|
$this->redis_client = $redis_client;
|
||||||
$this->principal_backend = $principal_backend;
|
$this->principal_backend = $principal_backend;
|
||||||
$this->client_id = $client_id;
|
$this->client_id = $client_id;
|
||||||
$this->client_secret = $client_secret;
|
$this->client_secret = $client_secret;
|
||||||
$this->keycloakTokenUrl = $keycloakTokenUrl;
|
$this->keycloakTokenUrl = $keycloakTokenUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function addReditCache(string $username, string $hash, array $roles): void {
|
||||||
|
$this->redis_client->set("credentials".$username.$hash, json_encode($roles), ["EX" => 60 * 15]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkReditCache(string $username, string $hash): array {
|
||||||
|
if (!$this->redis_client->exists("credentials" . $username . $hash)) return ["valid" => false];
|
||||||
|
|
||||||
|
$datastr = $this->redis_client->get("credentials" . $username . $hash);
|
||||||
|
$roles = json_decode($datastr);
|
||||||
|
return ["valid" => true, "roles" => $roles];
|
||||||
|
}
|
||||||
|
|
||||||
protected function validateUserPass($username, $password) : bool
|
protected function validateUserPass($username, $password) : bool
|
||||||
{
|
{
|
||||||
|
$hash = hash("sha256", $password);
|
||||||
|
$inCache = $this->checkReditCache($username, $hash);
|
||||||
|
if ($inCache["valid"]) {
|
||||||
|
$this->principal_backend->setPrincipals($inCache["roles"]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$curl = curl_init();
|
$curl = curl_init();
|
||||||
|
|
||||||
curl_setopt_array($curl, [
|
curl_setopt_array($curl, [
|
||||||
|
@ -52,6 +74,8 @@ class KeycloakAuth extends AbstractBasic
|
||||||
if ($err || $data['http_code'] != 200) {
|
if ($err || $data['http_code'] != 200) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
$this->addReditCache($username, $hash, []);
|
||||||
|
|
||||||
$x = json_decode($body);
|
$x = json_decode($body);
|
||||||
$user_data = json_decode(base64_decode(explode(".",$x->access_token)[1]), true);
|
$user_data = json_decode(base64_decode(explode(".",$x->access_token)[1]), true);
|
||||||
|
|
||||||
|
@ -66,6 +90,8 @@ class KeycloakAuth extends AbstractBasic
|
||||||
|
|
||||||
$this->principal_backend->setPrincipals($roles);
|
$this->principal_backend->setPrincipals($roles);
|
||||||
|
|
||||||
|
$this->addReditCache($username, $hash, $roles);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue