How to create Token-Based Authentication(oauth2) for AngularJS and Laravel Apps via passport - angularjs

I created an web app which it uses laravel default registration(auth), I've tested passport oauth2 client access token from taylor tutorial. My web app uses angular js for UI and laravel for backend , so I need to create user, when create user request is sent from angular and then create a global access token to give it in my response to angular which then in all later request I use it to authenticate requests.
actually I want to implement oauth2 authentication for my web app, but so far I've searched a lot but I couldn't find any useful step by step tutorial for it.
anyone can help me out?
FYI: I'm using laravel 5.3 with passport enabled and angular js 1.5 for frontend.

Use JWT token based authentication here you can learn about jwt https://jwt.io/

I've solved this.
I've Customized laravel auth for login and register and created a method which will send a request to the server to create an access token for registering user or log in.
I've set up passport and test it as taylor did in his toturial.
then in AuthenticatesUsers.php I've changed sendloginResponse method response like :
protected function sendLoginResponse(Request $request)
{
isset($request->token) ? $token = $request->token : $token = null;//Check if login request contain token
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
? $this->StatusCode($token,$this->credentials($request),$status=false) : $this->StatusCode($token,$this->credentials($request),$status=true);
}
And I have added this method to request access token and send it as json response :
public function StatusCode($token,$user,$status){
if( $token != null && $token != ''){
return ($status == true) ? response()->json(GetToken($user),200) : response()->json(['Message' => 'Failed to log in'],403);
}
function GetToken($userobject)
{
$http = new Client;
$response = $http->post('http://localhost/iranAd/public/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '1',
'client_secret' => 'xKqNbzcXyjySg20nVuVLw5nk5PAMhFQOQwRTeTjd',
'username' => $userobject['email'],
'password' => $userobject['password'],
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
function RefreshToken($token,$userobject)
{
$http = new Client;
$response = $http->post('http://localhost/iranAd/public/oauth/token', [
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => 'refresh_token',
'client_id' => '1',
'client_secret' => 'xKqNbzcXyjySg20nVuVLw5nk5PAMhFQOQwRTeTjd',
'username' => $userobject['email'],
'password' => $userobject['password'],
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
return ($status == true) ? response()->json(GetToken($user),200) : response()->json(['Message' => 'Failed to log in'],403);
}
Same Procedure for register users.

The purpose of this post is not to answer(as already answered) but to give more info to other readers who eventually need more info on topic.
This is very helpfull tutorial just on this issue Implementing Vue.js 2.0 and Laravel 5.3 with CORS problem solution
Check this one and 2 next clips.
Some of this you can find in shorter form here here

Related

What is the best way to save token (JWT) in cakephp 4?

I have a project and I made the backend using nodejs.
I made a user registration module and the authentication generates a token!
This token will need to be used in other requests where the user must be logged in.
What is the best way to store this token on the frontend using cakephp 4?
Is there any component? Is it safe to store this token using the session?
I would appreciate it if someone could help analyze this case.
This is my authentication method:
public function login()
{
$http = new Client();
if ($this->request->is('post')) {
$response = $http->post(
'http://localhost:8889/api/auth/login',
[
'email' => $this->request->getData("username"),
'password' => $this->request->getData("password"),
]
);
if ($response->getStatusCode() == 401) {
return $this->redirect($this->referer());
}
if ($response->isOk()) {
$json = $response->getJSON();
return $this->redirect(['action' => 'home', 'controller' => 'Pages']);
}
}
}
Return 200 contains an accessToken.
The best way to store the token is with an HttpOnly Cookie.
According to the Microsoft Developer Network, HttpOnly is an
additional flag included in a Set-Cookie HTTP response header. Using
the HttpOnly flag when generating a cookie helps mitigate the risk of
client-side script accessing the protected cookie (if the browser
supports it).
If you store it in a LocalStorage/SessionStorage then it can be easily grabbed by an XSS attack (from Javascript/Client side)
The CakePHP 4 way to do it is like this:
https://book.cakephp.org/4/en/controllers/request-response.html#creating-cookies
$cookie = new Cookie(
'jwt_token', // name
'token', // value
new DateTime('+1 hour'), // expiration time
'/', // path
'example.com', // domain
true, // secure only?
true // http only -> this is what you need
);

laravel reactjs pusher: presence channel response is 302

I'm trying to make a reactjs application where an user can only login to one device at the time with the same user credentials. Unfortunately it isn't working.
I'm trying to authenticate a presence channel with reactjs to laravel but I get a 302 response.
reactjs:
Pusher.logToConsole = true;
var pusher = new Pusher("9028d58568392772df59", {
cluster: "eu",
forceTLS: true,
authEndpoint: '/broadcasting/auth',
auth: {
headers: {
'X-CSRF-Token': csrf_token
}
}
});
var channel = pusher.subscribe("presence-HandleCredentials");
channel.bind("sameCredentials", function(data) {
console.log(data);
alert(JSON.stringify(data));
});
channel:
Broadcast::channel('App.User', function ($user, $id = 1) {
return (int) $user->id === (int) $id;
});
broadcast:
public function boot()
{
Broadcast::routes(['middleware' => ['auth:web']]);
require base_path('routes/channels.php');
}
When I added this ['middleware' => ['auth:web']] I got the error. Before I added that I got a 403 error.
in the config\app.php I uncommented App\Providers\BroadcastServiceProvider::class,
Are there any tutorials out there that are build with laravel and reactjs for a presence channel?
does anyone know how to get past this 302 redirect?
Recently had the same issue with my laravel-websockets and laravel echo.
In my case I was unable to solve the 302, as Broadcast was unable to authenticate my logged in user. I was trying to subscribe to my private channel. So the workaround i found was that i manually created a POST route in web.php as "/broadcasting/auth". This is what my front-end requests to. So The updated code in web.php is as follows.
Route::post('/broadcasting/auth', function(Request $request){
$pusher = new Pusher\Pusher(
env('PUSHER_APP_KEY'),
env('PUSHER_APP_SECRET'),
env('PUSHER_APP_ID'),
array(
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => false,
'host' => env('APP_URL'),
'port' => 6001,
'scheme' => 'http',
)
);
return $pusher->socket_auth($request->request->get('channel_name'),$request->request->get('socket_id'));
});
I was creating my own websocket that is why i had to mention the host & port within the options, you don't need to use it if you are Using Pusher. You can also add other middlewares to the routes if needed.
You have to comment out the following line in app/providers/BroadcastServiceProvider:
public function boot()
{
// Broadcast::routes();
require base_path('routes/channels.php');
}
so that the request can reach my broadcasting/auth route in web.php.
Try this. now this should return a 200 when the broadcasting/auth is requested by your client end with response of an auth code. Do let me know if this solves your problem.

Which Part to integrate with FCM? Frontend or Backend

So let's jump on the direct issue. I've made a native app where I'm using laravel REST API as backend and reactjs as frontend. I have completed all the functionality except Push Notifications.
Now I don't know how fcm works and which part I'd have to integrate?
If I have to integrate laravel or reactjs and how do I do that?
I hope you guys get my question and please pardon me if my question is silly. I'm a beginner so I hope you understand. Thanks in advance.
You can use FCM directly into any laravel project by using packages.
There is package exists in laravel to make it easy .
Take a look at it .
Laravel-FCM-package
You have to implement the code to receive notification in Your Frontend (ReactJs or React native). The notification will be pushed from the FCM Server, have a look at the documentation to know How it works?
Or, you can simply follow this medium article: Implementing FCM in React Native
Also, if this is a web app then follow this article: FCM Integration in ReactJS
It seems like my last task. So u have to use Laravel or backend engine to send firebase cloud message (fcm) and using reactjs to retrieve it.
For backend based on php (Laravel/lumen/whatever) you can use this :
https://firebase-php.readthedocs.io/en/latest/cloud-messaging.html
or if you need more simple, just using curl() function. This is my simple function for fcm :
public function sendCloudMessageTopic($title, $message, $topics, $detail = null)
{
try {
$serverApiKey = "YOUR APP FIREBASE KEY";
$header = [
"Authorization: Key=" . $serverApiKey,
"Content-Type: Application/json",
];
$notification = [
"title" => $title,
"body" => $message,
];
$data = [
"notification" => $notification,
"detail" => $detail,
];
$payload = ["notification" => $notification, "data" => $data, "to" => $topics];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => $header,
));
$response = curl_exec($curl);
$failed = curl_error($curl);
curl_close($curl);
if ($failed == TRUE)
throw new \Exception("CURL Action Failed to send firebase cloud message");
$result = json_decode($response);
if (!isset($result->message_id))
throw new \Exception("Failed to send firebase cloud message");
return [
'status' => 1,
'message' => "successfully sending firebase cloud message"
];
} catch
(\Exception $exception) {
return [
'status' => 0,
'message' => "Failed to send firebase cloud message"
];
}
}
I've never tried it for fronted to retrieve it, but you can take a look to this article :
https://codeburst.io/how-to-add-push-notifications-on-firebase-cloud-messaging-to-react-web-app-de7c6f04c920
Thanks,

where and how to store laravel passport authentication token and send request from front-end with that token?

i've created a laravel passport api based authentication.and using react js as frontend.when i send login request with email,password my backend send me authentication token.now where should i store this token?? if i want store it in cookies how to do that?? and how to send this with frontend ajax request??
actually i'm totally new.so if this question sound stupid ,i'm sorry..
this is my login function:
public function login()
{
if (Auth::attempt(['email' => request('email'), 'password' => request('password')])) {
$user = Auth::user();
$success['token'] = $user->createToken('AppName')->accessToken;
return response()->json(['success' => $success], $this->successStatus);
} else {
return response()->json(['error' => 'Unauthorised'], 401);
}
}
You can save the token to local Storage on react js.It is one of the method to store and access the token.
localStorage.setItem("token", token value)

Cakephp 3 HTTP Basic Authentication login issue

I am using basic authentication in my project to access Api. In ApiController, I added below code in beforeFilter:
$this->Auth->config('authenticate', [
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
'userModel' => 'Users'
]
]);
So from chrome postman application, I am sending post request with basic auth credentials. for example like below:
So when I send a request, I get unauthorized error back.
you are sending a post request with a 'password' field
Your application is expecting a 'api_key' field that would contain the password.
I think you missed this one script in your model entity.
use Cake\Auth\DefaultPasswordHasher;
protected function _setPassword($password)
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher)->hash($password);
}
}
Put this one in Model/Entity/User.php

Resources