Manually encrypt user password in Symfony php - php

I have a need to manually encrypt the password in the same way Symfony does it.
$user->setPlainPassword($password);
$userManager->updateUser($user);
This is application code that saves the user password. But it is obviously encrypted (not plain as method says).
How can I manually get the same result for given password?
EDIT1:
The problem is that I want to authenticate user manually in users controller code. I have readable username and password that comes as parameters. I want to return 401 if they to not exist in database.

Symfony comes with a useful command to encode a password the same way it does:
bin/console security:encode-password 'your_plain_password' 'AppBundle\Entity\YourUserClass'

Try this in your controller action:
$encoder = $this->get('security.encoder_factory')->getEncoder($userClass);
$encodedPassword = $encoder->encodePassword($plainPassword);

In newer Symfony versions (5.3+) you can do it by running CLI command:
bin/console security:hash-password

Related

symfony 3 FOSUserBundle Bcrypt password hasher

does anybody know how brypt hashes for passwords, used in Symfony 3 with FOSUser Bundle (default parameters) can be generated (online service or php function(preferred))? For example, for password 111 I have the following hash: $2y$13$zGCO1RyfbDZovNY9tWOETuXuG/NghlNqimTICEI1r15podQMOp.e2
I have tried several online generators but still could not reproduce this hash. Any Ideas? Is it possible to use hash generated 'separately' from Symfony? Thank you
When a tried to execute it from Controller this was the result:
[Symfony\Component\Console\Exception\CommandNotFoundException] There are no commands defined in the "fos:user" namespace.
the command is not a service or is not public(by fos_user) IDK.
I did it this way
public function changePasswordAction(Request $request){
...
$manipulator = $this->get('fos_user.util.user_manipulator');
$manipulator->changePassword('jimorales', '123');
...
return new Response('password changed!');
}
before/after you can add your own logig
Hope it helps!!

Laravel Passport Password Grant - Client authentication failed

