CakePHP 3 basic authentication get authenticated user - cakephp-3.0

public function beforeSave(Event $event) //for api
{
$hasher = new DefaultPasswordHasher();
$entity->api_key_plain =
Security::hash(Security::randomBytes(32), 'sha256', false);
$entity->api_key = $hasher->hash($entity->api_key_plain);
return true;
}
$this->loadComponent('Auth', [
'authenticate' => [
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
//'finder'=>'apiauth',
'userModel'=>'Students',
],
],
'userModel'=>'Students',
'storage' => 'Memory',
'unauthorizedRedirect' => false,
]);
public function getuser(){
$user=$this->Auth->getUser(); // Auth getUser not found
$header= $this->request->getHeader('Authorization');
$usr =$this->Auth->user(); // Always return null
return $this->jsonResponse($usr,200);
}
how to get authenticated user information form each request in CakePHP 3 AuthComponent
documentation : the getUser() method should return an array of user information on the success or false on failure.

Related

How to set home page in Yii2

public function actionIndex() {
$this->layout = 'landing';
$loginForm = new LoginForm();
if (\Yii::$app->request->getIsPost()) {
$loginForm->load(\Yii::$app->request->post());
if ($loginForm->validate()) {
$user = $loginForm->getUser();
\Yii::$app->user->login($user);
return $this->goHome();
}
}
}
method goHome() sends to the home page. I have added '' => 'site/index' to the URL Manager earlier to send people to the SiteController and Index action, but Yii2 does not do anything. How to set up a correct home page rule?
You should write homeUrl parameter on config/main.php. For example:
return [
'id' => 'app-frontend',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'homeUrl' => ['some/home-url-example'],
'modules' => [
...
],
...
]

is it possible to create an email only authentication from existing email-password structure in Laravel

I am trying to create email only authentication. Instead of having a login, I want a situation where I will only have signup and once the email is entered, a bearer token is created.
I have the signup function and login function which worked when I had password initiated but I have removed the password but I tried to move the "create token" to signup. It gives error that token is undefined.
Signup function
public function signup(Request $request)
{
$request->validate([
'email' => 'required|string|email|unique:users'
]);
$user = new User([
'email' => $request->email
]);
$user->save();
return response()->json([
'message' => 'Successfully created user!'
], 201);
}
Login function
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email'
]);
$credentials = request(['email', '=']);
if(!Auth::attempt($credentials))
return response()->json([
'message' => 'Unauthorized'
], 401);
$user = $request->user();
$tokenResult = $user->createToken('Personal Access Token');
$token = $tokenResult->token;
if ($request->remember_me)
$token->expires_at = Carbon::now()->addWeeks(1);
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
]);
}
It is really simple, you have already done most of the work needed to be done here. You don't need the login function rather you need to copy the token part of the function as illustrated below
public function signup(Request $request)
{
$request->validate([
'email' => 'required|string|email|unique:users'
]);
$user = new User([
'email' => $request->email
]);
$user->save();
Auth::login($user);
$tokenResult = $user->createToken('Personal Access Token');
$token = $tokenResult->token;
if ($request->remember_me)
$token->expires_at = Carbon::now()->addWeeks(1);
$token->save();
return response()->json([
'message' => 'Successfully created user!',
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
], 201);
}

Yii: How to validatePassword with Edvlerblog\Adldap2 using userprincipalname instead of samaccountname

Question
Currently looking for how other people handled the validate password function when they need to authenticate with the userprincipalname instead of the Edvlerblog\Adldap2 validatePassword function which uses samaccountname.
Please provide feedback in the comments if you are struggling with
anything specific so we can update the documentation.
Current Implementation
For app/common/model/LoginForm
getUser
The Edvlerblog\Adldap2 getUser() function works, and even caches the queryLdapUserObject, allowing you to fetch any of the AD attributes.
protected function getUser()
{
if ($this->_user === null) {
$this->_user = \Edvlerblog\Adldap2\model\UserDbLdap::findByUsername($this->username);
}
return $this->_user;
}
validatePassword()
Currently, the following validatePassword function does not work for me because in my instance AD must authenticate against the userprincipalname instead of the samaccount name.
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
A solution
Here is one workaround thanks to the Edvlerblog\Adldap2 who recently released 3.0.5 addressing a couple issues and providing some examples in his readme docs.
Please note the addition of findByAttribute(), allowing the following:
$this->_user = \Edvlerblog\Adldap2\model\UserDbLdap::findByUsername($this->username);
validatePassword() w/ userprincipalname
Update your login model: common\models\LoginForm.php
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user) {
$this->addError('username', 'Incorrect username.');
} else {
// Note: queryLdapUserObject is a cached object,
// so the ldap fetch does not get called :-).
$userprincipalname = $this->_user->queryLdapUserObject()->getAttribute('userprincipalname');
$auth = Yii::$app->ad->auth()->attempt($userprincipalname[0], $this->password);
if (!$auth) {
$this->addError('password', 'Incorrect password.');
}
}
}
}
getUser() w/userprincipalname
/**
* Finds user by [[username]]
*
* #return User|null
*/
protected function getUser()
{
if ($this->_user === null) {
$this->_user = \Edvlerblog\Adldap2\model\UserDbLdap::findByUsername($this->username);
}
return $this->_user;
}
Yii2 ldap Component Configuration
Reference: https://github.com/Adldap2/Adldap2/blob/master/docs/configuration.md
Config in your frontend\config\main:
'components' => [
'log' => [... ],
'authManager' => [... ],
'ad' => [
'class' => 'Edvlerblog\Adldap2\Adldap2Wrapper',
'providers' => [
'default' => [
'autoconnect' => true,
'config' => [
'domain_controllers' => ['your.ldap.domain.com'],
'base_dn' => "OU=XXX,OU=XXX,DC=ccccccc,DC=xxxx,DC=com",
'admin_username' => "your_username",
'admin_password' => "your_password",
'port' => 389,
],
],
],
],
],

