Drupal 7 - how to allow an application to access a certain drupal url (from menu hook), either with super basic url-based auth or anonymously - authentication

I'm pretty new to drupal, so bear with me if I'm not using correct terms.
I'm trying to give a stupidly basic application access to a drupal url - this application cannot do any complicated authentication.
Otherwise, this drupal system needs authentication and all other menu hooks use 'access arguments' => array('access content')
Even before looking a solution for easy authentication method with drupal like http://user:password#server.com/awesome/member/12345, I've tried just giving anonymous access with the following code block in a drupal .module file
function awesome_module_menu() {
$items['awesome/member/%'] = array(
'title' => 'Awesome member',
'type' => MENU_NORMAL_ITEM,
'page callback' => 'aw_memberdata_fetch',
'delivery callback' => 'aw_memberdata_deliver',
'access arguments' => TRUE // this supposedly should allow anonymous access - from the web
);
return $items;
}
I have these two functions, one to fetch the data, one to show it:
function aw_memberdata_fetch(memberId)
{
//fetch array of objects from DB
...
return $items;
}
function aw_memberdata_deliver($items)
{
switch(arg(3)) //format, comes after items
{
case 'json':
drupal_json_output($items);
break;
default:
$output = makeHtml($items); //makes HTML
drupal_deliver_html_page($output);
}
}
With an authenticated browser, this works as intented. From a browser with no auth cookie I'm allowed to see the HTML, but the results are not there, it's like the page callback function doesn't run for anon users, but delivery callback does.
How do I make this work for anon users?

You are using access arguments with the default user_access function for permission verification. This will basically call user_access(true) which will return
true for authenticated user (you are probably testing with the administrator account (uid = 1)) which bypasses the verification check. Administrator has full privileges.
false for anonymous users because the string value of the first argument passed to the user_access true doesn't exist as a permission setting.
You should use either use
a custom YOURMODULE_access hook which does the permission verification
declare custom permissions for your module (YOURMODULE_permission hook)
don't use permission verification by using 'access callback' => true which gives access to anonymous and authenticated users
function awesome_module_menu() {
$items['awesome/member/%'] = array(
'title' => 'Awesome member',
'type' => MENU_NORMAL_ITEM,
'page callback' => 'aw_memberdata_fetch',
'delivery callback' => 'aw_memberdata_deliver',
'access callback' => true,
);
return $items;
}

Related

"Attempt to read property \"id\" on null", Create access token error with laravel passport, laravel 9, php 8.2.2

devs,
so I have been struggling with this problem for about 10 hours now, and I can't seem to find a solution online, worst is that I don't even know why it happens.
I am working on a project which uses PHP LARAVEL as the backend and I started writing the API for the flutter frontend to consume then I ran into this error while trying to test the API endpoint for registering and logging in.
The problem is the process fails with this error when I try to generate or create a token for the registered user or logged-in user.
Here a snapshot of my register function
public function store(Request $request)
{
$validated = Validator::make($request->all(),[
"email" => "required|email",
"password" => 'required',
"first_name"=> "required",
"last_name" => "required",
"phone_number" => 'required',
]);
if ($validated->fails()) {
return response()->json(['errors' => "Invalide credentials"], 403);
}
$user = User::create(
// [
// 'first_name' => $request->first_name,
// 'last_name'=> $request->last_name,
// 'email' => $request->email,
// 'password' => bcrypt($request->password),
// 'phone_number' => $request->phone_number,
// ]
$request->toArray()
);
Auth::guard('api')->check($user);
// $newUser = User::find($user->id);
$token = $user->createToken('authToken')->accessToken;
// return $token;
return response(['token' => $token, 'first_name'=>$user->first_name, 'email'=>$user->email ], 200);
}
The login and register functions all look the same at this point.
Error-causing code is :
$token = $user->createToken('authToken')->accessToken;
Please I am open to your suggestions, thanks.
I finally found a solution for this error and I believe it will help anyone out there with a similar problem.
The problem originates from the fact that your application is unable to asign a unique id to your client, remember your website or mobile app is a client to the backend with also(your mobile app or website) might have other users, so laravel passport will need to identify it with a unique id, below are some of the steps i used to fix this error.
First it originates because during the passport installation, i forgot to install
Blockquote
--uuids
If you have a similar error, follow the steps below to fix:
NOTE: You must have laravel passport installed already, if not, them follow the complete installtion guide Here
Step 1:
Install passport uuids
php artisan passport:install --uuids
Your result will look something like
After creating, the uuid for your application, you will have to include it in your .env file as such:
PASSPORT_PERSONAL_ACCESS_CLIENT_ID=986eb40c-0458-4b6e-bead-ea2fc4987033
PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET=VXLdTpqWK9i3CBqFwZgje5fuerQ5Uf2lvwXJqBoP
And there you go, you can now try to do what you couldn't do before.

Send email with TDD Laravel 5.6

I am doing the registration user
public function register(RegistrationUser $request)
{
$user = $this->usersRepo->create($request->all());
$user->activation_token = str_random(48);
$user->save();
Mail::to($user->email)->queue(new ActivationAccount($user->first_name, $user->last_name, $user->email, $request->input('password'), $url));
return redirect()->route('successful.registration')
}
My registration test is:
public function it_creates_a_new_user()
{
$this->withExceptionHandling();
$response = $this->get(route('register'))
->assertStatus(200);
$this->post('register', [
'first_name' => 'Juan',
'last_name' => 'Lopez',
'email' => 'jlopez#gmail.com',
'password' => 'secret',
'activation_tone' => str_random(48)
])->assertRedirect(route('successful.registration'));
$this->assertDatabaseHas('users', [
'email' => 'jlopez#gmail.com',
]);
}
I have two questions:
1) How can I write a test to send the registration email and verify that it sends and arrives well?
2) When the user clicks on his email he calls a method where the activation token is passed to activate his account
In my opinion you should use mail fake ,which will prevent mail from being sent. You may then assert that mailables were sent to users and even inspect the data they received.
please read laravel docs: https://laravel.com/docs/5.6/mocking#mail-fake
There must be a route which is handling activation token and functionality, so try to get the token and call route with specific token
Note: As a developer we need to make sure that our code works which our tests are confirming, Sending and delivering email should be not be covered as they considered to work as expected(by any email service provider).

How to send user login credentials after user registers

I am using laravel's default login and registration. I have successfully set up authentication, however I would like to send user's username and password to the emails they used during registration. How can I achieve this?
You can initiate a mail to user after you validated input received and before your create functions of your register controller present in
$email = new UserRegisterData(new User(['password' => $user->password, 'name' => $user->name]));
To do this you need to rewrite
protected function validator(array $data)
function in your register controller and modify that with this mail. as
protected function validator(array $data)
{
$email = new UserRegisterData(new User(['password' => $user->password, 'name' => $user->name]));
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:customers',
'password' => 'required|min:6|confirmed',
]);
}
once you hashed your password in create function, i think it can't be read. Also check if any security issue it may generate. Also you need to create mail as 'UserRegisterData' and add necessary code in it.

How to do a Sign Up with OAuth (facebook, twitter, google)?

I use Laravel (5) as my php framework, it recently added a library for social authentication (facebook, google, twitter and github).
I've been wondering how would you do a Sign Up with OAuth, a login can easily be done by getting the user's email via OAuth, checking if it exists in your DB, and if it does, then log in that user. But how would you do the Sign Up?
Mathius - I've recently been working on a site doing something similar to what you've described and this is what has worked for me:
public function syncUserDetails($userData)
{
// First I check to see if there is a user in the DB
// with the oAuth email address
if ( $user = $this->user->where('email', $userData->email)->first() )
{
// If there is a user, I simply update their local info
// with what is on their oAuth account
$user->token = $userData->token;
$user->google_id = $userData->id;
$user->name = $userData->name;
$user->avatar = $userData->avatar;
$user->first_name = $userData->user['given_name'];
$user->last_name = $userData->user['family_name'];
$user->save();
return $user;
}
// Otherwise, if the user doesn't already exist,
// I create them in my local user's DB
return $this->user->firstOrCreate([
'email' => $userData->email,
'token' => $userData->token,
'google_id' => $userData->id,
'name' => $userData->name,
'avatar' => $userData->avatar,
'first_name' => $userData->user['given_name'],
'last_name' => $userData->user['family_name']
]);
}
This is what I'm using to log in a user. However, you could just as easily run this alongside your regular Laravel login method.

Cakephp 2.0 Auth doesn't redirect to users/login

I have some code in AppControler::beforeFilter()
$this->Auth->authorize = array('Actions' => array('actionPath' => 'controllers'));
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
But the Auth does not redirect me to the users/login when I'm trying to load nonpublic action in browser. Instead it redirects me to the '/'. What I'm doing wrong?
It's probably because you have not granted permissions to the Login action in the users controller. Add this to the top of the users controller:
function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('login');
}
As a side note, the loginAction already defaults to /users/login. The same goes for the logoutRedirect. Try removing both as they are not really needed since you are already wanting it to go to the default location.
UPDATE
Have you included the component in the top of the AppController?
public $components = array('Auth');
The other thing to confirm is that you are not already logged in. If you are already logged in but have not granted permission to a specific action within a controller for logged in users, it can redirect as well.