Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialNick Girling
4,607 PointsAble to require authentication, but if not logged in, get white screen
Having some issues with authentication. I have required requireAuth() on some of the pages, and so if the user is logged in then they are able to see the file. However if the user is not logged in, instead of being redirected to /dev/ (last line of text), I just see a white sheet.
var_dumping() shows that isAuthenticated() is false if the user is not logged in and true if the user is logged in so I believe the part that is not working is the $accessToken. I have included a print_r() of the $accessToken to see if anyone knows what I am missing.
Any help is appreciated.
function isAuthenticated() {
if (!request()->cookies->has('access_token')) {
return false;
}
try {
\Firebase\JWT\JWT::$leeway = 1;
\Firebase\JWT\JWT::decode(
request()->cookies->get('access_token'),
getenv('SECRET_KEY'),
['HS256']
);
return true;
} catch (\Exception $e) {
echo "error is " . $e->getMessage();
}
}
function requireAuth() {
if(!isAuthenticated()) {
$accessToken = new \Symfony\Component\HttpFoundation\Cookie('access_token', 'Expired', time()-3600, '/dev/', getenv('COOKIE_DOMAIN'));
//print_r($accessToken);
redirect('/dev/',['cookies' => [$accessToken]]);
}
}
print_r($accessToken)
Symfony\Component\HttpFoundation\Cookie Object
(
[name:protected] => access_token
[value:protected] => Expired
[domain:protected] => localhost
[expire:protected] => 1490307817
[path:protected] => /dev/
[secure:protected] =>
[httpOnly:protected] => 1
[raw:Symfony\Component\HttpFoundation\Cookie:private] =>
[sameSite:Symfony\Component\HttpFoundation\Cookie:private] =>
)
Also here is the redirect()
function redirect($path, $extra = []) {
$response = \Symfony\Component\HttpFoundation\Response::create(null, \Symfony\Component\HttpFoundation\Response::HTTP_FOUND, ['Location' => $path]);
if (key_exists('cookies', $extra)) {
foreach ($extra['cookies'] as $cookie) {
$response->headers->setCookie($cookie);
}
}
$response->send();
exit;
}
I also noticed if I use the Symfony sessions (in the tutorial video after) I also get an error. Not sure if the problem is linked. It seems the problem is with the $session->start() method..
This is the code in my bootstrap.php file
require_once(__DIR__.'/../../vendors/vendor/autoload.php');
require_once('functions.php');
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
$session = new Symfony\Component\HttpFoundation\Session\Session();
try {
$session->start();
} catch(Exception $e) {
echo "getMessage() - ".$e->getMessage();
echo "<br>";
echo "getline() - " . $e->getLine();
echo "<br>";
echo "getCode() - " . $e->getCode();
echo "<br>";
echo "getFile() - " . $e->getFile();
echo "<br>";
echo "getTrace() - ".$e->getTrace();
echo "<br>";
echo "getTraceAsString() - ".$e->getTraceAsString();
}
And it outputs:
getMessage() - Failed to start the session because headers have already been sent by "/Users/Oli/Desktop/gripup/dev/login.php" at line 4.
getline() - 134
getCode() - 0
getFile() - /Users/Oli/Desktop/gripup/dev/vendors/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php
getTrace() - Array
getTraceAsString() - #0 /Users/Oli/Desktop/gripup/dev/vendors/vendor/symfony/http-foundation/Session/Session.php(71): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() #1 /Users/Oli/Desktop/gripup/dev/app/inc/bootstrap.php(12): Symfony\Component\HttpFoundation\Session\Session->start() #2 /Users/Oli/Desktop/gripup/dev/login.php(5): require_once('/Users/Oli/Desk...') #3 {main}
5 Answers
Alena Holligan
Treehouse TeacherI want to verify that your vendor folder in in Desktop/gripup/dev/ ?
login.php is where there error is coming from, can I see that file? is the bootstrap file included at there very top? should be line 2 right after <?php
Alena Holligan
Treehouse Teacheryou need to put the
<?php include("app/inc/html/header.php");
require_once('app/inc/bootstrap.php' );
BEFORE any HTML output, so BEFORE
<!DOCTYPE html>
<html lang="en">
Nick Girling
4,607 PointsThanks your right, not sure how i managed that. That fixes the errors showing up, but still stuck with this problem with redirect().
When I try to login I still get a blank page. I have even downloaded the files and replaced my functions with your functions and also the login page and doLogin. Sadly I am just getting a white screen.
I have included all the files i believe are involved in the login. Been trying all day to get my head round it but nothing. Any help would be really really appricated
login.php
require_once('app/inc/bootstrap.php' );
?>
<div class="main-body">
<div id="wrap">
<div class="container">
<?php
if (request()->cookies->has('access_token')) {
echo "<h2>You are already logged in</h2>";
}?>
<div class="well col-sm-6 col-sm-offset-3">
<form class="form-signin" method="post" action="app/inc/actions/doLogin.php">
<h2 class="form-signin-heading">Please sign in</h2>
<?php //print display_flash_error_success(); ?>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" name="email" class="form-control" placeholder="Email address" required autofocus>
<br>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required>
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
</div>
</div>
</div>
doLogin.php (within Users my user's id is called user_id, hence $user['user_id'] rather than $user['id'])
require __DIR__ .'/../bootstrap.php';
$user = findUserByEmail(request()->get('email'));
if (empty($user)) {
$session->getFlashBag()->add('error', 'Username was not found');
redirect('/login.php');
}
if (!password_verify(request()->get('password'), $user['password'])) {
$session->getFlashBag()->add('error', 'Invalid Password');
redirect('/login.php');
}
$expTime = time() + 7200;
$jwt = \Firebase\JWT\JWT::encode([
'iss' => request()->getBaseUrl(),
'sub' => "{$user['user_id']}",
'exp' => $expTime,
'iat' => time(),
'nbf' => time(),
'is_admin' => $user['role_id'] == 1
], getenv("SECRET_KEY"),'HS256');
$accessToken = new Symfony\Component\HttpFoundation\Cookie('access_token', $jwt, $expTime, '/', getenv('COOKIE_DOMAIN'));
$session->getFlashBag()->add('success', 'Successfully Logged In');
redirect('/dev/',['cookies' => [$accessToken]]);
bootstrap.php
require_once(__DIR__.'/../vendor/autoload.php');
require_once __DIR__ . '/functions.php';
require_once __DIR__ . '/connection.php';
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
$session = new \Symfony\Component\HttpFoundation\Session\Session();
$session->start();
?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="/app/inc/css/admin.css">
within functions.php
function redirect($path, $extra = []) {
$response = \Symfony\Component\HttpFoundation\Response::create(null, \Symfony\Component\HttpFoundation\Response::HTTP_FOUND, ['Location' => $path]);
if (key_exists('cookies', $extra)) {
//print_r($extra); (see below)
foreach ($extra['cookies'] as $cookie) {
//echo $cookie; (see below)
$response->headers->setCookie($cookie);
}
}
$response->send();
exit;
}
echo $cookie
ACCESS_TOKEN = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJcL2RldlwvYXBwXC9pbmNcL2FjdGlvbnNcL2RvTG9naW4ucGhwIiwic3ViIjoiOSIsImV4cCI6MTQ5MDczNjU0NiwiaWF0IjoxNDkwNzI5MzQ2LCJuYmYiOjE0OTA3MjkzNDYsImlzX2FkbWluIjpmYWxzZX0.AfMXIX8VqFU6zVAM36y6Sg_SrRHTRHplJ8Op0yOv-J4; expires = Thu, 28-Mar-2017 9:29:06 p.m. GMT; path = /; domain = localhost; httponly
print_r($extra)
Array
(
[cookies] => Array
(
[0] => Symfony\Component\HttpFoundation\Cookie Object
(
[name:protected] => access_token
[value:protected] => eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJcL2RldlwvYXBwXC9pbmNcL2FjdGlvbnNcL2RvTG9naW4ucGhwIiwic3ViIjoiOSIsImV4cCI6MTQ5MDczNjc2NSwiaWF0IjoxNDkwNzI5NTY1LCJuYmYiOjE0OTA3Mjk1NjUsImlzX2FkbWluIjpmYWxzZX0.RZSjXnxV96KGvDlGS_yEl_JfCZ6uS7bijPGwU604CZA
[domain:protected] => localhost
[expire:protected] => 1490736765
[path:protected] => /
[secure:protected] =>
[httpOnly:protected] => 1
[raw:Symfony\Component\HttpFoundation\Cookie:private] =>
[sameSite:Symfony\Component\HttpFoundation\Cookie:private] =>
)
)
)
Here is an updated structure
Alena Holligan
Treehouse Teacherdoes it show "login.php" in the url for the blank page?
Do you have all errors turned on? https://teamtreehouse.com/library/basic-error-handling-in-php
Can you echo something at the VERY top of the login.php page?
Nick Girling
4,607 PointsOnce I enter the correct or incorrect details and click login, the url changes to http://localhost:8888/dev/app/inc/actions/doLogin.php (which it should), but is blank.
Yes all errors are turned all.
The login.php page is ok I believe. It loads an echo at the top and the bottom of the page.
If I use the correct login info, when I login and add an echo to doLogin.php (like below), it does echo "test". I have also var_dumped the $accessToken below. If i enter the information in incorrectly, so it should redirect to the login.php page in either of the first 2 if statements, then it again still is a blank screen and is stuck on the doLogin.php page. So it seems like the trouble is with the redirect.
require __DIR__ .'/../bootstrap.php';
$user = findUserByEmail(request()->get('email'));
if (empty($user)) {
$session->getFlashBag()->add('error', 'Username was not found');
redirect('/login.php');
}
if (!password_verify(request()->get('password'), $user['password'])) {
$session->getFlashBag()->add('error', 'Invalid Password');
redirect('/login.php');
}
$expTime = time() + 7200;
$jwt = \Firebase\JWT\JWT::encode([
'iss' => request()->getBaseUrl(),
'sub' => "{$user['user_id']}",
'exp' => $expTime,
'iat' => time(),
'nbf' => time(),
'is_admin' => $user['role_id'] == 1
], getenv("SECRET_KEY"),'HS256');
$accessToken = new Symfony\Component\HttpFoundation\Cookie('access_token', $jwt, $expTime, '/', getenv('COOKIE_DOMAIN'));
var_dump($accessToken);
$session->getFlashBag()->add('success', 'Successfully Logged In');
echo "test";
redirect('/dev/',['cookies' => [$accessToken]]);
var_dump($accessToken);
object(Symfony\Component\HttpFoundation\Cookie)#19 (9) {
["name":protected]=>
string(12) "access_token"
["value":protected]=>
string(248) "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJcL2RldlwvYXBwXC9pbmNcL2FjdGlvbnNcL2RvTG9naW4ucGhwIiwic3ViIjoiOSIsImV4cCI6MTQ5MDgxNTQ5NSwiaWF0IjoxNDkwODA4Mjk1LCJuYmYiOjE0OTA4MDgyOTUsImlzX2FkbWluIjpmYWxzZX0.52bhrFjlWDLtJbagQRENO7sMOV5agiXaMz341s6-KAg"
["domain":protected]=>
string(9) "localhost"
["expire":protected]=>
int(1490815495)
["path":protected]=>
string(1) "/"
["secure":protected]=>
bool(false)
["httpOnly":protected]=>
bool(true)
["raw":"Symfony\Component\HttpFoundation\Cookie":private]=>
bool(false)
["sameSite":"Symfony\Component\HttpFoundation\Cookie":private]=>
NULL
}
test
Nick Girling
4,607 PointsRight, I have worked it out.
I re-created all the files and it seems to be working. Not sure if there was a trailing white space or if the html within the bootstrap file (even though it was after the ending php tag):
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="/app/inc/css/admin.css">
Thanks so much for your help! Seems this time it was a silly annoying issue, but I have learnt a lot debugging this one.
Alena Holligan
Treehouse TeacherGreat job! Debugging is a valuable skill for any developer :) I'm hoping to put together a specific debugging course in the not too distant future :)
Nick Girling
4,607 PointsNick Girling
4,607 PointsNo its not, the vendor file is within the vendors folder (Desktop/gripup/dev/vendors/vendor). This is being made locally on phpStorm and this is where it installed the folder for some reason. I could try and remove this and manually install composer into another directory. I have also just noticed there is a composer.phar file within dev/app/inc/ and the vendor folder is within dev/vendors/vendor. Not sure if thats normal.
Are you sure its login.php? Because with my bootstrap.php file throwing these errors, I can see exactly the same error being thrown on register.php but it says
getMessage() - Failed to start the session because headers have already been sent by "/Users/Oli/Desktop/gripup/dev/register.php" at line 4.
Here is an image to show its layout. The dev/ part is the main home page with front end website. The app/ part is where I was planning on having the web app.
here is login.php