How to use JWT in Yii2 project?

In my REST API i want to use JWT fro Authorization.
So, I include this extension - https://github.com/sizeg/yii2-jwt
It clear how to create JWT token, but how to validate Token in API side ? I heart, i must use two tokens - auth_token and refresh_token. For what? What different when i whatt to validate and check user ?
I mean - ok, when i receive username and password, I create auth_token (JWT) and update token in users DB, after i return token to frontend.
After frontend will send auth token in each request, and I will validate token and check user in users DB and check access etc. How to realize refresh token and for what?
For example my controller:
class UploadController extends Controller {
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => JwtHttpBearerAuth::className()
];
return $behaviors;
}
public function actionIndex() {
//Work with User
}
}
And how to get token from headers ?
Controller
public function actionLogin()
{
$username = Yii::$app->request->post('username');
$password = Yii::$app->request->post('password');
$provider = new ActiveDataProvider([
'query' => User::find()
->where(['user_name' => $username])->asArray()->one(),
]);
$result = $provider->query;
if($result)
{
if (Yii::$app->getSecurity()->validatePassword($password, $result['user_pass']))
{
$tokenId = base64_encode(mcrypt_create_iv(32));
$issuedAt = time();
$notBefore = $issuedAt; //Adding 10 seconds
$expire = $notBefore + 5184000; // Adding 60 Days
$serverName = 'your-site.com';
$data = [
'iat' => $issuedAt, // Issued at: time when the token was generated
'jti' => $tokenId, // Json Token Id: an unique identifier for the token
'iss' => $serverName, // Issuer
'nbf' => $notBefore, // Not before
'exp' => $expire, // Expire
'data' => [ // Data related to the signer user
'id' => $result['user_id'],
'username' => $result['user_name'],
'mobile' => $result['user_mobile'],
'email' => $result['user_email'],
'city' => $result['user_city'],
'state' => $result['user_state'],
'country' => $result['user_country'],
'picture' => $result['user_picture'],
]
];
$jwt = JWT::encode(
$data,
JWT_KEY,
'HS512'
);
$response = [
'status' => true,
'message' => 'Login Success..',
'era_tkn' => $jwt,
];
}
else
{
$response = [
'status' => false,
'message' => 'Wrong username or password.',
];
}
}
else
{
$response = [
'status' => false,
'message' => 'Wrong username or password.',
];
}
return $response;
}
Make global method for check token
public function check_token()
{
$headers = Yii::$app->request->headers;
$token = $headers->get('era_tkn');
if($token)
{
try{
$valid_data = JWT::decode($token, JWT_KEY, array('HS512'));
$valid_data = $valid_data->data;
}catch(Exception $e){
$valid_data = $e->getMessage();
}
}
else
{
$valid_data = 'Required Authentication';
}
return $valid_data;
}
Call check_token mathod
$user_data = $this->check_token();
if (!empty($user_data->id))
{
echo $user_data->id;
}
else
{
echo "Invalid Token.";
}

Yii2 Yii::$app->user->identity->id returns an error instead of redirecting to login page

in my behaviours I have specified that actionList can only be viewed by authenticated users.
$behaviors [ 'access' ] = [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => [ 'list' ],
'allow' => ['#'],
]
],
];
In actionList I'm getting the user_id:
public function actionList() {
$user_id = \Yii::$app->user->identity->id;
return $this->render( 'list' );
}
All good, but if you go to this action when not logged in, you get an error:
PHP Notice – yii\base\ErrorException
Trying to get property of non-object
Makes sense, I'm not logged in so I don't have a user id, but why does the code go that far? If I comment the $user_id = \Yii::$app->user->identity->id; out, I get redirected to the login page, which is the expected behaviour. I don't think I should have to do yet another check to see if someone is logged in in the action itself, shouldn't that be handled by the behaviours['access'] beforehand?
Try this changing the allow and roles attributes:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['list'],
'allow' => true,
'roles' => ['#'],
],
], // rules
], // access
];
}
More info here.
Here is my cent to the already good answers above
Add following code to the main controller file in your project (not the base controller) but some controller above this which is base for every other controller
/**
* Check if user is logged in and not logged out
*
* #param type $action
* #return type
*/
public function beforeAction($action) {
$this->enableCsrfValidation = false;
if(!empty($action) && $action->actionMethod == 'actionLogin') {
return true;
}
/* Check User's Login Status */
if (is_null(Yii::$app->user->identity)) {
$this->redirect(Url::to(['../site/login']));
Yii::$app->end();
}
return true;
}