Below is a working example of my OpenId implementation. I use hyves.nl as the OpenId provider but this also works with me.yahoo.com and probably other OpenId providers as well (but not Google).
So far so good. But now I want to fetch the nickname and/or fullname from my hyves profile. But when I set nickname and/or fullname to true in the $props array I can't login anymore at all.
What am I doing wrong here?
class TestController extends Zend_Controller_Action
{
private $_sreg = null;
public function init()
{
$props = array('nickname' => false,
'email' => false,
'fullname' => false,
'dob' => false,
'gender' => false,
'postcode' => false,
'country' => false,
'language' => false,
'timezone' => false);
$this->_sreg = new Zend_OpenId_Extension_Sreg($props);
}
public function loginAction()
{
$consumer = new Zend_OpenId_Consumer();
if (!$consumer->login('hyves.nl', 'http://localhost/trouwcom/public/test/verify', 'http://localhost/trouwcom', $this->_sreg))
{
echo 'Login failed';
}
$this->_helper->viewRenderer->setNoRender();
}
public function verifyAction()
{
$consumer = new Zend_OpenId_Consumer();
if ($consumer->verify($_GET, $id, $this->_sreg))
{
echo 'VALID ' . htmlspecialchars($id);
$data = $this->_sreg->getProperties();
print_r($data);
}
else
{
echo 'INVALID ' . htmlspecialchars($id);
}
$this->_helper->viewRenderer->setNoRender();
}
}
Could it be this bug? http://framework.zend.com/issues/browse/ZF-5266
Don't know if you found your answer already. But if you didn't or anyone else is reading this question like me and having the same problem I just found the answer.
The problem with openId provider "hyves.nl" is that they don't return the verification parameters by $_GET but by $_POST.
# This works
$consumer->verify($_POST, $id, $this->_sreg);
Related
Am new here, but i need your help please.
Through couple of tutorials online, was able to get the GOOGLE LOGIN work perfectly on my Web App on my Xampp localhost server. But when I moved same code onto live Web App running on Linux Cpanel Server, got an error "403.shtml is not a valid controller name".
Here is the code.
Controller - Login.php
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Models\LoginModel;
class Login extends Controller
{
public $loginModel;
public $session;
public $email;
public $googleClient=NULL;
public function __construct(){
helper('form');
$this->loginModel = new LoginModel();
$this->session = session();
$this->email = \Config\Services::email();
include_once APPPATH.'Libraries/vendor/autoload.php';
$this->googleClient = new \Google_Client();
$this->googleClient->setClientId('clientID');
$this->googleClient->setClientSecret('SecretID');
$this->googleClient->setRedirectUri('https://example.net/login/gauth');
$this->googleClient->setAccessType('online');
$this->googleClient->addScope('email');
$this->googleClient->addScope('profile');
}
public function index()
{
$data = [];
//Here code for site login
//Google login button
$loginButton = '';
if(!session()->set("AccessToken"))
{
$loginButton = $this->googleClient->createAuthUrl();
$data['loginButton'] = $loginButton;
return view('login', $data);
}
else
{
return view('login', $data);
}
return view('login', $data);
echo view('includes/footer');
}
public function gauth()
{
$session = session();
$token = $this->googleClient->fetchAccessTokenWithAuthCode($_GET['code']);
if(!isset($token['error'])){
$this->googleClient->setAccessToken($token['access_token']);
session()->set("AccessToken", $token['access_token']);
$googleService = new \Google_Service_Oauth2($this->googleClient);
$data = $googleService->userinfo->get();
$currentDateTime = date("Y-m-d H:i:s");
$userdata=array();
if($this->loginModel->google_user_exists($data['id']))
{
//User ALready Login and want to Login Again
$userdata = [
'verification_code' => $data['id'],
'first_name' => $data['given_name'],
'last_name' => $data['family_name'],
'email' => $data['email'],
'profile_pic' => $data['picture'],
'last_modified' => $currentDateTime
];
$this->loginModel->updateGoogleUser($userdata, $data['id']);
session()->set("logged_user", $userdata['verification_code']);
}
else
{
//new User want to Login
$userdata = [
'social_provider' => Google,
'status' => active,
'verification_code' => $data['id'],
'first_name' => $data['given_name'],
'last_name' => $data['family_name'],
'email' => $data['email'],
'profile_pic' => $data['picture'],
'created_at' => $currentDateTime
];
$this->loginModel->createGoogleUser($userdata);
}
session()->set("logged_user", $userdata['verification_code']);
}
else
{
session()->setFlashData("Error", "Something went Wrong");
return redirect()->to(base_url());
}
//Successfull Login
return redirect()->to(base_url()."/home");
}
}
View - login.php
<div class="form-group">
<i class="bi bi-google px-3"></i> Login with Google
</div>
Looking forward to hear from you
Ok I simplified and tested your code and authentication works just fine. The problem is your user creation and/or redirection logic.
if (!isset($token['error'])) {
$googleService = new \Google\Service\Oauth2($this->googleClient);
$data = $googleService->userinfo->get();
// Login Success
} else {
// Login Failed
}
I'm using Socialite to get user information from facebook. All is going well but my redirect isn't working
Sub-routes
I read that it's not possible to do a redirect from a submethod, or
any method that's not in your routes.
But how else can i redirect the user after I logged them in?
My URL looks like this after the successfull facebook handshake
http://tmdb.app/auth/login/facebook?code=AQBTKNZIxbfdBruAJBqZ8xx9Qnz...
Code
class SocialController extends Controller {
public function login(Authenticate $authenticate, Request $request)
{
return $authenticate->execute($request->has('code'), $this);
}
public function userHasLoggedIn($data)
{
$user = User::where('provider_id', $data->id)->first();
if( !$user )
{
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'provider' => 'facebook',
'provider_id' => $data->id
]);
}
// NOT WORKING!
return redirect('test');
}
}
Your login function should be handling the redirect.
I'm guessing execute returns $data if the user is sucessfully logged in and false if not.
class SocialController extends Controller {
public function login(Authenticate $authenticate, Request $request)
{
if($data = $authenticate->execute($request->has('code'), $this))
{
$user = User::where('provider_id', $data->id)->first();
// maybe delegate the user creation to another class/service?
if( !$user )
{
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'provider' => 'facebook',
'provider_id' => $data->id
]);
}
return redirect('test');
}
return redirect('fail_view');
}
}
You can do it using PHP header function in Laravel sub method. I try it and works properly. Hope it can help you.
// You can using the following code
$url= url("about-laravel");
header("Location:" . $url);
exit;
// Or using the following code to redirect and keep set flash message
$result= $this->yourMethod(); // return redirect($this->route)->with('flash_message', 'I\'m Flash Message'); for TRUE or NULL for false
if( $result ){
return $result;
}
I'm currently working on a project using the Phalcon Framework that has pages with complex forms and a lot of inputs, to break it down nicely I'm dividing the forms into a step-by-step process.
How would one validate the form on each step before going to the next step and then save the whole form on the final step?
I can't seem to find anything documented about this sort of process as it likes to validate the form in it's entirety if I use the form builder.
Simple, just create a custom methods in your form class to validate any step, and the posted data from some step save into message class and store it into session by "stepX", when posted data is not valid just set defaults from post. When valid save it into session as i describe above.
For example how i mean "controller"
<?php
class MyController extends BaseController {
public function processStep1Action(){
$form = new MyForm();
if($this->request->isPost()){//im using my custom request class
if(!$form->isValid($this->request->getPost()){
//error messages goes here
$form->setDefaultsFromRequest($this->request); // it will set the filled data
}
else {
$messageClass = new MyMessageContainer();
$messageClass->setData($this->request);//inside parse requested data into message class, or parse it as $messageClass->name = $this->request->getPost('name');
$this->session->save('step1',$messageClass); //maybe it would be want to serialize it
//then redirect to the step 2 or x
}
}
}
}
So in the next step you can access data from sessions $this->session->get('step1'); so you can in final step load all posted data and store it into DB.
I hope this helps! :)
here is my form maybe it can be helpful for you.
<?php
namespace Manager\Library\Forms\User;
use Phalcon\Forms\Form,
Phalcon\Forms\Element\Email,
Phalcon\Forms\Element\Select,
Phalcon\Forms\Element\Password,
Phalcon\Forms\Element\Check,
Phalcon\Validation\Validator\Confirmation,
Phalcon\Validation\Validator\StringLength,
Phalcon\Forms\Element\Submit,
Phalcon\Validation\Validator\PresenceOf,
Model\Group;
class AddUser extends Form {
public function initialize()
{
$email = new Email('email');
$email->addValidators(array(
new \Phalcon\Validation\Validator\Email(array(
'message' => 'Nezadali jste email nebo má nesprávny tvar(email#domena.tld).'
))
));
$this->add($email);
$this->initGroupElement();
$password = new Password('password');
$password
->addValidator(new StringLength(array('min' => 6,'messageMinimum' => 'Nezadali jste heslo nebo je příliš krátke, minimální počet znaků je 6.')))
->addValidator(new Confirmation(array('with' => 'password-again',"message" => "Zadané hesla se neshodují.")));
$this->add($password);
$repeatPassword = new Password('password-again');
$this->add($repeatPassword);
$this->initializeProfileElements();
$active = new Check('active',array('value' => 1));
$this->add($active);
$this->add( new Submit('save') );
\Phalcon\Tag::setDefault('password', '');
\Phalcon\Tag::setDefault('password-again', '');
}
public function initializeEdit(){
$email = new Email('email');
$email->addValidators(array(
new \Phalcon\Validation\Validator\Email(array(
'message' => 'Nezadali jste email nebo má nesprávny tvar(email#domena.tld).'
))
));
$this->add($email);
$this->initGroupElement();
$password = new Password('password');
$this->add($password);
$repeatPassword = new Password('password-again');
$this->add($repeatPassword);
$this->initializeProfileElements();
$active = new Check('active',array('value' => 1));
$this->add($active);
$this->add( new Submit('save') );
\Phalcon\Tag::setDefault('password', '');
\Phalcon\Tag::setDefault('password-again', '');
}
protected function initGroupElement(){
$auth = \Core\Auth::getIdentity();
$groups = new Group();
// $groups->addColumns(array('id','name'));
//set global condition about Super Admin
$groups->addFilter('id', 1,'<>');
if($auth){
//set restrictions for main groups
if((int)$auth->group_id === 1){ //super admingroup
//no filter
}
else if((int)$auth->group_id === 2){ //admin group
$groups->addFilter('id', 1,'>');
}
else if((int)$auth->group_id === 6){//Provozovatel group
$groups->addFilter('id',array(3,6,7));
$groups->addFilter('public', 1,'=',true);
}
else { // other groups
$groups->addFilter('public', 1);
}
}
$groups = $groups->findFiltered();
$groupElement = new Select('group');
foreach($groups as $group){
$groupElement->addOption(array($group->id => $group->name));
}
$this->add($groupElement);
}
protected function initializeProfileElements(){
$forename = new \Phalcon\Forms\Element\Text('forename');
$this->add($forename);
$surname = new \Phalcon\Forms\Element\Text('surname');
$this->add($surname);
$street = new \Phalcon\Forms\Element\Text('street');
$this->add($street);
$postal = new \Phalcon\Forms\Element\Text('postal');
$this->add($postal);
$city = new \Phalcon\Forms\Element\Text('city');
$this->add($city);
$ic = new \Phalcon\Forms\Element\Text('ic');
$this->add($ic);
$dic = new \Phalcon\Forms\Element\Text('dic');
$this->add($dic);
}
public function setDefault($fieldName,$value){
\Phalcon\Tag::setDefault($fieldName, $value);
}
public function setDefaults($object){
if($object instanceof \Model\User){
$this->setDefaultsFromObject($object);
}
else if($object instanceof \Phalcon\Http\Request){
$this->setDefaultsFromRequest($object);
}
}
protected function setDefaultsFromObject(\Model\User $user){
$profile = $user->getRelated('\Model\Profile');
\Phalcon\Tag::setDefaults(array(
'email' => $user->email,
'group' => $user->group_id,
'active' => $user->active,
'forename' => $profile->forename,
'surname' => $profile->surname,
'street' => $profile->street,
'city' => $profile->city,
'postal' => $profile->postal,
'ic' => $profile->IC,
'dic' => $profile->DIC
));
}
protected function setDefaultsFromRequest(\Phalcon\Http\Request $request){
\Phalcon\Tag::setDefaults(array(
'email' => $request->getPost('email'),
'group' => $request->getPost('group'),
'active' => $request->getPost('active')
));
\Phalcon\Tag::setDefaults(array(
'forename' => $request->getPost('forename'),
'surname' => $request->getPost('surname'),
'street' => $request->getPost('street'),
'city' => $request->getPost('city'),
'postal' => $request->getPost('postal'),
'ic' => $request->getPost('ic'),
'dic' => $request->getPost('dic')
));
}
}
In addition to Kamil's answer, another option to consider is to use Javascript on the front-end to handle your multi-step form. This will add some complexity as you will need to have the javascript to handle the form steps and do preliminary validation, but it only requires a single submit where you can validate content within a single method.
Cake is not saving the cookie, at least not that I can see, and when I revisit the page I am not auto logged in.i actually want to implement the 'remember me functionality '.i am using this component
https://github.com/ceeram/Authenticate/wiki/Set-Cookie
here is my code
login.ctp
echo $this->form->create();
echo $this->form->input('email');
echo $this->form->input('password');
<?php echo $this->Form->checkbox('remember_me', array('hiddenField' => false,'name' => 'remember_me'));?>
echo $this->form->end('submit');
?>
UserController
<?php
class UsersController extends AppController {
public $components = array('Cookie');
public function beforeFilter() {
parent::beforeFilter();
$this->Cookie->type('rijndael');
$this->Security->requireSecure('login');// for security
$this->Auth->authenticate = array(
'Authenticate.MultiColumn' => array(
'fields' => array(
'username' => 'email',
'password' => 'password'
),
'columns' => array('email', 'mobileNo'),
'userModel' => 'User',
)
);
}
public function index(){
}
public function login() {
$this->layout='userdefault';
if ($this->request->is('post')) {
//$this->Auth->logout();
$cookie = $this->Cookie->read('Auth.User');
debug($cookie);
if ($this->Auth->login()) {
$this->_setCookie($this->Auth->user('id'));
$this->redirect('/users/controlpanel');
} else {
$this->Session->setFlash('Incorrect Email/Password Combination');
}
}
}
protected function _setCookie($id) {
if (!$this->request->data('User.remember_me')) {
return false;
}
$data = array(
'username' => $this->request->data('User.email'),
'password' => $this->request->data('User.password')
);
$this->Cookie->write('User', $data, true, '+1 week');
return true;
}
public function logout() {
$this->redirect($this->Auth->logout());
}
public function controlpanel(){
$this->layout='controlpaneldefault';
}
}
?>
and also tell me how can i check or debug the cookie to check that whether my cookie saving or not or if debugging is not possible then tell me how can i set the name of the cookie so i go in the browser cookies and search the cookie with name
insert exit(); after debug($cookie); for check cookie data.
in my Zend Framework project, I use a Service Layer, however I don't really know where to handle errors.
For example, let's say I've a UserService::updateUser($data);
What if I've:
$data = array(
'userId' => 2,
'firstName' => 'Jane',
'lastName' => 'Doe',
);
And user with id 2 doesn't exist?
Where and how would you handle such errors?
You can forward to a specific controller to handle all your business errors, like this :
if ($error=true)
return $this->_forward('standarderror', 'businesserror', 'default',
array('msgtitle' => $this->view->translate('item_not_found'),
'msg' => $this->view->translate('item_not_found_msg')));
and where your BusinesserrorController looks like :
class BusinesserrorController extends Zend_Controller_Action {
public function init() {
$this->_helper->viewRenderer->setNoRender();
}
public function standarderrorAction() {
$msgtitle = $this->_getParam('msgtitle');
$msg = $this->_getParam('msg');
$this->view->errortitle = $msgtitle;
$this->view->errormessage = $msg;
$this->view->nextstep = $this->view->translate('return_to_the_homepage');
$this->view->nextstepurl = "/";
echo $this->render('error/businesserror', null, true);
}
}
you can parametrize the forwarded url as well ;)