Yii2 rest api basic auth - rest

I need Basic authentication in Yii2 rest API:
Api controller:
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator']['class'] = HttpBasicAuth::className();
$behaviors['authenticator']['auth'] = function ($username, $password) {
return \app\models\User::findOne([
'username' => $username,
'password' => $password,
]);
};
}
My Requwest:
login:password#api/users
How fix it?
Error:
Invalid argument supplied for foreach()
if ($this->_behaviors === null) {
$this->_behaviors = [];
foreach ($this->behaviors() as $name => $behavior) {
$this->attachBehaviorInternal($name, $behavior);
}
}
Line with "foreach".

In controller:
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(),
];
return $behaviors;
}
Url for Get: username:password#api/users

Related

Codeigniter 4 Rest API - 301 Moved Permanently

I have Codeigniter 4 web app that run REST API with firebase/php-jwt on Laragon 5.0.0210523 environment that run Apache-2.4.47, PHP-8.1.7, and MongoDB-4.0.28. I followed a tutorial and it works fine both server REST API and it REST client. After day work, i stop laragon server. In the next day i try run REST API server then tried then run the client but it failed and gave 301 moved permanently error, but i still can access it from postman.
REST API server side
composer.json
***
"require": {
"php": "^7.4 || ^8.0",
"codeigniter4/framework": "^4.0",
"mongodb/mongodb": "^1.12",
"firebase/php-jwt": "^6.3"
},
***
.env file
***
JWT_SECRET_KEY = SomeThing$089
JWT_TIME_TO_LIVE = 3600
app.baseURL = 'http://ci4-api.localhost'
***
Route.php
***
$routes->get('/', 'Home::index');
$routes->resource('api/users');
$routes->post('api/auth', [\App\Controllers\Api\Auth::class, 'index']);
***
JWT_Helper.php
use App\Models\ModelUsers;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
/**
* #throws Exception
*/
function getJWT($authHeader)
{
if (is_null($authHeader)){
throw new Exception("Authentication JWT failed");
}
return explode(" ", $authHeader)[1];
}
function validateJWT($encodedToken)
{
$key = getenv('JWT_SECRET_KEY');
$decodedToken = JWT::decode($encodedToken, new Key($key, 'HS256'));
$modelUsers = new ModelUsers();
$modelUsers->get_email($decodedToken->email);
}
function createJWT($email): string
{
$timeRequest = time();
$timeToken = getenv('JWT_TIME_TO_LIVE');
$timeExpired = $timeRequest + $timeToken;
$payload = [
'email' => $email,
'iat' => $timeRequest,
'exp' => $timeExpired,
];
return JWT::encode($payload, getenv('JWT_SECRET_KEY'), 'HS256');
}
FilterJWT.php
namespace App\Filters;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Exception;
class FilterJWT implements FilterInterface
{
use ResponseTrait;
public function before(RequestInterface $request, $arguments = null)
{
$header = $request->getServer('HTTP_AUTHORIZATION');
try {
helper('jwt');
$encodedToken = getJWT($header);
validateJWT($encodedToken);
return $request;
} catch (Exception $ex) {
return Services::response()->setJSON(
[
'error' => $ex->getMessage(),
]
)->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED);
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// TODO: Implement after() method.
}
}
Filters.php
***
public $aliases = [
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'invalidchars' => InvalidChars::class,
'secureheaders' => SecureHeaders::class,
'auth' => FilterJWT::class,
];
public $filters = [
'auth' => [
'before' => [
'api/users/*',
'api/users'
]
]
];
***
ModelUsers.php
namespace App\Models;
use App\Libraries\MongoDb;
class ModelUsers
{
private $database = 'ci4_api';
private $collection = 'user';
private $conn;
function __construct()
{
$mongodb = new MongoDb();
$this->conn = $mongodb->getConn();
}
function get_user_list() {
try {
$filter = [];
$query = new \MongoDB\Driver\Query($filter);
$result = $this->conn->executeQuery($this->database. '.' . $this->collection, $query);
return $result->toArray();
} catch (\MongoDB\Driver\Exception\RuntimeException $ex) {
show_error('Error while fetching users: ' . $ex->getMessage(), 500);
}
}
***
Auth.php
namespace App\Controllers\Api;
use App\Controllers\BaseController;
use App\Models\ModelUsers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Validation\Validation;
use Config\Services;
class Auth extends BaseController
{
use ResponseTrait;
private ModelUsers $model;
private Validation $validation;
function __construct()
{
$this->model = new ModelUsers();
$this->validation = Services::validation();
}
public function index()
{
$email = $this->request->getVar('email');
$password = $this->request->getVar('password');
$password_hash = password_hash($password, PASSWORD_DEFAULT);
$data1 = [
'email' => $email,
'password' => $password
];
if (!$this->validation->run($data1, 'login')) {
$errors = $this->validation->getErrors();
$response = [
'status' => 201,
'error' => null,
'messages' => [
'errors' => [
$errors
]
],
];
return $this->respond($response);
}
$data1 = $this->model->get_email($email);
//return $this->respond($data1, 200);
if (!$data1) {
$response = [
'status' => 201,
'error' => null,
'messages' => [
'error' => 'Data user atau password tidak ada1'
],
];
return $this->respond($response, 200);
}
$password_user = $data1->password;
if (password_verify($password_hash, $password_user) != 0){
$response = [
'status' => 201,
'error' => null,
'messages' => [
'error' => 'Data user atau password tidak ada2'
],
];
return $this->respond($response, 200);
}
helper('jwt');
$response = [
'message' => 'Auth berhasil dilakukan',
'data' => $data1,
'access_token' => createJWT($email)
];
return $this->respond($response, 200);
}
***
users.php
namespace App\Controllers\Api;
use App\Controllers\BaseController;
use App\Models\ModelUsers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\HTTP\Response;
use CodeIgniter\Validation\Validation;
use Config\Services;
class Users extends BaseController
{
use ResponseTrait;
private ModelUsers $model;
private Validation $validation;
function __construct()
{
$this->model = new ModelUsers();
$this->validation = Services::validation();
}
public function index(): Response
{
$data = $this->model->get_user_list();
$count = count($data);
if ($count <= 0) {
$data = [
'status' => 201,
'error' => null,
'message' => [
'success' => 'Tidak ada data daftar pegawai'
],
];
}
return $this->respond($data, 200);
}
***
REST Client
.env file
***
app.baseURL = 'http://ci4-test.localhost'
***
Routes.php
***
$routes->get('/rest', [\App\Controllers\Rest\RestClient::class, 'index']);
***
RestClient.php
namespace App\Controllers\Rest;
use App\Controllers\BaseController;
use Config\Services;
class RestClient extends BaseController
{
public function index()
{
$client = Services::curlrequest();
$token = "someToken";
$url = "http://ci4-api.localhost/api/users/";
$headers = [
'Authorization' => 'Bearer ' . $token,
];
$response = $client->request('GET', $url, ['headers' => $headers, 'http_errors' => false]);
return $response->getBody();
}
}
Postman
api auth
api all user list
I have already tried some simple solution, like reload all laragon service like apache server and mongodb, restart the windows and tried find online, but it only suggest that the url is incorectly used like in this one []https://stackoverflow.com/questions/56700991/codeigniter-301-moved-permanently[3]
Is there anyone have same issue or solution, thanks in advance.
After trying some few more time, i found the problem. It still around about url similiar like in case of Codeigniter 301 Moved Permanently, but my problem i added "/" on my url.
eg
RestClient.php
//Read all users
$url = "http://ci4-api.localhost/api/users/";
Maybe i added it after copy paste process
so the correct url is
RestClient.php
//Read all users
$url = "http://ci4-api.localhost/api/users";
hopefully help some people facing same problem

run codecept REST for yii2 how to get $_SERVER['PHP_AUTH_USER']?

Configure modules in api.suite.yml
class_name: ApiTester
modules:
enabled:
- REST:
url: http://xxxx
depends: Yii2
- \backend\tests\Helper\Api
config:
- Yii2
class UserLoginCest
public function tryToTest(ApiTester $I)
{
$I->haveHttpHeader('Authorization', 'Basic Og==');
$I->sendPOST('/admin/user/login', ['username' => 'wen', 'password' => '123456']);
$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
$I->seeResponseIsJson();
$I->seeResponseContains('{"result":"ok"}');
}
in UserController $behaviors
$behaviors['authenticator'] = [
'class' => CompositeAuth::class,
'authMethods' => [
[
'class' => HttpBasicAuth::class,
'auth' => function ($username, $password) {
$request = Yii::$app->request;
$username = $username ?: $request->post('username');
$password = $password ?: $request->post('password');
if (!$user = User::findByUsername($username)) {
return null;
}
if (!$user->validatePassword($password)) {
return null;
}
if ($user->login()) {
return $user;
}
return null;
}
],
]
];
in Yii2 HttpBasicAuth
$username = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : null;
$password = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : null;
var_dump($_SERVER) is not set $_SERVER['PHP_AUTH_USER'] response 401 Unauthorized
Use amHttpAuthenticated method: https://codeception.com/docs/modules/REST#amHttpAuthenticated
$I->amHttpAuthenticated('username', 'password');

Facebook Login Exception

I have this function that handle the Fb Callback.
public function handleFbCallback() {
if( !\Input::get('error', NULL) ) {
try {
$fuser = \Socialize::with('facebook')->user();
$token = $fuser->token;
if($fb = \App\UserFacebook::whereEmail($fuser->getEmail())->first()) {
$fb->fb_id = $fuser->getId();
$fb->nickname = $fuser->getNickname();
$fb->name = $fuser->getName();
$fb->avatar = $fuser->getAvatar();
$fb->token = $token;
$fb->save();
$profile = \App\Profile::whereUserId($fb->user_id)->first();
if($profile) {
$profile->name = $fuser->user['first_name'];
$profile->last_name = $fuser->user['last_name'];
$profile->save();
} else {
\App\Profile::create([
'name' => $fuser->user['first_name'],
'last_name' => $fuser->user['last_name'],
'user_id' => $fb->user_id,
]);
}
//load user and increments number login
$user = \App\User::find($fb->user_id);
if($user) {
$user->last_login = date('Y-m-d H:i:s');
$user->number_logins = $user->number_logins + 1;
$user->save();
}
}
else {
$password = str_random(8);
$nuser = \App\User::whereEmail($fuser->getEmail())->first();
if(!$nuser) {
$nuser = \App\User::create([
'email' => $fuser->getEmail(),
'password' => bcrypt($password),
'active' => 1,
]);
if(\Session::get('source', NULL)) {
$nuser->source = \Session::get('source');
\Session::forget('source');
}
if(\Session::get('campaign', NULL)) {
$nuser->source = \Session::get('campaign');
\Session::forget('campaign');
}
$nuser->save();
//profile
\App\Profile::create([
'name' => $fuser->user['first_name'],
'last_name' => $fuser->user['last_name'],
'user_id' => $nuser->id,
]);
}
$nuser->last_login = date('Y-m-d H:i:s');
$nuser->number_logins = 1;
$nuser->save();
$fb = \App\UserFacebook::create([
'fb_id' => $fuser->getId(),
'nickname' => $fuser->getNickname(),
'name' => $fuser->getName(),
'email' => $fuser->getEmail(),
'avatar' => $fuser->getAvatar(),
'token' => $token,
'user_id' => $nuser->id
]);
}
\Auth::loginUsingId($fb->user_id);
if(\Session::get('custom_url', NULL) == 'thanks') {
return redirect()->route('landing.thanks', array('social', $fb->user_id));
} elseif($url = \Session::get('custom_url', NULL)) {
\Session::forget('custom_url');
return redirect($url);
}
return redirect()->intended();
}
catch(Exception $e) {
dd($e->getMessage());
}
}
return redirect('/');
}
Running this function it make an exception:
Client error: GET https://graph.facebook.com/v2.6/me?access_token=&appsecret_proof=cb32db5fac27b922d1a9c3040772a05b9a6e79f8145ee5a9fc21bbefd1f00909&fields=name,first_name,last_name,email,gender,verified resulted in a 400 Bad Request response: {"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthExce (truncated...)
But it make an exception about the token.
Someone have any idea to solve that?
Thank you!

how to convert the pure soap php to laravel 5

I am new in laravel 5. This code is ok in pure php. But I don't know how to convert this to laravel 5. Can you tell me how to transfer this code to laravel 5.
client.php:
<?php class client {
public function __construct()
{
$params = array('location' => 'http://localhost:8888/csoap/server.php',
'uri' => 'urn://localhost:8888/csoap/server.php');
/* Initialize webservice */
$this->instance = new SoapClient(NULL, $params);
}
public function getString($id)
{
return $this->instance->__soapCall('getOutputString', $id);
}
}
$client = new client();
$id = array('id' => '1');
echo $client->getString($id);
?>
csoap/server.php:
<?php class server {
public function getOutputString($id)
{
$str = 'Youre ID is ' . $id . '.';
return $str;
}
}
$params = array('uri' => 'http://localhost:8888/csoap/server.php');
$server = new SoapServer(NULL, $params);
$server->setClass('server');
$server->handle();
?>
This is how I performed my installation in laravel 5.1
"require": {
"artisaninweb/laravel-soap": "0.2.*"
}
run: composer install or composer update
Add the service in config/app.php.
'providers' => [
...
...
Artisaninweb\SoapWrapper\ServiceProvider',
]
'aliases' => [
...
...
'SoapWrapper' => 'Artisaninweb\SoapWrapper\Facades\SoapWrapper'
]
This is my client soap:
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
class DataSoap {
public function demo()
{
// Add a new service to the wrapper
SoapWrapper::add(function ($service) {
$service
->name('mydata')
->wsdl('http://localhost:8888/csoap/Server.php')
->trace(true)
});
$data = [
'str' => 'Hello World',
];
// Using the added service
SoapWrapper::service('mydata', function ($service) use ($data) {
var_dump($service->getFunctions());
var_dump($service->call('getString', [$data])->getSringResult);
});
}
}
When I run the this code, I get an error
Class 'Artisaninweb\SoapWrapper\ServiceProvider' not found
You should change:
Artisaninweb\SoapWrapper\ServiceProvider
to:
Artisaninweb\SoapWrapper\ServiceProvider::class
and also:
SoapWrapper' => 'Artisaninweb\SoapWrapper\Facades\SoapWrapper
to:
SoapWrapper' => Artisaninweb\SoapWrapper\Facades\SoapWrapper::class

Zend 1.12 login not working

i'm creating a login system using salt and password two columns but it's not working my code of action
public function indexAction() {
$form = new Admin_Form_Login();
$request = $this->getRequest();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
if ($this->_process($form->getValues())) {
// We're authenticated! Redirect to the home page
$this->_helper->redirector('', 'dashboard');
} else {
echo 'Password is wrong';
}
}
}
$this->view->form = $form;
}
protected function _process($values) {
// Get our authentication adapter and check credentials
$adapter = $this->_getAuthAdapter();
$adapter->setIdentity($values['email']);
$adapter->setCredential($values['password']);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
$user = $adapter->getResultRowObject();
$auth->getStorage()->write($user);
return true;
}
return false;
}
protected function _getAuthAdapter() {
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('eg_user_login')
->setIdentityColumn('email')
->setCredentialColumn('password')
->setCredentialTreatment("MD5(CONCAT(? , salt))");
return $authAdapter;
}
and code of registration action is
$regForm = new Admin_Form_Register();
$this->view->form = $regForm;
if ($this->getRequest()->isPost()) {
if ($regForm->isValid($this->_request->getPost())) {
$values = $regForm->getValues($this->_request->getPost());
$pass = $values['pass1'];
$salt = sha1($pass);
$password = MD5($salt . $pass);
$data = array(
'f_name' => $values['fname'],
'l_name' => $values['lname'],
'gender' => $values['gender'],
'email' => $values['email'],
'contact' => $values['contact'],
'password' => $password,
'salt' => $salt,
'created_on' => date("d-m-y"),
'user_role' => $values['userrole'],
'status' => 0
);
$db = new Admin_Model_Userreg();
$db->insert($data);
}
}
it is displaying any error,i think problem in encryption and decryption in password.
login page is not redirecting to dashboard and not storing the user instance .... please help me. thank you.