Introduction

JSON Web Tokens (JWT) are quickly becoming a great way of authorising users to perform certain actions but a lot of things can go wrong as well in the implementation. We are going to build a JWT lab that does not check if the signature is valid but not before we give you an overview of what a JWT token looks like.

Make a connection

THE SERVER GETS ERASED EVERY 24 HOURS

Let's create a way of generating JWT tokens

add the following code to your file:

 <?php

include('instructions.php');

function generate_jwt($headers, $payload, $secret = 'secret', $encoding = 'SHA256') {
	$headers_encoded = base64url_encode(json_encode($headers));
	$payload_encoded = base64url_encode(json_encode($payload));
	$signature = hash_hmac('SHA256', "$headers_encoded.$payload_encoded", $secret, true);
	$signature_encoded = base64url_encode($signature);
	$jwt = "$headers_encoded.$payload_encoded.$signature_encoded";
	return $jwt;
}

function base64url_encode($str) {
    return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
}

function is_jwt_valid($jwt, $secret = 'secret') {
	// split the jwt
	$tokenParts = explode('.', $jwt);
	$header = base64_decode($tokenParts[0]);
	$payload = base64_decode($tokenParts[1]);
	$signature_provided = $tokenParts[2];

	// check the expiration time - note this will cause an error if there is no 'exp' claim in the jwt
	$expiration = json_decode($payload)->exp;
	$is_token_expired = ($expiration - time()) < 0;

	// build a signature based on the header and payload using the secret
	$base64_url_header = base64url_encode($header);
	$base64_url_payload = base64url_encode($payload);
	$signature = hash_hmac('SHA256', $base64_url_header . "." . $base64_url_payload, $secret, true);
	$base64_url_signature = base64url_encode($signature);

	// verify it matches the signature provided in the jwt
	$is_signature_valid = ($base64_url_signature === $signature_provided);
	
	if ($is_token_expired || !$is_signature_valid) {
		return FALSE;
	} else {
		return TRUE;
	}
}

function getBody($jwt,$secret = 'secret'){
	// split the jwt
	$tokenParts = explode('.', $jwt);
	$header = base64_decode($tokenParts[0]);
	$payload = base64_decode($tokenParts[1]);
	$signature_provided = $tokenParts[2];
	is_jwt_valid($jwt,$secret);
		
	return $payload;
	
}

function getFlag($jwt){
	$body = json_decode(getBody($jwt));
	if($body->canViewFlag=="True"){
		echo "Good job!! The flag is flag{1_L0v#3_Ch33s3!}";
	}else{
		echo "You can not read the flag";
	}
}

$headers = array('alg'=>'HS256','typ'=>'JWT');
$payload = array('canViewFlag' => "False", 'exp'=>(time() + 60));

$jwt = generate_jwt($headers, $payload);

header("Authorization: Bearer $jwt");

echo "The server gave you the following JWT: <br> $jwt";
echo "<hr>";

?>

<form>
  <label for="JWT">Your JWT:</label><br>
  <input type="text" id="JWT" name="JWT"><br>
  <input type="submit"> 
</form>

<?php

if(isset($_GET['JWT'])){
	echo getFlag($_GET['JWT']);
}

?>

Let's hack it

Let's secure it