How to do basic authentication in Yii2 REST api - rest

I have tried this, but it does not help me: Yii2 REST API BasicAuth not working
Here is what I did:
I have BaseController and DocumentController extending it.
in BaseController I have this code:
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator'] = [
'class' => 'yii\filters\ContentNegotiator',
'formats' => [
'application/json' => Response::FORMAT_JSON,
]
];
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(),
'auth' => [$this, 'authenticate']
];
return $behaviors;
}
/**
* Finds user by username and password
*
* #param string $username
* #param string $password
* #return static|null
*/
public function authenticate($username, $password)
{
// username, password are mandatory fields
if(empty($username) || empty($password)) {
return null;
}
// get user using requested email
$user = User::findByUsername($username);
// if no record matching the requested user
if(empty($user)) {
return null;
}
// if password validation fails
if(!User::validatePassword($password)) {
return null;
}
// if user validates (both user_email, user_password are valid)
return $user;
}
When I try to visit my api: localhost/api/documents/5
I get this error: Getting unknown property: app\\controllers\\DocumentController::password_hash
What I am supposed to do to make this thing work ? I just do not understand what yii wants from me anymore.
EDIT: full error :
{"name":"Unknown Property","message":"Getting unknown property: app\\controllers\\DocumentController::password_hash","code":0,"type":"yii\\base\\UnknownPropertyException","file":"/var/www/html/api/_protected/vendor/yiisoft/yii2/base/Component.php","line":143,"stack-trace":["#0 /var/www/html/api/_protected/models/UserIdentity.php(129): yii\\base\\Component->__get('password_hash')","#1 /var/www/html/api/_protected/controllers/AppController.php(58): app\\models\\UserIdentity->validatePassword('wspass')","#2 [internal function]: app\\controllers\\AppController->authenticate('wsuser', 'wspass')","#3 /var/www/html/api/_protected/vendor/yiisoft/yii2/filters/auth/HttpBasicAuth.php(68): call_user_func(Array, 'wsuser', 'wspass')","#4 /var/www/html/api/_protected/vendor/yiisoft/yii2/filters/auth/AuthMethod.php(60): yii\\filters\\auth\\HttpBasicAuth->authenticate(Object(yii\\web\\User), Object(yii\\web\\Request), Object(yii\\web\\Response))","#5 /var/www/html/api/_protected/vendor/yiisoft/yii2/base/ActionFilter.php(71): yii\\filters\\auth\\AuthMethod->beforeAction(Object(yii\\rest\\IndexAction))","#6 [internal function]: yii\\base\\ActionFilter->beforeFilter(Object(yii\\base\\ActionEvent))","#7 /var/www/html/api/_protected/vendor/yiisoft/yii2/base/Component.php(541): call_user_func(Array, Object(yii\\base\\ActionEvent))","#8 /var/www/html/api/_protected/vendor/yiisoft/yii2/base/Controller.php(269): yii\\base\\Component->trigger('beforeAction', Object(yii\\base\\ActionEvent))","#9 /var/www/html/api/_protected/vendor/yiisoft/yii2/web/Controller.php(108): yii\\base\\Controller->beforeAction(Object(yii\\rest\\IndexAction))","#10 /var/www/html/api/_protected/vendor/yiisoft/yii2/base/Controller.php(152): yii\\web\\Controller->beforeAction(Object(yii\\rest\\IndexAction))","#11 /var/www/html/api/_protected/vendor/yiisoft/yii2/base/Module.php(454): yii\\base\\Controller->runAction('index', Array)","#12 /var/www/html/api/_protected/vendor/yiisoft/yii2/web/Application.php(84): yii\\base\\Module->runAction('document/index', Array)","#13 /var/www/html/api/_protected/vendor/yiisoft/yii2/base/Application.php(375): yii\\web\\Application->handleRequest(Object(yii\\web\\Request))","#14 /var/www/html/api/index.php(12): yii\\base\\Application->run()","#15 {main}"]}

Related

Yii2: rest api model get data

