Symfony2 authenticating users through a webservice - web-services

I'm currently dealing with Symfony2's Security component.
I try to authenticate users against a webservice. To authenticate a user, I have to provide to the webservice a username and a password.
I know that I've got to create a class that implements UserProvider. But the loadUserByUsername function doesn't fit my webservice needs : in order to authenticate a user, it ask for both username and password whereas the UserProvider's function only requires username.
Here is a similar question to the problem I face : Symfony2 authentication without UserProvider
I've been struggling on this problem for a couple of days...

I fixed this problem in that way:
services.yml:
services:
user_provider:
class: "%my_class%"
arguments: ["#service_container"]
WebServiceUserProvider.php
/**
* #param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->apiClient = $container->get('api_client');
$this->request = $container->get('request');
}
and use $password = $this->request->get('password'); in your loadUserByUsername method

One way of accomplishing this would be to load the user by the username and then validate the password. If the a user exists for the given username and the password entered matches with the password of that user, then authenticate the user.
Example:
public function userLogin($username, $password)
{
$em = $this->getEntityManager();
$query = $em->createQuery('SELECT u FROM VenomCoreBundle:User u WHERE u.username = :username OR u.email = :username AND u.isDeleted <> 1 ')
->setParameter('username', $username);
try {
$entity = $query->getSingleResult();
if (count($entity) > 0) {
$encoder = new MessageDigestPasswordEncoder('sha512', true, 10);
$passwordEnc = $encoder->encodePassword($password, $entity->getSalt());
$userPassword = $entity->getPassword();
if ($passwordEnc == $userPassword) {
$tokenValue = $entity->getUserToken();
$profile = $entity->getUserProfile();
if(!$profile) {
return false;
}
$userName = $profile->getFullName();
$response = array(
'token' => $tokenValue,
'username' => $userName
);
} else {
return false;
}
}
} catch (\Doctrine\Orm\NoResultException $e) {
return false;
}
return $response;
}

Related

How do I fix request timeout when trying to sing up a user in cognito via .net

Does somebody know how to fix request timeout by gateway (504) when trying to register a user into cognito? I use it with AWS Api gateway. locally it runs with no problem, but when I upload it into AWS lambda it gets a request timeout.
When I have te code below with the await it timesout. When I leave the await away it will not timeout but it also will not register the user in cognito.
private static readonly string _clientId = DotNetEnv.Env.GetString("AWS_CLIENT_ID", null);
private static readonly string _poolId = DotNetEnv.Env.GetString("AWS_USER_POOL", null);
private static AmazonCognitoIdentityProviderClient CreateCognitoClient()
{
return new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials());
}
/*
* Method name: regsiterAsync
* #param1: user (User), contains the basic userdata for registering a user (email, username, password, name)
* returns: Response (object)
**/
public static async Task<Response> registerAsync(User user)
{
Response response = new Response();
/*
* Check if user already exists in our database.
**/
if (DbHandler.getUserByEmail(user.email) == null)
{
/*
* Create a signup request to be sent to amazon cognito.
**/
SignUpRequest signUpRequest = new SignUpRequest()
{
ClientId = _clientId,
Username = user.email,
Password = user.password,
UserAttributes = new List<Amazon.CognitoIdentityProvider.Model.AttributeType>
{
new AttributeType
{
Name = "email",
Value = user.email
}
}
};
try
{
/*
* Send singup request to amazon cognito
* Returns a SingUpRequest(object)
**/
using(var cognitoClient = CreateCognitoClient())
{
var signUpResult = await cognitoClient.SignUpAsync(signUpRequest);
}
}
catch (Exception e)
{
/*
* Incase that a error accoured by sending the SingUpRequest to cognito. Return a error response.
**/
response.status = "failed";
response.message = e.Message;
return response;
}
/*
* Add user to our database
**/
User storedUser = DbHandler.addUser(user);
/*
* Return response with success data
**/
response.message = "User successful registered.";
response.data = storedUser;
return response;
}
/*
* In case the user already exists in our database. Return a non successful response
**/
response.status = "failed";
response.message = "User already exists.";
return response;
You need to increase the timeout value of the lambda function under Basic settings section. Default value for timeout is 3 seconds and your function takes more than that.

BadMethodCallException Method username does not exist

I have a very weird problem. When I'm submitting the form, it throws an error with server-side validation.
BadMethodCallException
Method username does not exist.
LoginController.php
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $username = 'username';
protected $redirectTo = '/dashboard';
protected $guard = 'web';
public function getLogin()
{
if (Auth::guard('web')->check())
{
return redirect()->intended('dashboard');
}
return view('login');
}
public function postLogin(Request $request)
{
$auth = Auth::guard('web')->attempt(['username' => $request->username(),
'password' => $request->password(), 'active' => 1]);
if ($auth)
{
return redirect()->route('dashboard');
}
return redirect()->route('/');
}
public function getLogout()
{
Auth::guard('web')->logout();
return redirect()->route('/');
}
}
The problem is that you trying to access the input property as method, I mean $request->username() and same with password, there is no username method, that's why you are getting error. you can access input with input() method like $request->input('username') or via dynamic property $request->username
read more at docs

