简体   繁体   中英

Is there any way to change response of auth:api , A laravel api_token

I am creating API with Default api-authentication

I am using laravel 6.x

Its run when i generate on user register and pass generated token with request.

But

  1. when i pass a wrong token, Then it shows a Login page HTML, i want to show some custom JSON response instead of HTML
  2. Also is there any way to check that passed token is same with passed user id or not. Because user can pass different user id with token.

My api route file as below

Route::middleware('auth:api')->post('/listUser', 'ApiController@listUser');

I have manage my points as below

For Point 1

  1. when i pass a wrong token, Then it shows a Login page HTML, i want to show some custom JSON response instead of HTML

I made change in App/Exceptions/handler.php

Modify render function as below

public function render($request, Exception $exception)
{
    if ($exception instanceof NotFoundHttpException) {
        if ($request->is('api/*')) {
            return response()->json(['error' => 'Not Found'], 404);
        }
        //return response()->view('404', [], 404);
    }
    return parent::render($request, $exception);
}

It workrs well because i have an api based routes

My api route look likes

// Request with Authentication v1

Route::group(['prefix' => 'v1', 'namespace' => 'Api\v1', 'middleware' => ['api','auth:api'] ], function () {

  Route::post('/myProfile', 'ApiController@myProfile');

});

// Request without Authentication v1
Route::group(['prefix' => 'v1', 'namespace' => 'Api\v1', 'middleware' => 'api'], function () {
  Route::post('/register', 'ApiController@register');

});

For Point 2

  1. Also is there any way to check that passed token is same with passed user id or not. Because user can pass different user id with token.

For that i have created a function checkValidations in ApiController and check user id is associated with particular token or not as below:

In that function i check in way that

  1. Check for all validation passed from called method
  2. Match token associated with user id then return success
  3. else return invalid token response

Function Code

public function checkValidations($required = [], $request = [])
{
    $validator = Validator::make($request->all(), $required);
    if ($validator->fails()) {
         $this->response[] = array(
                'status' => 'false',
                'response_msg' => implode(",",$validator->messages()->all()),
            );
         return array('response' => $this->response);
    } else if(isset($request['api_token']) && auth('api')->user()->id == 
         $request['id']) {
        return 'success';
    } else {
        $this->response[] = array(
                'status' => 'false',
                'response_msg' => 'Invalid token',
            );
         return array('response' => $this->response);
    }
}

And call that checkValidations from any function and can reuse it as

public function myProfile(Request $request)
{
    $validation = [
           'id' => 'bail|required|exists:users',
           'api_token' => 'bail|required|min:60|max:60'
     ];
    if( $this->checkValidations($validation, $request) == 'success'){
            $this->response[] = array(
                    'status' => 'true',
                    'response_msg' => 'Success',
                            'data' => auth('api')->user()
                );
    }

    return array('response' => $this->response);

}

May be there is many other best way to manage that points, but i didn't found, so i manage in above ways.

  1. You can configure a custom response in the Authenticate middleware. eg

    public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->guest()) { if ($guard === 'api') { return response('Unauthorized.', 401); } else { return redirect()->guest('login'); } } return $next($request); }
  2. You can do this by extending the TokenGuard , with your custom logic. Or you can create a new Middleware, which asserts that user authenticated by API matches the passed user ID.

I just verified the kind of exception if is related with authentication and then the URL( as API guard use '/api' just verify it) and fire the response.

if($exception instanceof \Illuminate\Auth\AuthenticationException){
            if($request->is('api/*')){
                return response()->json([
                    'success' => false,
                    'message' => 'User not logged'
                ]);
            }
        }

I made the below change in app/Exceptions/Handler.php .

protected function unauthenticated($request, AuthenticationException $exception)
{
    if ($request->expectsJson()) {
        return response()->json(['error' => 'Not Authorized'], 404);
    }

    return redirect()->guest(route('login'));
}

Add use Illuminate\Auth\AuthenticationException in the document. Also, do not forget to add X-Requested-With:XMLHttpRequest to your request header. (Or Headers in postman)

return redirect()->guest(route('login')); is to redirect you to login page when you are not using the APIs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM