I am having problem with Auth component when I use $this->Auth->allow('index','view');
I am getting /users/login has resulted in too many redirects when I use $this->Auth->allow('*') it works fine. I am using cakephp 1.3.12 here is app_controller.php
class AppController extends Controller {
var $components = array('Auth','Session');
function beforeFilter(){
$this->Auth->allow('index','view');
}
}
I changed the app_controller.php
class AppController extends Controller {
var $components = array('Auth','Session');
function beforeFilter(){
$this->Auth->allow(array('index','view','display'));
}
}
users_controller.php
class UsersController extends AppController {
var $name = 'Users';
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('login','logout'));
}
function login() {
if ($this->Session->read('Auth.User')) {
$this->redirect('/', null, false);
}
}
routes.php
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
any suggestions?
Thanks
Don't know but you might want to check if you have any request actions.
"If you are using requestAction in your layout or elements you should allow those actions in order to be able to open login page properly."
http://book.cakephp.org/1.3/en/view/1257/allow
This had me stumped for the longest time.
Let's say you render an element somewhere in your template:
echo $this->element('comments');
And in views/elements/comments.ctp you have something that requests an action like
$comments = $this->requestAction('comments/index');
foreach($comments as $comment) {
// print stuff
}
In your CommentsController your have to:
function beforeFilter() {
$this->Auth->allow('index');
}
Notice you are requesting an index action from your comments controller in your element. That's why you have to allow 'index' for that specific controller.
I haven't seen this problem properly addressed anywhere. Hope that's what is causing your error.
its an array =)
$this->Auth->allow(array('index','view'));
your getting the too many redirects message becasuse the /user/login action is not accessible. So the server tries to display the login page, but it can't, because regular non-connected users dont have acces to /user/login. And when a user doesn't have access to a page, the server will redirect him to the login page... so you see, its an infinite loop.
The /user/login action should be authorized to everyone. Your Users controller should look like this:
class UsersController extends AppController {
var $name = 'Users';
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array('login','logout'));
}
function login(){
if ($this->Session->read('Auth.User')) {
$this->redirect('/', null, false);
}
}
//if you're using prefix routes.
function admin_login(){
$this->redirect('/users/login');
}
if this doesn't the problem, maybe you're redirecting the page in the routes.php
Hope this helps
you are doing it wrong.How can app can get to know that which of your controller action you are trying to controller.Do it from your controller.
remove this from app
$this->Auth->allow(array('index','view','display'));
try this in your app controller with needed change
$this->Auth->loginError = "Wrong credentials. Please provide a valid username and password.";
$this->Auth->authError = "You don't have sufficient privilege to access this resource.";
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'dashboard');
do this from your user controller
$this->Auth->userModel = 'User';
$this->Auth->allow('*');
And in your login dont do anything all of your redirect and all will be doing by app controller.
If you have any doubt regarding this mail me
jafarkv9#gmail.com
Related
I have a application where after update user should be redirected to previous page from pagination.
let's say there is a gridview and user is at page 3. Then he update some record at that page. There should be a redirect to index page 3. What if, while user is updating record, before save, he opens another controller/action in new tab. Then ReturnUrl is now that new action and after save the record he is updating, he is redirected to that new url.
I've tried to set in every action "index" Url::remember(); and then in action "update" - return $this->goBack().
Also return $this->redirect(Yii::$app->request->referrer);, but it stays at same page.
There is a way to store every index URL in session, but in large project that means many sessions.
You could provide the returnUrl to the link, say:
Url::to(['update','id'=>$model->url,'returnUrl'=> Yii::$app->request->url]);
Then in your controller, use $this->request->queryParams['returnUrl'] to redirect to the previousUrl.
To take it one step further, to always provide the returnUrl, you could extend the Url Helper class:
namespace app\helpers;
use yii\helpers;
class Url extends yii\helpers\Url
public function toRouteAndReturn($route, array $params = [], $scheme = false) {
$params['returnUrl'] = Yii::$app->request->url;
return parent::toRoute($route,$params,$scheme);
}
You could provide in your main config:
'on afterAction' => function($event) {
if(!Yii::$app->getResponse()->isSent && !empty(Yii::$app->getRequest()->queryParams['returnUrl']) {
Yii::$app->getResponse()->redirect(Yii::$app->getRequest()->queryParams['returnUrl']);
}
}
Then you could use app\helpers\Url::toRouteAndReturn() instead of yii\helpers\Url::toRoute() to have it return to the previous url.
You can try below Solution.
First in your index page, get current page url and encode it.
$current_url=base64_encode(\Yii::$app->request->getUrl());
Append this url with your update link as below.
'urlCreator' => function ($action, $model, $key, $index) use ($current_url) {
if ($action === 'update') {
$url = Yii::$app->request->baseUrl . '/controllerName/update?id=' . $model->id.'&prev='.$current_url;
return $url;
}
// ......
}
In Controller, in Update method decode url as below and use for redirection.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$prev=base64_decode($_REQUEST['prev']);
// ......
return $this->redirect($prev); // you will redirect from where update method is called
// ......
}
Isn't it quite easy to pass page param into your update url (<model/update>) like <model>/update?id=<id>&page=<page>?
in your index.php view, edit your ActionColumn as follow:
[
'class' => 'yii\grid\ActionColumn',
'urlCreator' => function ($action, $model, $key, $index) {
return \yii\helpers\Url::to([$action, 'id' => $model->id, 'page' => Yii::$app->request->getQueryParam('page', null)]);
},
],
As you can see, I'm getting page param from request url and pass it to models' action buttons
And when you click to update model, the page that we entered from is stored/placed in url.
Controller:
public function actionUpdate($id, $page = null)
{
$model = $this->findModel($id);
...
if($model->save()) {
return $this->redirect(['index', 'page' => $page]);
}
...
}
Finally, after we successfully update the model, the action redirects us to previous index page.
How to check if current page is homepage? In my header i want to show something only on homepage.
$header = new ViewModel(array(
'login' => $this->getAuthService()->hasIdentity(),
'controller' => $this->getRequest()->getControllerName(),
'action' => $this->getRequest()->getActionName()
));
In my view i have tried to find the homepage by finding index controller and index action but this is not working.
<?php
if($this->controller = 'index' && $this->action = 'index') {
echo 'home';
}
else {
echo 'not';
}
?>
Take a look at this ViewHelper or that get matched route in view.
You have to test if your called url is your "home" route. You cant test it by controller or action name because you could have more than one IndexController and indexAction. But you coul only have one route "home".
i am using facebook connect under codeigniter.after authentication i want to redirect on success method of my controller
here is my controller:
class Welcome extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->model('Facebook_model');
}
function index()
{
$fb_data = $this->session->userdata('fb_data');
$data = array(
'fb_data' => $fb_data,
);
$this->load->view('welcome', $data);
}
function topsecret()
{
$fb_data = $this->session->userdata('fb_data');
if((!$fb_data['uid']) or (!$fb_data['me']))
{
redirect('welcome');
}
else
{
$data = array(
'fb_data' => $fb_data,
);
$this->load->view('topsecret', $data);
}
}
function success()
{
$this->load->view('welcome_message');
}
}
my model for facebook api access:
class Facebook_model extends CI_Model {
public function __construct()
{
parent::__construct();
$config = array(
'appId' => '261066574000678',
'secret' => ' 79e11f65449988965362f58e9a4aabd7',
'fileUpload' => true, // Indicates if the CURL based # syntax for file uploads is enabled.
);
$this->load->library('Facebook', $config);
$user = $this->facebook->getUser();
// We may or may not have this data based on whether the user is logged in.
//
// If we have a $user id here, it means we know the user is logged into
// Facebook, but we don't know if the access token is valid. An access
// token is invalid if the user logged out of Facebook.
$profile = null;
if($user)
{
try {
// Proceed knowing you have a logged in user who's authenticated.
$profile = $this->facebook->api('/me?fields=id,name,link,email');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
$fb_data = array(
'me' => $profile,
'uid' => $user,
'loginUrl' => $this->facebook->getLoginUrl(
array(
'scope' => 'email,user_birthday,publish_stream', // app permissions
'redirect_uri' => 'https://sanjay.localhost.com/index.php/welcome/success' // URL where you want to redirect your users after a successful login
)
),
'logoutUrl' => $this->facebook->getLogoutUrl(),
);
$this->session->set_userdata('fb_data', $fb_data);
}
}
since i am testing this on localhost host,i also edited my host file and changed my localhost hostname to sanjay.localhost.com.redirect happens but not happens..i think may be because of querystring.when redirects happens redirect uri is
=">https://sanjay.localhost.com/index.php/welcome/success?state=ff5712299510defa&code=AQCaD-FAd1shuW#=
i am not understanding how to handle state and code inside of query string.
please help.
Thank you for contacting me on my blog. First of all, Facebook is discontinued the localhost support. Her is the link https://developers.facebook.com/bugs/128794873890320.
I have not developed any app using codeigniter, I use CakePHP but the auth follow should be same.
1. Create a fb_login function in user controller.
2. This function will follow this logic.
a. Use $facebook->getUser() to get user id.
b. Then use $facebook->api('/me') to be sure.
3.If you get FacebookApiException then send user to login with Facebook. If you use official SDK then the current url will be added to redirect url.
4.the Facebook will redirect your user after sign in. so you will get data using $facebook->getUser(). Save this data in session for further use in you app. then redirect user to you control page or any other page. CakePHP has setFlash() function wich show what ever msg set in the control panel in view. I think Codeignator should have some thing like this. If not you can simply set a msg in session and redirect user. Then unset the msg after showing the msg.
Here is full code
$uid = $facebook->getUser();
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
//echo $e->getMessage();
$uid = null;
}
$loginUrl = $facebook->getLoginUrl(
array(
'scope' => 'publish_stream,offline_access,email'
),''
);
if (!$uid) {
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
exit;
}
//search using uid on your user table to check if the use is returnign user or new user.
if($new_user ==1)
{
$this->Session->setFlash('please sign up');
//redirect to sign up
}
else
{
$this->Session->setFlash('you are good lad');
//reditect to control panel
}
I have a PHPunit test like this:
public function testUsersCanRegisterWhenUsingValidData()
{
$this->request->setMethod('POST')
->setPost(array(
'username' => 'user123',
'zip_code' => '43215',
'email' => 'me1#something.com',
'password' => 'secret',
'confirm_pswd' => 'secret',
));
$this->dispatch('/account/register');
$this->assertRedirectTo('/account/login');
}
and a User controller action called register like this :
public function registerAction()
{
// Instantiate the registration form model
$form = new Application_Model_FormRegister();
// Has the form been submitted?
if ($this->getRequest()->isPost()) {
// If the form data is valid, process it
if ($form->isValid($this->_request->getPost())) {
// Does an account associated with this username already exist?
$account = $this->em->getRepository('Entities\Account')
->findOneByUsernameOrEmail($form->getValue('username'), $form->getValue('email'));
if (! $account)
{ // do something
.............
..............
} else {
$this->view->errors = array(
array("The desired username {$form->getValue('username')} has already been taken, or
the provided e-mail address is already associated with a registered user.")
);
}
} else {
$this->view->errors = $form->getErrors();
}
}
$this->view->form = $form;
}
I get an error in this line :
$account = $this->em->getRepository('Entities\Account')
->findOneByUsernameOrEmail($form->getValue('username'), $form->getValue('email'));
It's caused by $form->getValue('username') being NULL because the form has not actually been submitted, instead PHPunit has dispatched the action and set up the POST variables.
How can I get this working?
Sorry everyone. I had commented out this line to try and study my problem:
// If the form data is valid, process it
if ($form->isValid($this->_request->getPost())) {
and it turns out that my input test input was not valid and you can't use $form->getValue to get the value of an invalid form.
I didn't get any answers because this line was not commented out in my post and would have worked. Slap head............MODS feel free to delete this post if you think it is no help to anybody.
I'm developing an iFrame Canvas application for Facebook using CakePHP, its Auth component, WebTechNick's Facebook plugin and OAuth for canvas pages (I've enabled this in the Facebook Developer app options). I would like users to be able to use the application after adding it to their profile (by requesting email and publish_stream permissions) by visiting http://apps.facebook.com/myapp/ or as a tab in their profile.
Requesting permissions is not the problem. The user is redirected to the permissions request page and then redirected to a callback method which requests an access_token, as per this tutorial.
After this callback the user is redirected back to http://apps.facebook.com/myapp/ which shows their personal index page. This is also where the problems start. As soon as the aforementioned URI is loaded, the browser asks for a form resubmission, this happens every time I reload http://apps.facebook.com/myapp/. This is the case because Facebook wants to pass the (expected) signed_request parameter and I'm wondering what to do with it. It's not an empty variable, so do I need another validation method or redirect, perhaps?
How should I handle the procedure for the signed_request parameter and, more importantly how to get rid of this form resubmission dialog?
Some of my methods, they might be a bit of a mess due to all the experimentation of the past day.
beforeFilter, login and callback methods, in my UserController.php:
function beforeFilter() {
parent::beforeFilter();
if (empty($this->permissions)) {
$this->Auth->allow('login', 'logout', 'callback');
}
}
function login() {
$session = $this->facebook->getSession();
$login_url = 'https://graph.facebook.com/oauth/authorize?client_id=' . FACEBOOK_APP_ID . '&redirect_uri=' . MY_APP_URL . '/users/callback/&type=user_agent&&display=page&scope=' . FACEBOOK_APP_PERMISSIONS;
if($session){
try {
$uid = $facebook_client->getUser();
$me = $facebook_client->api('/me', $params);
print($me);
} catch (FacebookApiException $e) {
error_log($e);
}
} else {
$this->set('authorise', true);
$script = '$(document).ready(function() { facebookRequestPermissions("'.$login_url.'");});';
$this->set('script', $script);
}
}
function callback() {
function callFb($url, $params) {
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_VERBOSE => true
));
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
$params=array('client_id'=>FACEBOOK_APP_ID, 'type'=>'client_cred', 'client_secret'=>FACEBOOK_APP_SECRET);
$url = "https://graph.facebook.com/oauth/access_token";
$access_token = callFb($url, $params);
$access_token = substr($access_token, strpos($access_token, "=")+1, strlen($access_token));
if ($access_token) {
$this->redirect(FACEBOOK_APP_URL);
} else {
echo 'An error has occurred';
}
}
The JavaScript in the login method refers to this jQuery function, the Facebook JavaScript SDK is initialised in $(document).ready():
function facebookRequestPermissions(login_url) {
FB.getLoginStatus(function(response) {
if (response.status !== 'unknown') {
top.location.href=login_url;
}
});
}
The JavaScript function should only fire when a user is logged in, if not, a different landing page is shown.
I use some methods in an overall AppControler:
class AppController extends Controller {
var $components = array('RequestHandler', 'Session', 'Auth', 'Facebook.Connect');
var $helpers = array('Form', 'Time','Html','Javascript', 'Session', 'Facebook.Facebook');
protected $facebook;
protected $permissions;
private $user;
function beforeRender() {
//Save the username if it isn't already present
if ((int)$this->Auth->user('id') != '' && (string)$this->Auth->user('username') == '') {
$data = array('id' => (int)$this->Auth->user('id'), 'username' => (string)$this->user['username']);
$this->loadModel('User');
$this->User->save($data);
}
if (!empty($this->user) && !empty($this->permissions)) {
$this->set('currentUser', $this->Auth->user());
}
}
function beforeFilter() {
$this->Auth->autoRedirect = false;
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
App::import('Lib', 'Facebook.FB');
$this->facebook = new FB();
$this->user = $this->facebook->api('/me');
$this->permissions = $this->facebook->api('/me/permissions');
}
}
EDIT:
This only seems an issue with Firefox. Chrome doesn't display the dialog, but instead does a silent refresh after which the signed_request parameter is empty, strangely enough. This isn't the case with Firefox, where the signed_request parameter remains the same after every prompted refresh (unless the iFrame content is cached), which is looping infinitely, it seems.
EDIT 2:
Still struggling with this, but I ended up disabling the OAuth 2.0 for Canvas option in the Facebook Developer application, which has resolved the form resubmission issue. Of course this is not a real solution, because OAuth 2.0 is becoming mandatory for canvas application on Facebook, I believe.
Since I can't test the whole thing I am not sure if this is right, but on the first sight your JavaScript function looks strange to me. It looks like you always redirect to the login url, although the user gave permission.
Refering to Facebook JavaScript SDK, the function should look like this:
function facebookRequestPermissions(login_url) {
FB.getLoginStatus(function(response) {
if (!response.session) {
top.location.href=login_url;
}
});
}
or, if you want to call .status:
if (response.status == 'unknown')
About your question concerning the signed_request: it is used to get some information, look at Authentication - Signed Request to see what exactly. You don't need another validation method.