After hearing a lot about laravel passport, i thought of implementing it into my new project where my requirement is to create an API that'll be used in a mobile app.
So my mobile app is a client, which will further have its users.
I followed the steps mentioned by Taylor and also read about it here. In a nutshell I followed these steps:
Installed laravel/passport.
Created a website user.
Generated passport keys php artisan passport:install
Generated client_id and client_secret using php artisan passport:client
Added redirection and callback routes in web.php
Authorized the user and got the final access token.
Then I tried calling api/user( with Header Authorization containing value Bearer eyJ0eXAiOiJKV1...(token)
I received the data. Pretty simple and neat.
But my app users won't have these details. So I thought of configuring Password Grant Tokens which fits perfectly in my requirement.
Now starts the real headache. I've been trying to set this up for the last 3 days and continuously getting
{"error":"invalid_client","message":"Client authentication failed"}
I've tried almost every guide I followed online: Redirection Issues, Add Atleast One Scope Solution, P100Y Issue etc.
But I'm still getting invalid client error. Here's what I'm passing through POSTMAN to oauth/token:
{
"grant_type": "password,"
"client_id": "3,"
"client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"
"username": "test#gmail.com,"
"password": "123456,"
"scope": ""
}
Any help would be appreciated.
Check your credentials first if they are correct, Secondly check your model table which uses \Laravel\Passport\HasApiTokens trait that whether it contains email column, because by default it is used to identify user when validating credentials. if your table has username column or any other column which is used in validating credentials you must define a function findForPassport in that model. like this,
public function findForPassport($username) {
return self::where('username', $username)->first(); // change column name whatever you use in credentials
}
I use username and password column to validate a user,
in {project_directory}\vendor\laravel\passport\src\Bridge\UserRepository.php
this function validates your credentials,
public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity)
{
if (is_null($model = config('auth.providers.users.model'))) {
throw new RuntimeException('Unable to determine user model from configuration.');
}
if (method_exists($model, 'findForPassport')) { // if you define the method in that model it will grab it from there other wise use email as key
$user = (new $model)->findForPassport($username);
} else {
$user = (new $model)->where('email', $username)->first();
}
if (! $user || ! $this->hasher->check($password, $user->password)) {
return;
}
return new User($user->getAuthIdentifier());
}
notice the second if statement and you will get to know what is happening there.
hope this help :)
This might help point you in the right direction because we're implementing the password grant ourselves.
1 - On your step 4 instead of running this:
php artisan passport:install
run the following to create your password grant Client:
php artisan passport:client --password
The above command will give a followup question to set the name of your Password Grant Client. Be sure to get the id and secret of this new record in your database.
2 - Your POSTMAN Post request object should be wrapped inside an object similar to the following:
'form_params' => [
'grant_type' => 'password',
'client_id' => 'my_client-id',
'client_secret' => 'my_client-secret',
'username' => 'username or email', <-pass through variables or something
'password' => 'my-user-password', <- pass through variables or something
'scope' => '',
],
Update 1 10/12/2016:
On further investigation of this issue I ran into the exact same spot you're at and was forced to dive into the rabbit hole of passport.
Currently from what I'm seeing the system has set the client identifier as 'authorization_code' when it needs to be 'password'. I'm researching how to resolve this issue you're having as I've ran into it too. I will post code to help people follow along where I've been and what I've been doing but it's 2:40 am right now so I need some sleep.
Update 2 10/12/2016
Been debugging the issue for 7 hours now. There is a method within passport that validates the client. This method takes the inputs you've added in the object (mentioned above) and attempts to get the Client Entity through a client repository class based on what you've passed in. If a Client is found it will then be checked to see if an instance of the Client Entity truly exists within the Client Entity Interface which LOOKS like it pulls in the Client's credentials from the database. However, there is a block of code which returns NULL From what I'm getting in my testing. ALL fields are being introduced properly so far but there seems to be a mix-up between the repository and the interface. Which is causing the error to be thrown.
In the end I feel I'm getting close to solving this issue. Your patience is greatly appreciated. =)
Update 3 10/12/2016
After a long period of debugging I've found the initial problem. There were fields that weren't matching up. In short, it's a setup issue.
SO
The solution in this case is:
DOUBLE CHECK ALL FIELDS In the database with ALL credentials being passed in. Right down to periods, dashes, spaces passwords, client id, client secret, VALID redirect URIs/URLs, grant_types, and scopes (if you're using them):
Make sure the client in the database has an ENUM of 1 under the "password_client" column, if not you need to create one using the mentioned php artisan command above, which I'll reference here:
php artisan passport:client --password
Make sure the secret you're passing in matches what is listed for that client in your database character for character
Make sure the id you're passing matches and is of an integer data type.
Make sure there is a name of some sort for the client
Do not worry about the user_id column when using password grants
make sure the route is correct
Make sure the email your entering in (username) is an actual user inside of your users table within your database (or whatever table you customized the laravel 5.3 system to accept as your users table, I will add a link on how to customize laravel 5.3 system to accept a different users table as default if any need it).
Make sure the grant_type is spelled correctly
Make sure you're set up to accept the response bearer token (meaning the access_token and refresh_token).
Other than that, the initial steps I've outlined in the above part of this Answer should put you back on the right track. There are others here who did mention some similar steps that are helpful but address the same error that is related to a seperate issue as well (which I'm sure is a result of a setup issue related to their specific system setup).
I hope this helps though.
Have yo try running php artisan config:cache after all the passport commands.
use the below code to generate an access token, it has worked for me before:
$request->request->add([
'client_id' => '2',
'client_secret' => 'm3KtgNAKxq6Cm1WC6cDAXwR0nj3uPMxoRn3Ifr8L',
'grant_type' => 'password',
'username' => 'support#eliteride.co.uk',
'password' => 'pass22'
]);
$tokenRequest = $request->create('/oauth/token', 'POST', $request->all());
$token = \Route::dispatch($tokenRequest);
{"error":"invalid_client","message":"Client authentication failed"}
means that the client_id and client_secret you're currently sending is one of the following:
client_id and client_secret being sent is not registered in your oauth server
client_id and client_secret being sent is not of the grant type that you specify in the post body
For me, the password_client column value for that particular client
was 0. i manually changed it to 1 but it didn't help. – Kanav Oct 4 at
3:25
As I read your comment to some of the answer makes this one is obvious that you use the wrong type of client_id and client_secret for your password grant flow, so your case was the latter. You can verify that by finding the entry in oauth_clients table for your supplied client_id and client_secret
"grant_type": "password,"
"client_id": "3,"
"client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"
SELECT * FROM oauth_clients WHERE id = 3 AND secret = '8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g' AND password_client=1;
in your oauth_clients table to check that whether your supplied client_id and client_secret exists for password grant flow in your oauth server. And also you don't manually change the type of client by simply switching the value of that column, you have to create a new client for password grant type.
php artisan migrate
This command will migrate the laravel/passport migration file to generate two default clients for each type that laravel/passport currently supported. You can also create a client for password grant flow with
php artisan passport:client --password
When you have a new client for password grant type, try POSTing again to /oauth/token to generate a token with your new generated client_id and client_secret
Make sure you are not trying to obtain a token with a hashed client_secret...
If you are hashing the client secrets with Passport::hashClientSecrets(); within AppServiceProvider, the tokens generated will only be shown in the terminal output once. Loose this token and it is lost forever.
I was in a rush when I set my passport up and forgot that I was hashing the generated client secrets...
My request body should have contained a non-encrypted client secret, but instead I copied and pasted an encrypted secret from the database.
To fix this, either save your client secrets right away, or remove Passport::hashClientSecrets(); and create a new client.
I had the same issue, and got fixed by setting basic.auth headers, with client_id as username and secret as password.
Then it worked fine.
Check thoroughly the Grant Type.
{
"grant_type": "password",
"client_id": 2,
"client_secret":
"username": ,
"password":
"scope": ""
}
In the above example, it says password. Now check the table: oauth_clients
and make sure that the value of column password_client = 1
or look for the entry with the password_client = 1
Try commenting out this line Passport::hashClientSecrets(); in the AppServiceProvider file. You cant use hashed client secrets.
I have managed to get the Laravel Passport - Password_Grant_Token working through RESTED(POSTMAN like service) without any additional controllers or middlewares. Here is how I've managed to do it!
Install the default Auth-Scaffolding in laravel doc's here
Install the passport doc's here
Register a user through auth-scaffolding
Goto RESTED or POSTMAN, or any other like service
Check data in oauth_clients table for your form_params
With RESTED through Request_body_form_data not headers write yours forms_params and send a POST request to */oauth/token (full url required)(required form_params are grant_type, client_id, client_secret, username and password)
You should get in return an object with 4 keys (token_type, expires_in, access_token & refresh_token) and a status of 200 OK.
If all was succesfull so far...
Open another RESTED window:
Send a GET request to /api/user (again full url required)
In headers write 2 name-value pairs (Accept => application/json, Authorization => Bearer ACCESS_TOKEN_GOTTEN_IN_PREVIOUS_REQUEST (to /oauth/token)
And that should be it. You should get an user object as response from /api/user.
Check the redirect/callback url when the client is set up on the passport server. Check the entry where you get the client ID and secret from that the Redirect URL is correct.
I was getting the same error and found the Redirect URL wasn't correct.
It needs to be pointing to the /callback route (in the examples that Taylor gives)
Try creating a new password client using php artisan passport:client --password
then most probably an user wont be assigned to that password client. edit the database row and add an exsting user id to it.
{
"grant_type": "password,"
"client_id": "" <- edited and added user id
"client_secret": "8BU......," <- new secret
"username": "test#gmail.com," <- email of above added user id
"password": "123456,"<- password
"scope": ""
}
Hope you will be able to get token now
I was also facing the same issue , i got the solution from this link. Please check that.
https://github.com/laravel/passport/issues/71
It says that :
You make a call to /oauth/token just like you always would to get your token. But do so with a grant_type of custom_request. You'll need to add a byPassportCustomRequest($request) method to your User model (or whatever model you have configured to work with Passport). That method will accept a Illuminate\Http\Request and return the user model if you are able to authenticate the user via the request, or it will return null.
if you tried everything and still it's not working means try this solution!!
just give scope *.
$query = http_build_query([
'client_id' => 1,
'redirect_uri' => 'http://localhost:3000/callback',
'response_type' => 'code',
'scope' => '*'
]);
in my case this is the solution. I have checked
I had the same problem. When you execute php artisan passport:install it issues you with two types of secrets, one for CLIENT grant type, and other for PASSWORD grant type.
I was using the CLIENT secret to issue PASSWORD tokens. Once I changed that up, I was able to generate the access_token and refresh_token normally.
In my case, the solution was to wrap it inside Form-data,
don't miss it out if you use normal parameters with the postman, it won't work,
make sure to use a body request set to FORM-DATA.
Hopefully this will save someone the hour I spent debugging this problem:
I went down the rabbit hole to find out why authentication wasn't working. Turned out I was hashing my password in my UsersTableSeeder twice by accident, which is why the hash check failed.
Might be worth checking if the other answers listed don't work for you.
I fixed it by making sure that in the oauth_clients table my client has column password_client set to 1:
Source: https://github.com/laravel/passport/issues/589#issuecomment-357515110
There may be quite scenarios for the above issue.I will explain it one
by one. You always need to pass application/json header .
Make sure the client id and secret is in the oauth_clients and you
passed those parameter correctly.In order to generate those client id
and secret use php artisan passport:install.
Make sure to use password
grant client . To identify that goto oauth_clients table and check if
password_client is set to 1 and personal_access_client is set to 0 and
revoked to 0 . I hope this will solve the issue . Thank you
In laravel 9.x, the error : Client authentication failed will also be thrown if you have Passport::hashClientSecrets() in your AuthServiceProvider boot method. Am not sure why, but removing it just saved me time.
I was having this same issue, I tried all the above solutions, no success.
So i just reloaded the tables, recreated the user, the passport client and solved. My solution was reset everything:
php artisan migrate:fresh (will clean your database.)
php artisan passport:client --password
you can define a two variables like
$client_id = '111';
$client_secret = '1212';
and the condition is in your function like this
protected $clientID = '578324956347895';
protected $clinetSecret ='hflieryt478';
public function index(Request $request)
{
if (!($request->input('clientID') && $request->input('clinetSecret'))) {
return false;
}
$project = User::all();
return $project
}

Symfony 2 - not authenticating user using bcrypt

I add a user to the database.
I encode their password using bcrypt encryption:
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword($user->getPassword(),$user->getSalt());
$postData->setPassword($password);
This all persists to the database just fine.
On my User Entity my getSalt() method returns null:
public function getSalt(){
return null;
}
Now when I try to authenticate the symfony logs tells me that I am entering bad credentials.
However...
If i use this site to encrypt my password with bcrypt:
http://bcrypthashgenerator.apphb.com/
Then enter the result into the database manually and try and authenticate with the users password i have updated with the results from the above link,
It works fine.
So there is something I have not set, that when I am encrypting the password that symfony cannot authenticate against it.
I have tried the setting a salt on the getSalt(), setting it to an empty string.
EDIT
I am using php 5.5.9
I have also tried using the BCryptPasswordEncoder($cost) class,
setting the cost on the __construct the same as what's in my security.yml
and it still does not authenticate.
EDIT
I have also tried installing this class via composer to as suggested here.
EDIT
If I use the php method:
password_hash('testertester',PASSWORD_BCRYPT,array('cost'=>13));
It authenticates perfectly.
So its something to do deeper in Symfony. I'll keep digging.
Still no luck :-/
I am scouring the web to no avail so far.
Any help would be greatly appreciated.
Ad
I was passing in the existing entity object not the submitted data object!!
$postData = $form->getdata();
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword($user->getPassword(),$user->getSalt());
$postData->setPassword($password);
Note this line here:
$user->getPassword() needed to be $postData->getPassword()
$password = $encoder->encodePassword($postData->getPassword(),$user->getSalt());
You live and learn ay!

FOSUser + BorisMorel LdapBundle

I'm trying to integrate BorisMorel LdapBundle with FOSUser following this guide: Using a custom user manager with LDAP authentication
My objective is to authenticate by using LDAP and then storing the LDAP data in my fosuser table.
I've got to the point where the data is correctly retrieved from the LDAP and stored in the fosuser table. I don't want it to store the password on the database, because there's no use on it, as I prefer the password being validated using the LDAP on each login.
The problem is when I get to this point:
C:\xampp\htdocs\Symfony2\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider.php
In function:
public function authenticate(TokenInterface $token)
It calls the function:
$this->checkAuthentication($user, $token);
Which resolves this function:
checkAuthentication(UserInterface $user, UsernamePasswordToken $token)
Which is in this file:
C:\xampp\htdocs\Symfony2\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider.php
Because it checks the password using this:
encoderFactory->getEncoder($user)->isPasswordValid($user->getPassword(), $presentedPassword, $user->getSalt())) {
throw new BadCredentialsException('The presented password is
}
As the password on the fosuser table is empty, the authentication always fails, even if it already passed the LdapBundle test.
What I'm missing? I'm guessing that the wrong validator is being used, but it's not described in the BorisMorel resources!.
Please help!

What Kind of Encryption is used by Sentry

I am building an iOS app for an already existing web application I created. The web app uses laravel and sentry to encrypt passwords. New users have to be able to be created from the iOS app.
The server that the web app talks to is written in php but does not use laravel or sentry.
The only sentry function I need is the one they use to encrypt passwords.
What function does sentry use to hash passwords? I am talking about Cartalyst\Sentry\Hashing\NativeHasher
I need to be able to duplicate this function and use it in a separate php file.
i've found this link : https://github.com/cartalyst/sentry/blob/master/src/Cartalyst/Sentry/Hashing/NativeHasher.php
and this code is what you want probably:
public function hash($string)
{
// Usually caused by an old PHP environment, see
// https://github.com/cartalyst/sentry/issues/98#issuecomment-12974603
// and https://github.com/ircmaxell/password_compat/issues/10
if (!function_exists('password_hash')) {
throw new \RuntimeException('The function password_hash() does not exist, your PHP environment is probably incompatible. Try running [vendor/ircmaxell/password-compat/version-test.php] to check compatibility or use an alternative hashing strategy.');
}
if (($hash = password_hash($string, PASSWORD_DEFAULT)) === false) {
throw new \RuntimeException('Error generating hash from string, your PHP environment is probably incompatible. Try running [vendor/ircmaxell/password-compat/version-test.php] to check compatibility or use an alternative hashing strategy.');
}
return $hash;
}

Categories