1. Go to this page and download the library: Download dmstr/yii2-usuario-keycloak library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
dmstr / yii2-usuario-keycloak example snippets
use yii\authclient\Collection;
use Da\User\AuthClient\Keycloak;
return [
'components' => [
'authClientCollection' => [
'class' => Collection::class,
'clients' => [
'keycloak' => [
'class' => Keycloak::class,
'title' => getenv('KEYCLOAK_CLIENT_NAME'),
'clientId' => getenv('KEYCLOAK_CLIENT_ID'),
'clientSecret' => getenv('KEYCLOAK_CLIENT_SECRET'),
'issuerUrl' => getenv('KEYCLOAK_ISSUER_URL')
]
]
],
'user' => [
// So that the session do not get mixed up
'enableAutoLogin' => false
]
]
]
namespace app\components;
use Yii;
use yii\base\InvalidConfigException;
/**
* @property-read string|null $authSource
*/
class User extends yii\web\User
{
protected const AUTH_SOURCE_CLIENT_ID_SESSION_KEY = 'authSourceClientId';
/**
* @throws InvalidConfigException
*/
public function setAuthSource(string $clientId): void
{
Yii::$app->getSession()->set(self::AUTH_SOURCE_CLIENT_ID_SESSION_KEY, $clientId);
}
/**
* Returns the name of the auth client with which the user has authenticated himself.
*
* - null means not authenticated.
* - 'app' means, not authenticated via an auth client
*
* @return string|null
*/
public function getAuthSource(): ?string
{
if ($this->getIsGuest()) {
return null;
}
return Yii::$app->getSession()->get(self::AUTH_SOURCE_CLIENT_ID_SESSION_KEY, 'app');
}
}
use app\components\User;
use Da\User\AuthClient\Keycloak;
use Da\User\Event\SocialNetworkAuthEvent;
use dmstr\usuario\keycloak\controllers\SecurityController;
use yii\base\Exception;
use yii\base\InvalidArgumentException;
use yii\web\Application;
return [
'on ' . Application::EVENT_BEFORE_REQUEST => function () {
$user = Yii::$app->getUser();
$keycloakClientId = 'keycloak';
if ($user && !$user->getIsGuest() && Yii::$app->getUser()->getAuthSource() === $keycloakClientId) {
try {
$jwt = Yii::$app->jwt;
/** @var Keycloak $keycloak */
$keycloak = Yii::$app->authClientCollection->getClient($keycloakClientId);
// Check if token is valid
if (!$jwt->validate($keycloak->getAccessToken()->getToken())) {
// If token is invalid log out the user
throw new Exception('Access token invalid.');
}
} catch (Exception $exception) {
Yii::error($exception->getMessage());
// Logout user if token cannot be revalidated or is revoked
$user->logout();
}
}
},
'components' => [
'user' => [
'class' => User::class
]
],
'modules' => [
'user' => [
'controllerMap' => [
'security' => [
'class' => SecurityController::class,
'on ' . SocialNetworkAuthEvent::EVENT_AFTER_AUTHENTICATE => function (SocialNetworkAuthEvent $event) {
// Save the auth client info to differentiate afterward from which auth client the user was authenticated
Yii::$app->getUser()->setAuthSource($event->getClient()->getId());
}
]
]
]
]
];
namespace app\models;
use bizley\jwt\JwtHttpBearerAuth;
use Da\User\Model\SocialNetworkAccount;
use Lcobucci\JWT\Token\Plain;
use yii\base\NotSupportedException;
use Yii;
class User extends \Da\User\Model\User {
/**
* @inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
if ($type === JwtHttpBearerAuth::class) {
/** @var Plain $jwtToken */
$jwtToken = Yii::$app->jwt->getParser()->parse((string)$token);
$claims = $jwtToken->claims();
$userClientId = $claims->get('sub');
/** @var SocialNetworkAccount|null $socialAccount */
$socialAccount = SocialNetworkAccount::find()->andWhere([
'provider' => 'keycloak',
'client_id' => $userClientId
])->one();
if ($socialAccount) {
return static::find()
->whereId($socialAccount->user_id)
->andWhere(['blocked_at' => null])
->andWhere(['NOT', ['confirmed_at' => null]])
->andWhere(['gdpr_deleted' => 0])
->one();
}
return null;
}
throw new NotSupportedException("Type '$type' is not implemented.");
}
}
use app\models\User as UserModel;
return [
'components' => [
'user' => [
'identityClass' => UserModel::class
]
]
]
use bizley\jwt\Jwt;
use Lcobucci\JWT\Validation\Constraint\IssuedBy;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Constraint\LooseValidAt;
use Lcobucci\Clock\SystemClock;
return [
'components' => [
'jwt' => [
'class' => Jwt::class,
'signer' => Jwt::RS256,
'signingKey' => [
'key' => getenv('KEYCLOAK_PRIVATE_KEY_FILE'),
'method' => Jwt::METHOD_FILE,
],
'verifyingKey' => [
'key' => getenv('KEYCLOAK_PUBLIC_KEY_FILE'),
'method' => Jwt::METHOD_FILE,
],
'validationConstraints' => function (Jwt $jwt) {
$config = $jwt->getConfiguration();
return [
new SignedWith($config->signer(), $config->verificationKey()),
new IssuedBy(getenv('KEYCLOAK_ISSUER_URL')),
new LooseValidAt(SystemClock::fromUTC()),
];
}
]
]
];
use bizley\jwt\JwtTools;
use Lcobucci\JWT\Validation\Constraint\IssuedBy;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Constraint\LooseValidAt;
use Lcobucci\Clock\SystemClock;
return [
'components' => [
'jwt' => [
'class' => JwtTools::class,
'validationConstraints' => function (JwtTools $jwt) {
return [
new SignedWith($jwt->buildSigner(Jwt::RS256), InMemory::plainText(getenv('KEYCLOAK_PUBLIC_KEY_FILE'))),
// You could also use this line if you do not want to use a separate public key file
// new SignedWith($jwt->buildSigner(Jwt::RS256), InMemory::plainText(KeycloakHelper::publicKeyFromIssuer(getenv('KEYCLOAK_ISSUER_URL')))),
new IssuedBy(getenv('KEYCLOAK_ISSUER_URL')),
new LooseValidAt(SystemClock::fromUTC()),
];
}
]
]
];
use Da\User\Controller\RegistrationController;
use ActionEvent;
return [
'modules' => [
'user' => [
'controllerMap' => [
'registration' => [
'class' => RegistrationController::class,
'on ' . RegistrationController::EVENT_BEFORE_ACTION => function (ActionEvent $event) {
if ($event->action->id === 'connect') {
// You may need to change the form id but this is the default
$event->action->controller->view->registerJs('if ($(".has-error").length === 0){$("form#User").submit()};');
}
}
]
]
]
]
]
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.