I am using REST API in my project and everything works great. I describe a model using a model
<?php
namespace api\modules\v1\models;
use Carbon\Carbon;
use Yii;
class Comment extends \common\models\Comment
{
public function fields()
{
return [
'id',
'user' => function(Comment $model) {
return User::findOne($model->user_id);
},
'text',
'image' => function(Comment $model) {
return Yii::$app->params['link'].$model->image;
},
'created_at' => function(Comment $model) {
Carbon::setLocale(Yii::$app->language);
return Carbon::createFromTimeStamp(strtotime($model->created_at))->diffForHumans();
},
'children' => function(Comment $model) {
$comments = Comment::find()
->where(['comment_id' => $model->id]);
if (!$comments->exists()) {
return false;
}
return $comments->all();
},
'like',
'news_id',
'comment_id'
];
}
}
The data is returned in the specified format and that's great. But I need to send data to the controller using websockets. For example, when a new comment arrives, send it to all users.
$post = Yii::$app->request->post();
$image = UploadedFile::getInstanceByName('image');
$model = new \api\modules\v1\models\Comment([
'news_id' => $post['feed_id'],
'comment_id' => $post['comment_id'] ?? null,
'user_id' => Yii::$app->user->identity->id,
]);
$model->text = $model->findLinks($post['text']);
if ($image && !$image->error) {
if (!file_exists(Yii::$app->params['comment.pathAbsolute'])) {
if (!FileHelper::createDirectory(Yii::$app->params['comment.pathAbsolute'], 0777)) {
throw new \Exception('Помилка створення папки');
}
}
$serverName = Yii::$app->security->generateRandomString(16).'.'.$image->extension;
if ($image->saveAs(Yii::$app->params['comment.pathAbsolute'].$serverName)) {
$model->image = $serverName;
} else {
throw new \Exception($image->error);
}
}
if (!$model->save()) {
throw new \Exception($model->error());
}
Helper::ws(false, 'updateComment', ['feed_id' => $post['feed_id'], 'comment' => $model]);
And when I pass the $model, the data is passed as it is stored in the database. Is it possible to call a method or something so that the data is passed as I described in the model api?

during sails lift it throw error

hi i am new to sails and passport js i am trying authentication using passport js in sails but while am adding passport.js in config folder it give an error..any one know how to resolve this issu..
Here is my error
C:\Users\sachinn\AppData\Roaming\npm\node_modules\sails\node_modules\include-all\lib\help-include-all-sync.js:281
throw e;
^
`include-all` attempted to `require(E:\myApi\config\passport.js)`, but an error occurred::
Details:TypeError: JwtStrategy requires a function to retrieve jwt from requests (see option jwtFromRequest)
at new JwtStrategy (E:\myApi\node_modules\passport-jwt\lib\strategy.js:39:15)
at Object.<anonymous> (E:\myApi\config\passport.js:68:3)
at Module._compile (module.js:570:32)
passort.js
/**
* Passport configuration file where you should configure strategies
*/
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var JwtStrategy = require('passport-jwt').Strategy;
var EXPIRES_IN_MINUTES = 60 * 24;
var SECRET = process.env.tokenSecret || "4ukI0uIVnB3iI1yxj646fVXSE3ZVk4doZgz6fTbNg7jO41EAtl20J5F7Trtwe7OM";
var ALGORITHM = "HS256";
var ISSUER = "nozus.com";
var AUDIENCE = "nozus.com";
/**
* Configuration object for local strategy
*/
var LOCAL_STRATEGY_CONFIG = {
usernameField: 'email',
passwordField: 'password',
passReqToCallback: false
};
/**
* Configuration object for JWT strategy
*/
var JWT_STRATEGY_CONFIG = {
secretOrKey: SECRET,
issuer : ISSUER,
audience: AUDIENCE,
passReqToCallback: false
};
/**
* Triggers when user authenticates via local strategy
*/
function _onLocalStrategyAuth(email, password, next) {
User.findOne({email: email})
.exec(function (error, user) {
if (error) return next(error, false, {});
if (!user) return next(null, false, {
code: 'E_USER_NOT_FOUND',
message: email + ' is not found'
});
// TODO: replace with new cipher service type
if (!CipherService.comparePassword(password, user))
return next(null, false, {
code: 'E_WRONG_PASSWORD',
message: 'Password is wrong'
});
return next(null, user, {});
});
}
/**
* Triggers when user authenticates via JWT strategy
*/
function _onJwtStrategyAuth(payload, next) {
var user = payload.user;
return next(null, user, {});
}
passport.use(
new LocalStrategy(LOCAL_STRATEGY_CONFIG, _onLocalStrategyAuth));
passport.use(
new JwtStrategy(JWT_STRATEGY_CONFIG, _onJwtStrategyAuth));
module.exports.jwtSettings = {
expiresInMinutes: EXPIRES_IN_MINUTES,
secret: SECRET,
algorithm : ALGORITHM,
issuer : ISSUER,
audience : AUDIENCE
};
Options passed to JwtStrategy constructor must have a key jwtFromRequest.
It is missing in your code.
See https://github.com/themikenicholson/passport-jwt#usage
jwtFromRequest (REQUIRED) Function that accepts a request as the only
parameter and returns either the JWT as a string or null. See
Extracting the JWT from the request for more details.

