<?php
namespace App\Controller\Admin;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Pimcore\Controller\FrontendController;
use Pimcore\Bundle\AdminBundle\HttpFoundation\JsonResponse;
use Pimcore\Tool;
use Pimcore\Tool\Session;
use Pimcore\Tool\Authentication;
use App\Helper\APIHelper;
use App\Helper\LogHelper;
use App\Model\Admin;
use Defuse\Crypto\Crypto;
use App\Services\AppLogService;
use App\Services\AuthenService;
/**
* @Route("/auth-admin")
* @Template
*/
class AuthController extends FrontendController
{
CONST URL_TENANT_ID_KEY = '<tenant-id>';
public function loginSuccess($user)
{
Session::get()->unlock();
Session::get()->set('user', $user);
AuthenService::checkOneSession($user, Session::getSessionId());
AppLogService::insert('Login', [
'pimcoreAdmin' => $user
]);
return $this->redirectToRoute("pimcore_admin_login");
}
public function loginFail($error)
{
$error = 'Login failure!';
return $this->redirectToRoute("auth-admin-login", ['error' => $error]);
}
/**
* @Route("/login", name="auth-admin-login")
*/
public function loginAction(
Request $request
)
{
$error = $request->get('error');
$username = '';
try {
$adminUser = Session::get()->get('user');
if ($adminUser) {
return $this->redirectToRoute("pimcore_admin_login");
}
if ($request->get('id')) {
$token = $request->get('id');
$secret = getenv('APP_PARAMETERS_SECRET');
$decrypted = Crypto::decryptWithPassword($token, $secret);
$decrypted = explode('|', $decrypted);
list($timestamp, $username) = $decrypted;
$user = \Pimcore\Model\User::getByName($username);
if ($user) {
if ($user->getActive()) {
return $this->loginSuccess($user);
}
}
AppLogService::insert('Login', [
'error' => [],
'username' => $username
], 400, AppLogService::FAILED);
return $this->loginFail($error);
} else {
if ($request->getMethod() == Request::METHOD_POST) {
$username = $request->get('username');
$password = $request->get('password');
$adminUser = Authentication::authenticatePlaintext($username, $password);
if ($adminUser) {
return $this->loginSuccess($adminUser);
} else {
$error = "Null account or error password or deactive!";
}
}
}
} catch (\Throwable $e) {
$error = "Login failure!";
}
if ($error) {
AppLogService::insert('Login', [
'error' => $error,
'username' => $username
], 400, AppLogService::FAILED);
}
return [
'error' => $error ? 'Login failure!' : ''
];
}
/**
* @Route("/connect-azure", name="auth-admin-connect-azure")
*/
public function connectAzureAction()
{
$redirectUrl = getenv('AZURE_URL_LOGIN') ."/". getenv('AZURE_TENANT'). getenv('AZURE_PATH_AUTHORIZE');
$redirectUrl .= '?app=SGPlatform';
$params = [
'client_id' => getenv('AZURE_SSO_CLIENT_ID'),
'redirect_uri' => $this->getCurrentDomain() . '/auth-admin/check-azure',
'response_type' => getenv('AZURE_RESPONSE_TYPE'),
'scope' => getenv('AZURE_SSO_SCOPE'),
'state' => $this->randString(),
'response_mode' => getenv('AZURE_RESPONSE_MODE')
];
foreach ($params as $field => $value) {
$redirectUrl .= '&'. $field .'='. $value;
}
return $this->redirect($redirectUrl);
}
/**
* @Route("/check-azure", name="auth-admin-check-azure")
*/
public function checkAzureAction(
Request $request,
Admin $adminModel
)
{
$method = 'POST';
$url = str_replace(self::URL_TENANT_ID_KEY, getenv('AZURE_TENANT'), getenv('AZURE_URL_GET_TOKEN'));
$headers = [
// 'Content-Type' => 'application/x-www-url-form-urlencoded'
];
$body = [
'client_id' => getenv('AZURE_SSO_CLIENT_ID'),
'scope' => getenv('AZURE_SSO_SCOPE'),
'redirect_uri' => $this->getCurrentDomain() . '/auth-admin/check-azure',
'grant_type' => getenv('AZURE_GRANT_TYPE'),
'client_secret' => getenv('AZURE_SSO_CLIENT_SECRET'),
'code' => $request->get('code')
];
$response = APIHelper::callFormParams($method, $url, $headers, $body);
if ($response['status'] == 200) {
$tokenType = $response['response']['token_type'];
$accessToken = $response['response']['access_token'];
$authorization = $tokenType .' '. $accessToken;
$url = getenv('AZURE_URL_GET_PROFILE');
$headers = [
'Authorization' => $authorization
];
$response = APIHelper::callGET($url, $headers);
if ($response['status'] == 200) {
$admin = $adminModel->getAdmin($response['response']);
if ($admin) {
$userAdmin = $admin->getUser();
if ($userAdmin) {
$response['pimcoreAdmin'] = $userAdmin;
$user = \Pimcore\Model\User::getById($userAdmin);
if ($user->getActive()) {
$token = \Pimcore\Tool\Authentication::generateToken($user->getName());
AppLogService::insert('Login', $response);
return [
'token' => $token
];
}
}
}
AppLogService::insert('Login', $response, 400, AppLogService::FAILED);
return $this->loginFail("Login failure!");
} else {
$error = "Can access account from Azure AD";
if (array_key_exists('error', $response)) {
$error = $response['error'];
}
AppLogService::insert('Login', $response, 400, AppLogService::FAILED);
return $this->loginFail($error);
}
} else {
$error = "Can access account from Azure AD";
if (array_key_exists('error', $response)) {
$error = $response['error'];
}
AppLogService::insert('Login', $response, 400, AppLogService::FAILED);
return $this->loginFail($error);
}
}
/**
* @Route("/logout", name="auth-admin-logout")
*/
public function logoutAction(Request $request)
{
try {
$adminUser = Session::get()->get('user');
AppLogService::insert('Logout', [
'pimcoreAdmin' => $adminUser
]);
AuthenService::logoutSession($adminUser);
} catch (\Throwable $e) {}
Session::get()->unlock();
Session::get()->set('user', null);
return $this->redirectToRoute('auth-admin-login');
}
private function randString($length = 128) {
return bin2hex(random_bytes($length));
}
private function getCurrentDomain()
{
$domain = "https://". $_SERVER['HTTP_HOST'];
return $domain;
}
}