1

I'm using dingo/api (that has built-in support for jwt-auth) to make an API.

Suppose this is my routes :

$api->group(['prefix' => 'auth', 'namespace' => 'Auth'], function ($api) {
            $api->post('checkPhone', 'LoginController@checkPhone');

            //Protected Endpoints
            $api->group(['middleware' => 'api.auth'], function ($api) {
                $api->post('sendCode', 'LoginController@sendCode');
                $api->post('verifyCode', 'LoginController@verifyCode');

            });
        });

checkPhone method that has task of authorize and creating token is like :

public function checkPhone (Request $request)
        {
            $phone_number = $request->get('phone_number');
            if (User::where('phone_number', $phone_number)->exists()) {

                $user = User::where('phone_number', $phone_number)->first();

                $user->injectToken();

                return $this->response->item($user, new UserTransformer);

            } else {
                return $this->response->error('Not Found Phone Number', 404);
            }
        }

And injectToken() method on User Model is :

public function injectToken ()
        {
            $this->token = JWTAuth::fromUser($this);
            return $this;
        } 

Token creation works fine.

But When I send it to a protected Endpoint, always Unable to authenticate with invalid token occures.

The protected Endpoint action method is :

public function verifyCode (Request $request)
        {
            $phone_number = $request->get('phone_number');
            $user_code    = $request->get('user_code');

            $user = User::wherePhoneNumber($phone_number)->first();

            if ($user) {
                $lastCode = $user->codes()->latest()->first();

                if (Carbon::now() > $lastCode->expire_time) {
                    return $this->response->error('Code Is Expired', 500);
                } else {
                    $code = $lastCode->code;

                    if ($user_code == $code) {

                        $user->update(['status' => true]);

                        return ['success' => true];
                    } else {
                        return $this->response->error('Wrong Code', 500);
                    }
                }
            } else {
                return $this->response->error('User Not Found', 404);
            }
        }

I used PostMan as API client and send generated tokens as a header like this :

Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI5ODkxMzk2MTYyNDYiLCJpc3MiOiJodHRwOlwvXC9hcGkucGFycy1hcHAuZGV2XC92MVwvYXV0aFwvY2hlY2tQaG9uZSIsImlhdCI6MTQ3NzEyMTI0MCwiZXhwIjoxNDc3MTI0ODQwLCJuYmYiOjE0NzcxMjEyNDAsImp0aSI6IjNiMjJlMjUxMTk4NzZmMzdjYWE5OThhM2JiZWI2YWM2In0.EEj32BoH0URg2Drwc22_CU8ll--puQT3Q1NNHC0LWW4

I Can not find solution after many search on the web and related repositories.

What is Problem in your opinion?

Update :

I found that not found error is for constructor of loginController that laravel offers :

public function __construct ()
        {
            $this->middleware('guest', ['except' => 'logout']);
        }

because when I commented $this->middleware('guest', ['except' => 'logout']); all things worked. But if I remove this line is correct? How should be this line for APIs?

Ahmad Badpey
  • 6,348
  • 16
  • 93
  • 159
  • $api->version('v1', ['middleware' => 'api.auth'], function ($api) { $api->get('user', function () { $user = app('Dingo\Api\Auth\Auth')->user(); return $user; }); }); check authenticated users like this – Jagadesha NH Oct 22 '16 at 10:18
  • @Jagadesha NH, I tried it and error `Failed to authenticate because of bad credentials or an invalid authorization header` occurred. – Ahmad Badpey Oct 22 '16 at 10:36
  • https://github.com/dingo/api/issues/325 https://github.com/tymondesigns/jwt-auth/issues/16 check these links – Jagadesha NH Oct 22 '16 at 10:50
  • I added `RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]` to htaccess, but when sent requests to protected endpoint `404 Not Found` error occures. – Ahmad Badpey Oct 22 '16 at 11:16
  • @Jagadesha NH, I found that Handle Authorization Header was in .htaccess file of latest version on laravel(5.3.19) so does not need to add it too again. but problem not solved yet – Ahmad Badpey Oct 22 '16 at 13:02

3 Answers3

1

updating my config/api.php to this did the trick

// config/api.php
...
  'auth' => [
        'jwt' => 'Dingo\Api\Auth\Provider\JWT'
    ],
...
Cengkuru Michael
  • 4,590
  • 1
  • 33
  • 33
0

As I mentioned earlier as an Update note problem was that I used checkPhone and verifyCode in LoginController that has a check for guest in it's constructor.

And because guest middleware refers to \App\Http\Middleware\RedirectIfAuthenticated::class and that redirects logged in user to a /home directory and I did not created that, so 404 error occured.

Now just I moved those methods to a UserController without any middleware in it's constructor.

Ahmad Badpey
  • 6,348
  • 16
  • 93
  • 159
0

Always worth reading through the source to see whats happening. Answer: The is expecting the identifier of the auth provider in order to retrieve the user.

/**
 * Authenticate request with a JWT.
 *
 * @param \Illuminate\Http\Request $request
 * @param \Dingo\Api\Routing\Route $route
 *
 * @return mixed
 */
public function authenticate(Request $request, Route $route)
{
    $token = $this->getToken($request);

    try {
        if (! $user = $this->auth->setToken($token)->authenticate()) {
            throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
        }
    } catch (JWTException $exception) {
        throw new UnauthorizedHttpException('JWTAuth', $exception->getMessage(), $exception);
    }

    return $user;
}
Mwayi
  • 1,623
  • 15
  • 13