Source of file Authenticator.php
Size: 6,234 Bytes - Last Modified: 2021-12-24T06:33:55+00:00
/var/www/docs.ssmods.com/process/src/src/Controller/Authenticator.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 | <?php namespace Broarm\EventTickets\App\Controller; use Broarm\EventTickets\App\Model\Device; use Broarm\EventTickets\Forms\CheckInValidator; use Exception; use Firebase\JWT\JWT; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Environment; use SilverStripe\ORM\DataObject; use SilverStripe\Security\Member; use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator; use SilverStripe\Security\Permission; use SilverStripe\SiteConfig\SiteConfig; use UnexpectedValueException; /** * TicketValidator.php * * @author Bram de Leeuw * Date: 14/06/2017 */ class Authenticator extends Controller { const TYPE_ACCOUNT = 'ACCOUNT'; const VALIDATE_TICKET = 'eventtickets/validate'; const VALIDATE_TOKEN = 'eventtickets/authenticator/validatetoken'; private static $icon = 'favicon-152.png'; private static $validate_path = ''; private static $token_header = 'X-Authorization'; private static $jwt_alg = 'HS256';//'HS512'; private static $jwt_nbf_offset = 0; private static $jwt_exp_offset = 9000; private static $allowed_actions = array( 'authenticator', 'validateToken' ); /** * Handle the request * @param HTTPRequest $request * @return HTTPResponse * @throws Exception * @throws \ValidationException */ public function index(HTTPRequest $request) { $body = json_decode($request->getBody(), true); if ( isset($body['username']) && isset($body['password']) && isset($body['uniqueId']) ) { /** @var \Authenticator $authClass */ $auth = new MemberAuthenticator(); $member = $auth->authenticate(array( 'Email' => $body['username'], 'Password' => $body['password'], ), $request); if ($member && $member->exists()) { if (!Permission::check('HANDLE_CHECK_IN', 'any', $member)) { return new HTTPResponse(json_encode(array( 'message' => _t('TicketValidator.ERROR_USER_PERMISSIONS', 'You don’t have enough permissions to handle the check in.') )), 401); } $brand = isset($body['brand']) ? $body['brand'] : '-'; $model = isset($body['model']) ? $body['model'] : '-'; // find or create device and save token in it $device = Device::findOrMake($body['uniqueId'], $brand, $model); // create the token $tokenData = array( 'iat' => $issuedAt = time(), 'jti' => $device->ID, 'iss' => Director::absoluteBaseURL(), 'nbf' => $notBefore = $issuedAt + self::config()->get('jwt_nbf_offset'), 'exp' => $notBefore + self::config()->get('jwt_exp_offset'), 'data' => [ 'memberId' => $member->ID, 'deviceId' => $device->ID ] ); $token = JWT::encode($tokenData, self::jwtSecretKey(), self::config()->get('jwt_alg')); $device->Token = $member->encryptWithUserSettings($token); $member->ScanDevices()->add($device); $siteConfig = SiteConfig::current_site_config(); return new HTTPResponse(json_encode(array( 'id' => $device->ID, 'name' => $member->getName(), 'type' => self::TYPE_ACCOUNT, 'title' => $siteConfig->Title, 'image' => Director::absoluteBaseURL() . self::config()->get('icon'), 'token' => $token, 'validatePath' => Controller::join_links(Director::absoluteBaseURL(), self::VALIDATE_TICKET), 'validateTokenPath' => Controller::join_links(Director::absoluteBaseURL(), self::VALIDATE_TOKEN) )), 200); } } return new HTTPResponse(json_encode(array( 'message' => _t('TicketValidator.ERROR_WRONG_AUTHENTICATION', 'Wrong username or password given.') )), 401); } /** * Authenticate by given JWT * * @param HTTPRequest $request * @return bool|SS_HTTPResponse * @throws Exception */ public static function authenticate(HTTPRequest $request) { if ($header = $request->getHeader(self::config()->get('token_header'))) { list($jwt) = sscanf($header, 'Bearer %s'); if (!empty($jwt)) { try { $decoded = JWT::decode($jwt, self::jwtSecretKey(), array(self::config()->get('jwt_alg'))); } catch (UnexpectedValueException $e) { return new HTTPResponse(json_encode(array( 'code' => CheckInValidator::MESSAGE_TYPE_BAD, 'message' => $e->getMessage() )), 401); } if ( ($device = DataObject::get_by_id(Device::class, $decoded->data->deviceId)) && ($member = DataObject::get_by_id(Member::class, $decoded->data->memberId)) ) { return $device->Token === $member->encryptWithUserSettings($jwt); } } }; return false; } /** * @todo refresh token when valid * * @param HTTPRequest $request * @return bool|HTTPRequest * @throws Exception */ public function validateToken(HTTPRequest $request) { return self::authenticate($request); } /** * Get the token or return an error response * @return mixed * @throws Exception */ private static function jwtSecretKey() { $key = Environment::getEnv('JWT_SECRET_KEY'); if (!$key) { throw new Exception(_t('TicketValidator.ERROR_SERVER_SETUP', 'The server is not set up properly, contact your site administrator.')); } return $key; } } |