can i change user model credentials in loopback?

I am building an API for login and registration using loopback framework.
Loopback provides, by default, model User for login, register and other similar stuff. Default way to provide user's credentials in LoopBack is username-password/email-password but I want to use mobileNo-password/email-password as user's login credentials. So how can I do that? How can I change default credential option in User model?
You can achieve that in two ways:
If not using username field in User model, you can use it to store mobile number, mobileNo.
You have to edit user.js to accept mobileNo field as login credentials. User.login and User.normalizeCredentials are used for login process, so you can edit them like provided in the code snippet.
Note: Don't forget to add mobileNo to user.json
User.normalizeCredentials method
`User.normalizeCredentials = function(credentials, realmRequired, realmDelimiter) {
var query = {};
credentials = credentials || {};
if (!realmRequired) {
if (credentials.email) {
query.email = credentials.email;
} else if (credentials.mobileNo) {
query.mobileNo = credentials.mobileNo;
}
} else {
if (credentials.realm) {
query.realm = credentials.realm;
}
var parts;
if (credentials.email) {
parts = splitPrincipal(credentials.email, realmDelimiter);
query.email = parts[1];
if (parts[0]) {
query.realm = parts[0];
}
} else if (credentials.mobileNo) { //added mobileNo.
parts = splitPrincipal(credentials.mobileNo, realmDelimiter);
query.mobileNo = parts[1];
if (parts[0]) {
query.realm = parts[0];
}
}
}
return query;
};`
User.login method
`User.login = function(credentials, include, fn) {
.
.
.
.
.
if (!query.email && !query.mobileNo) {
var err2 = new Error('Mobile number or email is required');
err2.statusCode = 400;
err2.code = 'MOBILE_NUMBER_EMAIL_REQUIRED';
fn(err2);
return fn.promise;
}
}`

How to save all but one field in Doctrine + ZF2?

I have a User entity and in the edit Action I present a form to edit the user. I would like to have a password field available. If the password is blank, then I would like to update all field except the password, and if something is entered then all fields would be updated.
Here is my controller action.
public function editUserAction() {
$id = (int) $this->params()->fromRoute('id', 0);
if (!id) return $this->redirect()->toRoute('index', array('action' => 'users));
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$form = new UserForm($objectManager);
$user = $objectManager->find('Application\Entity\User', $id);
$form->bind($user);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
$data = $this->request->getPost();
if ($data->user['password'] == '') {
// how to save all but one field
}
else {
$objectManager->persist($user);
$objectManager->flush();
}
}
}
}
use the remove method:
vendor/zendframework/zendframework/library/Zend/Form/Fieldset.php
remove Remove a named element or fieldset
Parameters:
 
string
$elementOrFieldset
PHPDoc not found
Returns:
 
Type:
FieldsetInterface
if ($data->user['password'] == '')
{
$form->remove('password');
$objectManager->persist($user);
$objectManager->flush();
}

Codeigniter web services

