The Laravel Blog API uses custom middleware to protect endpoints that require authentication. The ApiAuthMiddleware validates JWT tokens before allowing access to protected routes.
ApiAuthMiddleware implementation
The middleware checks for a valid JWT token in the Authorization header:
app/Http/Middleware/ApiAuthMiddleware.php
class ApiAuthMiddleware
{
public function handle ( $request , Closure $next ) {
$token = $request -> header ( 'Authorization' );
$jwtAuth = new \ JwtAuth ();
$checkToken = $jwtAuth -> checkToken ( $token );
if ( $checkToken ) {
return $next ( $request );
}
else {
$data = array (
'code' => 400 ,
'status' => 'error' ,
'message' => 'El usuario no esta identificado.'
);
return response () -> json ( $data , $data [ 'code' ]);
}
}
}
How it works
Extract token
The middleware retrieves the JWT token from the Authorization header: $token = $request -> header ( 'Authorization' );
Validate token
It uses the JwtAuth helper to validate the token: $jwtAuth = new \ JwtAuth ();
$checkToken = $jwtAuth -> checkToken ( $token );
Allow or deny
If valid, the request proceeds. If invalid, it returns a 400 error: if ( $checkToken ) {
return $next ( $request ); // Continue to controller
}
else {
return response () -> json ([
'code' => 400 ,
'status' => 'error' ,
'message' => 'User is not authenticated.'
], 400 );
}
The middleware is registered in your application as api.auth and can be applied to routes or controllers.
Applying middleware to controllers
You can apply middleware in the controller constructor to protect specific methods:
PostController
CategoryController
The PostController protects write operations while allowing public read access: app/Http/Controllers/PostController.php
public function __construct () {
$this -> middleware ( 'api.auth' , [ 'except' => [
'index' ,
'show' ,
'getImage' ,
'getPostsByCategory' ,
'getPostsByUser' ,
]]);
}
Protected endpoints (require authentication):
store() - Create new post
update() - Update existing post
destroy() - Delete post
upload() - Upload post image
Public endpoints (no authentication):
index() - List all posts
show() - Get single post
getImage() - Retrieve post image
getPostsByCategory() - List posts by category
getPostsByUser() - List posts by user
The CategoryController has a similar pattern: app/Http/Controllers/CategoryController.php
public function __construct () {
$this -> middleware ( 'api.auth' , [ 'except' => [ 'index' , 'show' ]]);
}
Protected endpoints (require authentication):
store() - Create new category
update() - Update category
Public endpoints (no authentication):
index() - List all categories
show() - Get single category
Routes not listed in the except array will require valid JWT authentication.
Using middleware in protected methods
Once a route passes middleware validation, you can safely extract user information from the token:
app/Http/Controllers/PostController.php
public function store ( Request $request ) {
// Get authenticated user from token
$jwtAuth = new JwtAuth ();
$token = $request -> header ( 'Authorization' , null );
$user = $jwtAuth -> checkToken ( $token , true );
// Create post with user ID from token
$post = new Post ();
$post -> user_id = $user -> sub ;
$post -> category_id = $params -> category_id ;
$post -> title = $params -> title ;
$post -> content = $params -> content ;
$post -> image = $params -> image ;
$post -> save ();
}
Helper method for getting user identity
Many controllers use a helper method to extract user identity:
app/Http/Controllers/PostController.php
private function getIdentity ( Request $request ) {
$jwtAuth = new JwtAuth ();
$token = $request -> header ( 'Authorization' , null );
$user = $jwtAuth -> checkToken ( $token , true );
return $user ;
}
// Usage in controller methods
public function update ( $id , Request $request ) {
$user = $this -> getIdentity ( $request );
// Ensure user can only update their own posts
$post = Post :: where ( 'id' , $id )
-> where ( 'user_id' , $user -> sub )
-> first ();
if ( ! empty ( $post )) {
$post -> update ( $params_array );
}
}
This pattern ensures users can only modify their own content.
Authorization patterns
The API implements owner-based authorization:
Update post (owner only)
Delete post (owner only)
public function update ( $id , Request $request ) {
$user = $this -> getIdentity ( $request );
// Only fetch posts belonging to authenticated user
$post = Post :: where ( 'id' , $id )
-> where ( 'user_id' , $user -> sub )
-> first ();
if ( ! empty ( $post ) && is_object ( $post )) {
$post -> update ( $params_array );
}
}
Why use user_id in queries?
By including ->where('user_id', $user->sub) in queries, the API ensures:
Users can only update or delete their own posts
Prevents unauthorized access to other users’ content
No additional authorization logic needed
Database-level security
Error responses
When authentication fails, the middleware returns a consistent error response:
{
"code" : 400 ,
"status" : "error" ,
"message" : "El usuario no esta identificado."
}
Common authentication failures:
Missing token
Invalid token
Expired token
Request sent without Authorization header: curl -X POST "https://api.example.com/api/post"
# Returns 400 error
Token is malformed or tampered with: curl -X POST "https://api.example.com/api/post" \
-H "Authorization: invalid.jwt.token"
# Returns 400 error
Token is older than 7 days: curl -X POST "https://api.example.com/api/post" \
-H "Authorization: expired_token_here"
# Returns 400 error
Manual token validation
Some controllers manually validate tokens instead of using middleware:
app/Http/Controllers/UserController.php
public function update ( Request $request ) {
$token = $request -> header ( 'Authorization' );
$jwtAuth = new \ JwtAuth ();
$checkToken = $jwtAuth -> checkToken ( $token );
if ( $checkToken ) {
// Process update
$user = $jwtAuth -> checkToken ( $token , true );
$user_update = User :: where ( 'id' , $user -> sub ) -> update ( $params_array );
}
else {
$data = array (
'code' => 400 ,
'status' => 'error' ,
'message' => 'El usuario no esta identificado.'
);
return response () -> json ( $data , $data [ 'code' ]);
}
}
Using middleware in the constructor is preferred over manual validation as it’s more maintainable and follows Laravel conventions.
Testing protected endpoints
To test protected endpoints, you need a valid JWT token:
Login to get token
curl -X POST "https://api.example.com/api/user/login" \
-H "Content-Type: application/json" \
-d '{"json":"{\"email\":\"[email protected] \",\"password\":\"password123\"}"}'
Copy the JWT token
The response will contain your JWT token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
Use token in requests
curl -X POST "https://api.example.com/api/post" \
-H "Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{"json":"{\"title\":\"My Post\",\"content\":\"Content here\"}"} '
Next steps
Authentication Deep dive into JWT token generation and validation
Protected endpoints Explore endpoints that require authentication