Extending Authenticate¶
Storage¶
We provide a Session Storage type as default method to manage your user's status and other data. However you can choose a different storage like database, filesystem or memcached just mention few.
In order to create your own storage service, you will have to create a class that implements erdiko\authenticate\StorageInterface
like:
Class SessionStorage implements StorageInterface {
public function persist(UserStorageInterface $user)
{
$this->startSession();
$_SESSION["current_user"] = $user->marshall();
}
public function attemptLoad(UserStorageInterface $userModel)
{
$user = null;
$sapi = php_sapi_name();
if(!$this->contains('cli', $sapi)){
$this->startSession();
}
if(array_key_exists("current_user", $_SESSION)){
$_user = $_SESSION["current_user"];
if(!empty($_user)){
$user = $userModel::unmarshall($_user);
}
}
return $user;
}
public function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
public function destroy()
{
$this->startSession();
if(array_key_exists("current_user", $_SESSION)){
unset($_SESSION["current_user"]);
}
@session_destroy();
}
private function startSession()
{
if(!file_exists(ERDIKO_VAR . "/session")) {
mkdir(ERDIKO_VAR . "/session");
}
ini_set('session.save_path',ERDIKO_VAR . "/session");
if(session_id() == '') {
@session_start();
} else {
if (session_status() === PHP_SESSION_NONE) {
@session_start();
}
}
}
}
and edit your authenticate.json
config by adding new item in the storage section and put it as selected
{
"storage": {
"selected": "custom",
"storage_types": [{
"name": "session",
"namespace": "erdiko_authenticate_services",
"classname": "SessionStorage",
"enabled": true
},
{
"name": "custom",
"namespace": "app_lib_authenticate_services",
"classname": "CustomStorage",
"enabled": true
}]
}
}
Authentication types¶
As we mention before, here we need to split in two, authentication and authenticator.
Let's start with __authentication, here we will create class that implements _AuthenticationInterface where
we will put the custom user's validation logic, no matter if it's just a return true
, and LDAP call or any other
crazy algorithm.
Same as we did with storage, we need to add this new class in the authenticate.json
within the available_types
section.
{
"authentication": {
"available_types": [{
"name": "jwt_auth",
"namespace": "erdiko_authenticate_services",
"classname": "JWTAuthentication",
"enabled": true
},
{
"name": "custom_auth",
"namespace": "app_lib_authenticate_services",
"classname": "CustomAuthentication",
"enabled": true
}]
}
}
The last step is create an authenticator class that implements AuthenticatorInterface. This class is the one you will use in your app to preform the actual login process.
Within this class you will use previous defined tools to authenticate and store data, based on configuration file. Here's an example of login method:
public function login($credentials = array(), $type = 'jwt_auth')
{
$storage = $this->container["STORAGES"][$this->selectedStorage];
$result = false;
// checks if it's already logged in
$user = $storage->attemptLoad($this->erdikoUser);
if($user instanceof UserStorageInterface) {
$this->logout();
}
$auth = $this->container["AUTHENTICATIONS"][$type];
$result = $auth->login($credentials);
if(isset($result->user))
$user = $result->user;
else
throw new \Exception("User failed to load");
if(!empty($user) && (false !== $user)) {
$this->persistUser( $user );
$response = true;
}
return $result;
}
Of course is your choice what method implement, for example, you can opt to skip persistUser
if you want to use client
side cookie instead of session or any other method on the server side. Said that, we encourage you to implement
persistUser
method like this:
public function persistUser(UserStorageInterface $user)
{
$this->generateTokenStorage($user);
}
public function generateTokenStorage(UserStorageInterface $user)
{
$entityUser = $user->getEntity();
$userToken = new UsernamePasswordToken($entityUser->getEmail(),$entityUser->getPassword(),'main',$user->getRoles());
$_SESSION['tokenstorage'] = $userToken;
}
It will give you the chance to interconnect your authenticated user with other packages like erdiko/authorize
or any
Symfony/Security
.