I am creating a simple social media project to familiarize myself with JWT interaction in programs. My front end is Angular 6 and my Backend consists of PHP and MySql running on XAMPP (localhost server). It had been going pretty well for me until I hit a snag with a JWT interceptor in my frontend. The goal of the interceptor is to append the JWT in storage with each api call in the Authorization header. It is doing all of this, however it seems to invalidate the object being sent over to the server side code. (I should also note that all of my server side code works as it should when testing via postman.)
Here is the code for my interceptor:
import { HttpInterceptor, HttpRequest, HttpEvent, HttpHandler } from
"@angular/common/http";
import { Observable } from "rxjs";
export class JwtInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next:HttpHandler): Observable<HttpEvent<any>> {
//intercepts any outgoing http request to add the jwt token to the header if it exists. else do not (server will handle if it is not included).
const token = JSON.parse(localStorage.getItem('token'));
if (token) {
const cloned = request.clone({
headers: request.headers.set("Authorization",
"Bearer " + token)
});
return next.handle(cloned);
}
return next.handle(request);
}
}
Here is the server side php code that picks up the request: LoginUser.php
<?php
// required headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-
Headers, Authorization, X-Requested-With");
// includes to access the data we want to.
include_once '../config/Database.php';
include_once '../models/User.php';
// connect to the database.
$database = new Database();
$conn = $database->connect();
// create an instance of a user object.
$user = new User($conn);
// get the posted data
$data = json_decode(file_get_contents("php://input"));
$user->username = $data->username; // where I am getting an error message.
$user_exists = $user->userExists();
// generate json web token
include_once '../config/core.php';
include_once '../libs/php-jwt-master/src/BeforeValidException.php';
include_once '../libs/php-jwt-master/src/ExpiredException.php';
include_once '../libs/php-jwt-master/src/SignatureInvalidException.php';
include_once '../libs/php-jwt-master/src/JWT.php';
use \Firebase\JWT\JWT;
// verify user exists and the password is correct.
if($user_exists && password_verify($data->password , $user->password)){
$token = array (
"iss" => $iss,
"aud" => $aud,
"iat" => $iat,
"nbf" => $nbf,
"exp" => $exp,
"data" => array(
"username" => $user->username,
"accessLevel" => $user->accessLevel,
"email" => $user->email,
"isVerified" => $user->isVerified
)
);
// set the response
http_response_code(200);
// generate the jwt
$jwt = JWT::encode($token, $key);
echo json_encode(
array(
"message" => "Successful login.",
"jwt" => $jwt
)
);
}
else {
// set response code
http_response_code(401);
// tell the user login failed
echo json_encode(array("message" =>"Incorrect Login information." ));
echo json_encode(array("api call input" => $data));
}
Sending through the request as is returns the following console output:
Access to XMLHttpRequest at 'http://localhost/MySocialMedia/api/LoginUser.php' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
and when i go to look at the network response, this is the result:
<br />
<b>Notice</b>: Trying to get property 'username' of non-object in
<b>C:\xampp\htdocs\MySocialMedia\api\LoginUser.php</b> on line <b>26</b><br />
{"message":"Incorrect Login information."}{"api call input":null}
(for purposes of this example, the second echo response which is currently reporting null echos back json_encode($data).)
Based on this behavior, I would be quick to assume that I am just not preparing the post request correctly to begin with, however when I modified the interceptor to just handle the request without cloning or adding the bearer token, I get the expected output:
{"message":"Incorrect Login information."}{"api call input":{"username":"incorrectAccount","password":"incorrectPassword"}}
From the earlier error message I assumed it might have something to do with the CORS policy on the server side, however I have Authorization set in the header, however, I don't understand how this could be the issue either; in postman I am able to append an authorization header and still get expected behavior. All this leads me to believe that the problem must be occurring within the interceptor after it appends the bearer token, however I haven't been able to figure out exactly what is going wrong.
Any help would be greatly appreciated!
Also, if this may be of any extra help, I had the console log out what the request and the cloned request looked like. Aside from the cloned request having a mapped array of "authorization" => (my jwt here), they appeared exactly the same.
Comments
Post a Comment