I'm using Codeigniter 1.7. Does anyone have any experience of creating web services with PHP, particularly within the CodeIgniter framework? What are security measures need to consider while implementing web services? How to provide authentication with API keys?
Any Ideas?
It depends on the kind of web service you are inquiring about. Is the web service going to be a daemon for example? or a typical online web service. For either of these you must implement a RESTful type. RESTful meaning a stateless connection. This is where API keys are used; to identity a user for example.
Luckily Codeigniter is one with many libraries and extensions. An example of such libraries can be here: https://github.com/philsturgeon/codeigniter-restserver
Now for security concerns: API keys would replace sessions or any state. You would have to make full checks on the api. Many sites that implement APIs offer different solutions to the same end result.
Authentication with API keys are simple. You would check it against a storage type(database).
Here is a tutorial using codeigniter and the library linked previously: http://net.tutsplus.com/tutorials/php/working-with-restful-services-in-codeigniter-2/
This might be somewhat vague, but since you dont have any specific problems or apparent needs its hard to be specific.
EDIT:
In that case it would be better implementing a RESTful interface so that your iphone app can also use all of the user functionalities that your service provides. The best way would be to make everything accessible in one way. Meaning not having different controllers / models for the iphone connections and web connections.
So for example you could have the following controller:
<?php
class Auth extends CI_Controller{
public function login(){
//Check if their accessing using a RESTful interface;
$restful = $this->rest->check();
if($restful){
//Check for the API keys;
$apiKey = $this->input->get('apiKey');
$secretKey = $this->input->get('secretKey');
//If you have any rules apon the keys you may check it (i.e. their lengths,
//character restrictions, etc...)
if(strlen($apiKey) == 10 and strlen($secretKey) == 14)
{
//Now check against the database if the keys are acceptable;
$this->db->where('apiKey', $apiKey);
$this->db->where('secretKey', $secretKey);
$this->db->limit(1);
$query = $this->db->get('keys');
if($this->db->count_all_results() == 1)
{
//It's accepted the keys now authenticate the user;
foreach ($query->result() as $row)
{
$user_id = $row->user_id;
//Now generate a response key;
$response_key = $this->somemodel->response_key($user_id);
//Now return the response key;
die(json_encode( array(
'response_key' => $response_key,
'user_id' => $user_id
)
)
);
} //End of Foreach
}//End of Result Count
}//End of length / character check;
} else {
//Perform your usual session login here...;
}
}
}
?>
Now this is just a small example for performing these types of requests. This could apply to any type of controller. Though there are a few options here. You could make every request pass the apikey, and the secret each time and verify it at each request. Or you could have some sort of whitelist that once you have been verified the first time each request after that would be whitelisted, and or black listed on the opposite.
Hope this helps,
Daniel
<?php
//First Create Api file in controller name Api.php
/*
api call in postman
login :
email , password
http://localhost/demo/api/login
https://prnt.sc/pbs2do
register (user): :
fullname , email , password , recipeunit
http://localhost/demo/api/signup
https://prnt.sc/pbs3cc
profile and list (user profile and all user ) :
View Profile : email, if all then pass blank
http://localhost/demo/api/userlist
change password :
http://localhost/demo/api/change_password
email ,password ,newpassword , conformnewpassword (if needed)
https://prnt.sc/pbs3rt
*/
if(!defined('BASEPATH')) exit('No direct script access allowed');
require APPPATH . '/libraries/BaseController.php'; // this file will download first and pest in library
class Api extends BaseController
{
/**
* This is default constructor of the class
*/
public function __construct()
{
parent::__construct();
$this->load->model('api/signup_model','signup_model');
}
/**
* Index Page for this controller.
*/
public function index()
{
}
public function signup()
{
$this->signup_model->signup();
}
public function login()
{
$this->signup_model->login();
}
public function userlist()
{
$this->signup_model->userlist();
}
public function edit_user()
{
$this->signup_model->edit_user();
}
public function change_password()
{
$this->signup_model->change_password();
}
public function testpass()
{
$this->signup_model->testpass();
}
}
// then create model in model folder create api folder create signup_model.php file
//after that
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Signup_model extends CI_Model {
public function __construct()
{
parent::__construct();
$this->load->database(); /* load database library */
}
// User register (signin) process
public function signup($data = array())
{
// another db field update like dt_createddate
if(!array_key_exists('dt_createddate', $data)){
$data['dt_createddate'] = date("Y-m-d H:i:s");
}
if(!array_key_exists('dt_updateddate', $data)){
$data['dt_updateddate'] = date("Y-m-d H:i:s");
}
if(!array_key_exists('dt_updateddate', $data)){
$data['dt_updateddate'] = date("Y-m-d H:i:s");
}
$data['var_fullname'] = $this->input->post('fullname');
$data['var_email'] = $this->input->post('email');
$data['var_password'] =getHashedPassword($this->input->post('password')) ;
$data['int_recipeunit'] = $this->input->post('recipeunit');
// if(!empty($data['var_fullname']) && !empty($data['var_email']) && !empty($data['var_password']) ){ }
/* check emailid all ready exist or not */
$email_check=$this->input->post('email');
$this->db->select('var_email');
$this->db->from('tbl_user');
$this->db->where('var_email', $email_check);
$query = $this->db->get();
$user = $query->result();
if(!empty($user))
{
echo "{\"status\" : \"404\",\"message\" : \"Email all ready register\",\"data\":".str_replace("<p>","",'{}'). "}";
}
else
{
$insert = $this->db->insert('tbl_user', $data);
if($insert){
$this->db->select('var_email as email,var_fullname as fullname,dt_createddate as createdate');
$insert_id = $this->db->insert_id();
$query = $this->db->get_where('tbl_user', array('int_id' => $insert_id));
echo "{\"status\" : \"200\",\"message\" : \"User added sucessfully\",\"data\":".str_replace("<p>","",json_encode($query->row_array())). "}";
// return $this->db->insert_id();
}else
{
$message="Something Wrong";
echo "{\"status\" : \"400\",\"data\":".str_replace("<p>","",json_encode($message)). "}";
// return false;
}
}
}
/* Login user $email, $password*/
function login()
{
$email=$this->input->post('email');
$password=$this->input->post('password');
$this->db->select('int_id,var_email,var_password');
$this->db->from('tbl_user');
$this->db->where('var_email', $email);
$this->db->where('chr_status', 'A');
$query = $this->db->get();
$user = $query->result();
if(!empty($user))
{
if(verifyHashedPassword($password, $user[0]->var_password))
{
$this->db->select('var_email as email,var_fullname as fullname,dt_createddate as createdate');
$query = $this->db->get_where('tbl_user', array('var_email' => $email));
echo "{\"status\" : \"200\",\"message\" : \"Login sucessfully\",\"data\":".str_replace("<p>","",json_encode($query->row_array())). "}";
}
else
{
echo "{\"status\" : \"404\",\"message\" : \"Password does not match\",\"data\":".str_replace("<p>","",'{}'). "}";
}
}
else
{
echo "{\"status\" : \"404\",\"message\" : \"Invalid email \",\"data\":".str_replace("<p>","",'{}'). "}";
}
}
/* Fetch user data all or single */
function userlist()
{
$email=$this->input->post('email'); // post id of which user data you will get
if(!empty($email))
{
$email=$this->input->post('email');
$password=$this->input->post('password');
$this->db->select('int_id,var_email,var_password');
$this->db->from('tbl_user');
$this->db->where('var_email', $email);
$this->db->where('chr_status', 'A');
$query = $this->db->get();
$user = $query->result();
if(!empty($user))
{
$this->db->select('var_email as email,var_fullname as fullname,dt_createddate as createdate');
$query = $this->db->get_where('tbl_user', array('var_email' => $email));
$responce_json=json_encode($query->row_array());
echo "{\"status\" : \"200\",\"message\" : \"User data\",\"data\":".str_replace("<p>","",$responce_json). "}";
}
else
{
echo "{\"status\" : \"404\",\"message\" : \"Invalid email \",\"data\":".str_replace("<p>","",'{}'). "}";
}
}
else
{
$this->db->select('var_email as email,var_fullname as fullname,dt_createddate as createdate');
$query = $this->db->get('tbl_user');
$responce_json=json_encode($query->result_array());
echo "{\"status\" : \"200\",\"message\" : \"User data\",\"data\":".str_replace("<p>","",$responce_json). "}";
}
}
/* Update user data */
function edit_user($data = array()) {
$id = $this->input->post('id');
$data['first_name'] = $this->input->post('first_name');
/* $data['last_name'] = $this->input->post('last_name');
$data['email'] = $this->input->post('email');
$data['phone'] = $this->input->post('phone'); */
if(!empty($data) && !empty($id)){
if(!array_key_exists('modified', $data)){
$data['modified'] = date("Y-m-d H:i:s");
}
$update = $this->db->update('users', $data, array('id'=>$id));
if($update){
$message="User Update Sucessfully";
$responce_json=json_encode($message);
echo "{\"status\" : \"200\",\"data\":".str_replace("<p>","",$responce_json). "}";
}
}
else
{
return false;
}
}
/* change password */
function change_password()
{
$email=$this->input->post('email');
$password=$this->input->post('password');
$newpassword=$this->input->post('newpassword');
//$conformnewpassword=$this->input->post('conformnewpassword');
$this->db->select('int_id,var_email,var_password');
$this->db->from('tbl_user');
$this->db->where('var_email', $email);
$this->db->where('chr_status', 'A');
$query = $this->db->get();
$user = $query->result();
if(!empty($user))
{
if(verifyHashedPassword($password, $user[0]->var_password))
{
//if($newpassword==$conformnewpassword)
//{
$data['var_password'] = getHashedPassword($newpassword);
$update = $this->db->update('tbl_user', $data, array('var_email'=>$email));
$this->db->select('var_email as email,var_fullname as fullname,dt_createddate as createdate');
$query = $this->db->get_where('tbl_user', array('var_email' => $email));
echo "{\"status\" : \"200\",\"message\" : \"Password change sucessfully\",\"data\":".str_replace("<p>","",json_encode($query->row_array())). "}";
/* }
else
{
echo "{\"status\" : \"404\",\"message\" : \"New pass and conform pass does not match \",\"data\":".str_replace("<p>","",'{}'). "}";
} */
}
else
{
echo "{\"status\" : \"404\",\"message\" : \"Invalid old password \",\"data\":".str_replace("<p>","",'{}'). "}";
}
}
else
{
echo "{\"status\" : \"404\",\"message\" : \"Invalid email \",\"data\":".str_replace("<p>","",'{}'). "}";
}
}
/*
* Delete user data
*/
/* public function delete($id){
$delete = $this->db->delete('users',array('id'=>$id));
return $delete?true:false;
} */
}
?>