Would help with this please, the JWT is generated, but I’m using it I get 401 error message. I tried to trace it with xdebug, the findIdentityByAccessToken is been called. The test is done with PostMan.
user model:
public static function generateJwt ($email, $user_id, $registrationStamp) {
$jti = $registrationStamp * 4 / 3 + $user_id;
$uid = $user_id;
$key = \Yii::$app->jwt->key . $user_id;
$signer = new Sha512();
//todo: check the expiry time/--------------------------------------/
$token = \Yii::$app->jwt->getBuilder()
->setIssuer(\Yii::$app->params[ 'hostInfo' ])// Configures the issuer (iss claim)
->setAudience(\Yii::$app->params[ 'hostInfo' ])// Configures the audience (aud claim)
->setId($jti, true)// Configures the id (jti claim), replicating as a header item
->setIssuedAt(time())// Configures the time that the token was issue (iat claim)
->setExpiration(time() + 3600 * 7)// Configures the expiration time of the token (exp claim)
->set('email', $email)
->set('uid', $uid)// Configures a new claim, called "uid"
->sign($signer, $key)// creates a signature using "testing" as key
->getToken();
return $token;
}
public static function findIdentityByAccessToken ($token, $type = null) {
//throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
foreach ( self::$users as $user ) {
if ( $user[ 'id' ] === (string) $token->getClaim('uid') ) {
return new static($user);
}
}
return false;
}
public function login ($email, $password) {
if ( $this->validatePassword($password) AND $this->isUserActive() ) {
//\Yii::$app->user->login(self::findByEmail($this->email));
$token = (string) Token::generateJwt($this->email, $this->id, $this->created_at);
return $token;
}
return false;
}
Api/UserController
public function behaviors () {
$behaviors = parent::behaviors();
$behaviors[ 'authenticator' ] = [
'class' => \bizley\jwt\JwtHttpBearerAuth::class,
'only' => ['test'],
];
return $behaviors;
}
public function actionTest () {
return ['Test action'];
}
You right, but method findIdentityByAccessToken in called, I checked this by xdebug.
But how to pass the $user value here, should I make new query? and why there is foreach loop?
Oh, I understand now where did you get this code from - it’s the example from sizeg/yii2-jwt original package (I’m not providing such examples). As you can read there sizeg mentions using basic Yii 2 template in that example. The variable comes from here.
Well, since all depends on your implementation I can only give you some clues how to do it. Take a look at the tests for extension, this might give you general idea.
Based on that I changed my code, the login method moved to api/UserController
public function actionLogin () {
$email = \Yii::$app->request->post('email');
$password = \Yii::$app->request->post('password');
if ( !$email or !$password )
return ['result' => 'error', 'message' => 'Email or password error!'];
//find the user
$user = User::findByEmail($email);
if ( $user ) {
//if password valid & account is active
if ( $user->validatePassword($password) AND $user->isUserActive() ) {
$token = Token::generateJwt($user->id, $user->created_at);
User::$token = (string) $token;
\Yii::$app->request->headers->set('Authorization', "Bearer ".(string)$token);
return ['result' => 'success', 'message' => (string) $token];
}
}
return ['result' => 'error', 'message' => 'Email or password error!'];
}
and in the common/User model I changed this:
public static function findIdentityByAccessToken ($token, $type = null) {
if ( static::$token !== $token ) {
return null;
}
return new static();
}
and the method to generate the token:
public static function generateJwt ($user_id, $registrationStamp) {
$jti = "1234";//$registrationStamp * 4 / 2 + $user_id;
$uid = $user_id;
$key = \Yii::$app->jwt->key;
$signer = new Sha512();
//todo: check the expiry time/--------------------------------------/
$token = \Yii::$app->jwt->getBuilder()
->setIssuer(\Yii::$app->params[ 'hostInfo' ])// Configures the issuer (iss claim)
->setAudience(\Yii::$app->params[ 'hostInfo' ])// Configures the audience (aud claim)
->setId($jti, true)// Configures the id (jti claim), replicating as a header item
->setIssuedAt(time())// Configures the time that the token was issue (iat claim)
->setExpiration(time() + 3600 * 7)// Configures the expiration time of the token (exp claim)
->setSubject($uid)// Configures a new claim, called "uid"
->sign($signer, $key)// creates a signature using "testing" as key
->getToken();
return $token;
}
But same thing, error 401, maybe I need custom auth?!
I’m using api module to serve the frontend (vue) and the backend.
This version supports lcobucci/jwt library in version 4 which has been significantly improved (and changed - be aware).
Please read the doc before using it (several examples have been provided there). Let me know if you have any suggestions or would like to report an issue.
Whether the filter should throw an exception i.e. if the token has an invalid format. If there are multiple auth filters (CompositeAuth) it can make sense to “silent fail” and pass the validation process to the next filter on the composite auth list. Default is true.