symfony assert for entity type variable

how validate entity variable, because in my point it's valid for empty select.
/**
* #Assert\NotBlank(message = "education level cannot be empty")
* #var EducationLevel[]|ArrayCollection
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\EducationLevel")
*/
private $educationLevel;
form type
->add('educationLevel', EntityType::class, [
'class' => 'AppBundle:EducationLevel',
'multiple' => true,
'choice_label' => function ($educationLevel) {
return $educationLevel->getName();
},
])
NotBlank won't work, because it checks if value is not null or not empty string or not false
NotBlank manual
What you have to do is to write custom Constraint and a validator:
Custom validator manual
You can create a validation method in the entity which can verify if $educationLevel is null or collection of EducationLevel instances.
/**
* #Assert\IsTrue(message="Education level has to be blank or...")
*/
public function isEducationLevelValid()
{
if ($this->educationLevel->isEmpty()) {
foreach ($this->educationLevel as $edulevel) {
if (!$edulevel instanceof EducationLevel) {
return false;
}
}
return true;
} else {
return false;
}
}
The method is used automatically during entity bound form submission and of course you can use it as a normal entity's method.

Error with session ini setting modification

A PHP Error was encountered
Severity: Warning
Message: ini_set(): A session is active. You cannot change the session module's ini settings at this time
Filename: Session/Session.php
Line Number: 316
Backtrace:
File: C:\xampp\htdocs\testing\index.php
Line: 315
Function: require_once
<?php
session_start(); //we need to start session in order to access it through CI
class Adminlogin extends CI_Controller {
public function _construct(){
parent::_construct();
//Load form helper library
$this->load->helper('form');
//Load form validation library
$this->load->library('form_validation');
//Load session library
$this->load->library('session');
//Load database
$this->load->model('login_database');
}
//show login page
public function index()
{
$this->load->view('admin_login');
}
//show registration page
public function user_registration_show(){
$this->load->view('admin_signup');
}
//Validate and store registration data in database
public function new_user_registration(){
//Check Validation for user input in SignUp form
$this->form_validation->set_rules('admin_username', 'Username','trim|required|xss_clean');
$this->form_validation->set_rules('admin_password', 'Password','trim|required|xss_clean');
if($this->form_validation->run()== FALSE){
$this->load->view('admin_signup');}
else{
$data = array(
'admin_username' => $this->input->post('username'),
'admin_password' => $this->input->post('password'));
$result = $this->login_database->registration_insert($data);
if($result == TRUE){
$data['message_display'] = 'Registration Successfully !';
$this->load->view('admin_login', $data);
}else{
$data['message_display'] = 'Username already exist';
$this->load->view('admin_signup',$data);
}
}
}
//Check for user login process
public function user_login_process(){
$this->form_validation->set_rules('admin_username','Username', 'trim|required|xss_clean');
$this->form_validation->set_rules('admin_password','Password', 'trim|required|xss_clean');
if($this->form_validation->run() == FALSE){
if(isset($this->session->userdata['loggen_in'])){
$this->load->view('Admin/admin_dashboard');
}else{
$this->load->view('admin_login');
}
}else{
$data = array(
'admin_username' => $this->input->post('username'),
'admin_password' => $this->input->post('password'));
$result = $this->login_database->login($data);
if($result == TRUE) {
$username = $this->input->post('username');
$result = $this->login_database->read_user_information($username);
if($result != false){
$session_data = array(
'username' => $result[0]->admin_username,
'password' => $result[0]->admin_password);
//Add user data in session
$this->session->set_userdata('logged_in', $session_data);
$this->load->view('Admin/admin_dashboard');
}else{
$data = array(
'error_message' => 'Invalid Username or Password');
$this->load->view('admin_login',$data);
}
}
}
}
}
?>
Please remove the 1st line session_start(); or change it to..
// session_start(); //I do Not need this as I am using CI Sessions.
You are using CodeIgniters Sessions which you have loaded in your code...
$this->load->library('session');
As an Aside:
You don't need the end ?> in your PHP files where it is the last tag in the file.

