Logging a user in after registration in CakePHP - cakephp

I did a lot of research, followed many different examples, but still cannot get it to run properly.
So here is a part of the controller action from the registration:
if(!empty($this->request->data)){
$this->request->data['Company']['start_date']= date("Y-m-d");
unset($this->Company->User->validate['company_id']);
if($this->Company->saveAssociated($this->request->data)){
$user = $this->request->data['User'];
$data['User']['password'] = $user[0]['password'];
$data['User']['email'] = $user[0]['email'];
if($this->Auth->login($data)){
$this->redirect($this->Auth->redirect(array('controller'=>'customers', 'action'=>'index')));
}...
So the user is saved and a new array of user's email and password is created. It is then passed to $this->Auth->login. The login seems to pass, but the following error is on redirection to customers controller:
Notice (8): Undefined index: role [APP\Controller\CustomersController.php, line 32]
Notice (8): Undefined index: role [APP\Controller\CustomersController.php, line 36]
Even though the role field is autoset as manager on user creation.
Here is how the CustomerController looks like:
public function isAuthorized($user){
if($user['role'] == 'manager'){
return true;}
if (in_array($this->action, array('add', 'edit', 'index', 'view', 'delete', 'users'))){
if($user['role'] != 'manager'){
return false;
}}return true;}
Any help is very much appreciated.

Check the docs and the source for AuthComponent::login()
http://api.cakephp.org/2.4/class-AuthComponent.html#_login
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#manually-logging-users-in
http://api.cakephp.org/2.4/source-class-AuthComponent.html#583-606
When passing user data to AuthComponent::login(), you are logging a user in, but no authentication is going to happen! "Logging in" in this case means, the data provided is being stored in the session, and on following requests the user is being treated as logged in in case data is present in the session (in the specific key used by the component), ie you could even just pass 123456, the user would be treated as being logged in.
Authenticating on the other hand would cause a DB lookup, where all the user data would be fetched and consequently being stored in the session.
So the role field is not available because you haven't passed it to AuthComponent::login(), you've only passed email and password, consequently these are the only fields being available later on. Btw, DO NOT supply the password when doing such a manual login! You don't want to carry such sensitive information in the session!
To fix this problem, either pass the role field too, or call AuthComponent::login() without passing any data at all (make sure you are using Form authentication so that the data passed in the request is being used), so that it's going to authenticate the user and fetch its data from the DB.
See also http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html

Related

Laravel 8 Fortify User UUID Login Problem

I am currently setting up a new project using Laravel 8. Out of the box, Laravel is configured to use auto-incrementing ID's for the user's ID. In the past I have overrode this by doing the following.
Updating the ID column in the user table creation migration to
$table->uuid('id');
$table->primary('id');
Adding the following trait
trait UsesUUID
{
protected static function bootUsesUUID()
{
static::creating(function ($model) {
$model->{$model->getKeyName()} = (string) Str::orderedUuid();
});
}
}
Adding the following to the user model file
use UsesUUID;
public $incrementing = false;
protected $primaryKey = 'id';
protected $keyType = 'uuid';
On this new project, I did the same as above. This seems to break the login functionality. When the email and password are entered and submitted, the form clears as though the page has been refreshed. Thing to note is there are no typical validation error messages returned as would be expected if the email and/or password is wrong.
To check that the right account is actually being found and the password is being checked properly, I added the following code to the FortifyServiceProvider boot method. The log file confirms that the user is found and the user object dump is correct too.
Fortify::authenticateUsing(function(Request $request) {
\Log::debug('running login flow...');
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
\Log::debug('user found');
\Log::debug($user);
return $user;
}
\Log::debug('user not found');
return false;
});
Undoing the above changes to the user model fixes the login problem. However, it introduces a new problem that is the login will be successful but it wont be the right account that is logged in. For example, there are 3 accounts, I enter the credentials for the second or third account, but no matter what, the system will always login using the first account.
Anyone have any suggestions or ideas as to what I may be doing wrong, or if anyone has come across the same/similar issue and how you went about resolving it?
Thanks.
After digging around some more, I have found the solution.
Laravel 8 now stores sessions inside the sessions table in the database. The sessions table has got a user_id column that is a foreign key to the id column in the users table.
Looking at the migration file for the sessions table, I found that I had forgot to change the following the problem.
From
$table->foreignId('user_id')->nullable()->index();
To
$table->foreignUuid('user_id')->nullable()->index();
This is because Laravel 8 by default uses auto incrementing ID for user ID. Since I had modified the ID column to the users table to UUID, I had forgotten to update the reference in the sessions table too.

Cannot get Username / given_name when using angular-oauth2-oidc and Identity Server 4

I am following the Implicit Workflow example from the angular-oauth2-oidc documentation.
Everything works well in my Angular app, and I can login (during which I am redirected to Identity Server), get my token and use this token to access my Web Api.
However, I have noticed that the "given_name" claim is null, and therefore, the username is not displayed on the login page. Specifically, the following method from the sample code appears to return null:
public get name() {
let claims = this.oauthService.getIdentityClaims();
if (!claims) return null;
return claims.given_name;
}
I thought perhaps this was a problem with permissions, but my scope is set to:
scope: 'openid profile email api1',
Any idea what I need to change to get this "given_name" claim?
For those who encountered the same issue. You can fix it by adding this line AlwaysIncludeuserClaimsInIdToken=true in the client settings on identity provider side.
OauthService.getIdentityClaims() is a Promise and holds UserInfo you can extract the name field with braces, so your function should be:
public get name() {
let claims = this.oauthService.getIdentityClaims();
if (!claims) return null;
return claims['name'];
}
The answer marked as "Best answer" is not correct. Get the user claims in the 'idtoken' will cause that the 'idtoken' be very big and then you may exceed the size limit.
The correct implementation is to use the 'UserInfo' Endpoint and then use the method 'loadUserProfile':
Example:
getUserClaims() {
const user = this.oauthService.loadUserProfile();
console.log(user, user);
}
I had the same issue, in my case with an error displayed on the browser console, saying that Request was blocked by Security Policy.
even having the AllowAnyOrigin() method called in startup, I lacked to get the header allowed. So when in my angular aap i call the loadUserProfile method via the
token_received event, it sends some headers that were not allowed.
Finaly this fix my issue:
app.UseCors(options => options.AllowAnyOrigin().AllowAnyHeader());
Don't forget calling that before usemvc

Securing system-generated nodes in firebase

I've been going through the rules guide but haven't found an answer to this.
App users are able to submit "scores" of different types, which are then processed in JS and written to a "ranking" node. I have it set up so that every time a new score is submitted, the rankings are automatically recalculated and a new child is written if the user doesn't exist or updated if the user exists.
My question is how to secure this "ranking" node. Everyone should be able to read it, nobody except the system should be able to write it. This would prevent people from submitting their own rankings and aggregate scores.
EDIT
This is the operation:
Ref.child('rankings').child(uid).once('value', function (snapshot) {
if (snapshot.exists()) {
snapshot.ref().update(user); //user object created upstream
} else {
var payload = {};
payload[uid] = user;
snapshot.ref().parent().update(payload);
}
});
How would I add custom authentication to this call? Also, since I'm using AngularJS, is there any way to hide this custom token or would I have to route it through a backend server?
The key part of your problem definition is:
only the system should be able to write it.
This requires that you are able to recognize "the system" in your security rules. Since Firebase security is user-based, you'll have to make your "system" into a user. You can do this by either recording the uid from a regular user account or by minting a custom token for your "system".
Once you have that, the security for your ranking node becomes:
".read": true,
".write": "auth.uid == 'thesystem'"
In the above I assume you mint a custom token and specify thesystem as the uid.

CakePHP & Change user's profile

I have started learning cakePHP and now I am facing the following problem. How can allow my users to change their profile (their info in the DB).
This is my model -> http://bin.cakephp.org/view/798927304 I use these validations when someone tries to register .
This is my method for editing profiles: http://bin.cakephp.org/view/841227800
First I check does the user have the permission to edit this profile (is the profile his own).
Then get the desired id and try to save the request->data... But unfortunately without success.
And last this is my view -> http://bin.cakephp.org/view/1798312426
The only things I want to make are:
-Change their email (if they add new email)
-Change their social profiles (if the add them)
-Change their password (if they add it)
Can you guide me to do these things?
Thanks in advance!
Typically, when you call a save, as in:
$this->User->save($this->request->data)
The data in $this->request->data is cleared by default. In your edit method, you have an if statement below that is using the same save again.
The default functionality which I assume you have copied from a cakebaked edit method typically does the save and uses the returned logic to power that if statement. The second time you call it, you might be getting a false returned, which is likely skipping over that if statement.
To debug this, I suggest several of these in different locations:
debug($this->request->data);
Also, debug printouts are cleared on redirect, so in the mean time, you may want to comment out the redirect inside the if statement like so:
if ($this->User->save($this->request->data)) {
$this->Session->setFlash('Успешно променихте профила си.', 'success_message');
//$this->redirect(array('action' => 'profile'));
}
if($this->Auth->user() && $this->Auth->user('id') == $id) {
$this->User->read(null, $id);
$this->User->set(array(
'email' => $this->data['User']['email'],
'password' => $this->data['User']['password'],
'social_profile' => 'bla bla'
));
$this->User->save();
// etc
may do what you're after.
more # http://book.cakephp.org/view/1031/Saving-Your-Data

is FB's db (Oracle?) of "available username" in 'real-time' or gets updated dayly/wekly or never?

Scenario:
there is FB user with Facebook (FB) ID and personal profile.
that FB ID also has one Page.
Now that ID wants to assign an available username "Myusername" to its Page (not assigning that available "Myusername" to ID itself).
Error occurred and available "MyUsername" got assigned to ID .
In order to correct that, and to release "MyUsername" to the availability status,
ID's username "MyUsername" is changed to "NewReplacingUseername" .
However, when then trying to assign "MyUsername" (expected to be now AGAIN availabe) to the ID's Page, FB returns "Username not availabe".
However,
https://graph.facebook.com/MyUsername
returns
{
"error": {
"message": "(#803) Some of the aliases you requested do not exist: MyUsername",
"type": "OAuthException"
}
}
which should mean that "MyUsername" IS available !
Any help ?
========================
#OffBySome
thanks for pointing to that FAQ.
But that FAQ use terminology
"securing" a username
and
"diffrent account".
But this is NOT "different" account.
Page belong to the same ID account to which username was initially (arroneously) given but later that username to ID itself was replaced with NewUserName in order to free original Username to be given to the Page of same account to which ID belongs to.
As for "securing" , it is not anymore "secured" as it was replaced with NewUsername.
I need tech confirmation: Does FB store FOREVER any 'username' ever typed, even in error,
even if an account, who typed it in the first place, REPLACED it with something different, i.e. it is not used anymore / it is abandon ?
And, once again, this is within SAME account !
You cannot transfer a user name. Once it has been assigned it cannot be re-assigned so that is why you are getting that error message. This is documented on their FAQ:
Can I transfer my username to another account? Once you have secured a
username, it is not possible to transfer it to a different account on
Facebook. Also, when an account is removed from the site, its username
will be unavailable. Facebook does this for security reasons, namely
to prevent username squatting.

Resources