Tumblr API Authentification 401 Error

I'm struggling to figure this out, but with everything I'm doing I am unable to fetch a users information. I simply get a 401 error and cannot figure out why.
Code:
<?php
class Tumblr
{
public function connect()
{
$tumblr = new ExternalExtended_Helper_Tumblr;
$oauth = $tumblr->getOauthConsumer('https://mysite.com/register');
$requestToken = $oauth->getRequestToken();
$accessToken = $oauth->getAccessToken($this->_input->filter(array(
'oauth_token' => XenForo_Input::STRING,
'oauth_verifier' => XenForo_Input::STRING
)), $requestToken);
$user = $tumblr->retrieveUserInfo($accessToken);
}
}
<?php
class Helper_Tumblr
{
/**
* Returns a reference to the OAuth consumer, instantiating it if necessary
*
* #param string $callbackUrl URL to return to
*
* #return bool|Zend_Oauth_Consumer False if no Tumblr app configured, otherwise Oauth consumer
*/
public static function getOauthConsumer($callbackUrl = '')
{
$options = XenForo_Application::getOptions();
if (!$options->tumblrAppKey || !$options->tumblrAppSecret)
{
return false;
}
return new Zend_Oauth_Consumer(array(
'callbackUrl' => $callbackUrl,
'requestTokenUrl' => 'https://www.tumblr.com/oauth/request_token',
'authorizeUrl' => 'https://www.tumblr.com/oauth/authorize',
'accessTokenUrl' => 'https://www.tumblr.com/oauth/access_token',
'consumerKey' => $options->tumblrAppKey,
'consumerSecret' => $options->tumblrAppSecret,
));
}
/**
* Returns a reference to the OAuth client, instantiating it if necessary
*
* #param string $accessToken Tumblr access token (from code swap, or given by user); may be empty
*
* #return bool|Zend_Oauth_Client False if no Tumblr app configured, otherwise Oauth client
*/
public static function getOauthClient($accessToken)
{
$options = XenForo_Application::getOptions();
if (!$options->tumblrAppKey || !$options->tumblrAppSecret)
{
return false;
}
$access = new Zend_Oauth_Token_Access();
$access->setToken($accessToken->getToken());
$access->setTokenSecret($accessToken->getToken());
return $access->getHttpClient(array(
'consumerKey' => $options->tumblrAppKey,
'consumerSecret' => $options->tumblrAppSecret
));
}
/**
* Get a User's Information
*
* #return json
*/
public static function retrieveUserInfo($accessToken)
{
$oauthClient = self::getOauthClient($accessToken);
$oauthClient->setUri('http://api.tumblr.com/v2/user/info');
$response = $oauthClient->request(Zend_Http_Client::POST);
if ($response->isError())
{
throw new Exception("An error occurred sending request. Status code: {$response->getStatus()}");
}
return $response;
}
}
The error occurs in the function 'retrieveUserInfo' and a dump of the object looks like this:
object(Zend_Http_Response)#280 (5) {
["version":protected] => string(3) "1.1"
["code":protected] => int(401)
["message":protected] => string(14) "Not Authorized"
["headers":protected] => array(7) {
["Server"] => string(5) "nginx"
["Date"] => string(29) "Mon, 17 Feb 2014 02:53:08 GMT"
["Content-type"] => string(31) "application/json; charset=utf-8"
["Transfer-encoding"] => string(7) "chunked"
["Connection"] => string(5) "close"
["Set-cookie"] => string(89) "tmgioct=53017993ddbda801421421421421; expires=Thu, 15-Feb-2024 02:53:07 GMT; path=/; httponly"
["P3p"] => string(46) "CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL""
}
["body":protected] => string(71) "3c
{"meta":{"status":401,"msg":"Not Authorized"},"response":[]}
0
"
Why is it saying I'm not authorized and what haven't I done to become authorized?
Thanks!
Alright it's all fine, just a simple typo...
$access->setToken($accessToken->getToken());
$access->setTokenSecret($accessToken->getToken());
Should be:
$access->setToken($accessToken->getToken());
$access->setTokenSecret($accessToken->getTokenSecret());