i have token in header of ajax and when i get dd return null - ajax

i wanna send GET request from frontend to backend
i mean i want to send token from frontend to middlware
i mean i want get token from cookie and push in GET request and send for one of route in api.php that the route is GET method
i mean i want to push my token in ajax and send to laravel
infact i have two laravel project that i want send token from one to another
i mean i want push my token in header in ajax and get in backend with laravel
so see my code in the below fisrt my route from backend
later my jquery and then middleware
but my current problem is that when i dd header is is null
thanks
Route::get('/customers', 'App\Http\Controllers\CustomerController#show');
//
$.ajax({
url: "http://localhost:8000/api/customers",
type: "GET",
headers: {
"Authorization": getCookie("access_token")
}
});
//
dd($request->header('Authorization'));
if ($request->hasHeader('Authorization')) {
$access_token = $request->header('Authorization');
$query = DB::table("admins")->where("access_token", $access_token)->first();
if (isset($access_token) && $access_token == $query->access_token) {
return $next($request);
} else {
return response()->json([
"status" => 401,
"message" => "شما اجازه دسترسی ندارید",
]);
}
}

Related

Laravel / Airlock AJAX login - 419 (unknown status)

I'm trying to do a cross origin login request and everything except logging in is working. So if I go to api.example.com and log in with the laravel app and then go to www.example.com I can get the user by calling the /api/user end point (setup as part of airlock). What I'm failing to do is log in via AJAX with username / password. Here is the JS used:
First I call setCSRFCookie()
function setCSRFCookie() {
let xhr = new XMLHttpRequest();
xhr.open('GET', domain+'/airlock/csrf-cookie');
xhr.withCredentials = true;
xhr.send(null);
}
Then I call loginUser()
function loginUser() {
let xhr = new XMLHttpRequest();
let params = 'username=m#example.com&password=password';
xhr.open('POST', domain + '/login', true);
xhr.withCredentials = true;
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
xhr.send(params);
}
I'm getting a 419 (unknown status) which appears to be Laravel's response for an invalid CSRF token. I looked at the actual request and both APP_NAME_session and XSRF-TOKEN are being passed as part of the request. The only thought I had was that the /login default auth route isn't setup for this and I need to do one under /api/login so it's served by the airlock middleware. I appreciate any help you can give.
Laravel 6.12.0
Airlock 0.1.0
Make sure api.example.com is included in config/airlock.php like this
'stateful' => [
'localhost',
'api.example.com'
],
And request middleware should be auth:airlock

Can not get laravel cookie laravel_token while consuming own API

Cookie is avaiable in browser but can not get it even can not check if it exists .
working on laravel and vuejs app where I am using passport for authentication.
I am consuming own api with vuejs so I have added CreateFreshApiToken middleware in kernel.php
vuejs is creating and sending laravel_token cookie successfully but I can not read it using vuejs or javascript.
since I can not check if cookie is available or not I can not check if user is logged in or not.
How I will tell vuejs that user is logged in and take to intended route ?
For now I am saving access_token in localStorage and sending it with each request but I am looking for a solution which can help to use laravel builtin laravel_token cookie to authenticate and authorize the users.
More Details
If i run this command in console then I get response
document.cookie.match('XSRF-TOKEN')
But
document.cookie.match('laravel_token')
returns null
I think the tick icon in the shown image at top is sign of making it private or something that makes it inaccessible.
Update
I found something from internet
But I still want to know how I can tell vuejs app that user is logged in or not ??
Update 2
For now I am sending access_token in header manually from vuejs and it is working fine.
if(localStorage.getItem('laravel_token') !== 'undefined' && !! localStorage.getItem('laravel_token') == true){
window.axios.defaults.headers.common['Authorization'] = 'Bearer '+ localStorage.getItem('laravel_token')
}
A little work around will be for you to implement the authenticated method in your LoginController, and return a json success code. You can then receive this code and store.
public function authenticated(Request $request, $user)
{
// return redirect()->intended($this->redirectPath());
return json_encode(['authenticated' => true]);
}
Using axios...
axios.post('/login', {
email: user.username,
password: user.password
}).then(response => {
.then(response => {
console.log(response)
//response.data.authenticated will return true if user has been authenticated
})
}).catch(err => {
console.log(err)
})

How to authenticate Vue.js / Axios request of an API route in Laravel

I'm in Laravel 5.6. I have all my API routes built out and properly responding to requests from my REST client (Paw). I'm trying to build a simple front end to access those routes.
I'm trying to use Laravel's out-of-the-box features as much as possible, so I'm using Axios to call those routes from a blade template using Vue.js. It works if I disable auth middleware on the test route, but I get 401 errors on the console when auth middleware is enabled for the route.
The problem seems obvious enough... The auth:api guard on my /api routes wants to see an oauth token in the header, but when I log in with the web page it does session authentication. I assume there's a simple way to resolve this without having to spoof an oauth token request in the web frontend, right? Do I need to somehow pass the session token in my request with Axios? And, if so, do I also need to change the auth:api guard in my api routes file?
I solved it! I'm a bit embarrassed because the answer was actually in the Laravel docs, but I will say I tried this before posting the question here and it wasn't working. Perhaps something else was broken at the time.
Per the Laravel docs:
All you need to do is add the CreateFreshApiToken middleware to your
web middleware group in your app/Http/Kernel.php file:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
This Passport middleware will attach a laravel_token cookie to your
outgoing responses. This cookie contains an encrypted JWT that
Passport will use to authenticate API requests from your JavaScript
application. Now, you may make requests to your application's API
without explicitly passing an access token...
You will probably want to use Larvel Passport or a JWT auth mechanism for obtain the Authorization token.
Seeing as how you're using axios, add a request interceptor to attach the access token to every request once you successfully authenticate. A simple example:
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// assume your access token is stored in local storage
// (it should really be somewhere more secure but I digress for simplicity)
let token = localStorage.getItem('access_token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
to use the auth:api first you need api_token inside your users table
Schema::table('users', function ($table) {
$table->string('api_token', 80)->after('password')
->unique()
->nullable()
->default(null);
});
also you can create a user for testing as follows
User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'api_token' => Str::random(60),
]);
in your layout use the following before #yield('content')
<script>
window.Laravel = <?php echo json_encode(['api_token' => (Auth::user())->api_token]); ?>
</script>
now you can use window.laravel.api_token inside your vue js to use it in headers
heres an example
var methods = new Vue({
el: '#tabs_lists',
data: {
config: {
headers: {
Authorization: 'Bearer ' + window.Laravel.api_token,
Accept: 'application/json'
}
},
data: []
},
methods: {
test: function (link) {
axios.get(link, this.config)
.then(response => (this.data = response.data)).catch(function (error) {
// handle error
console.log(error);
});
}
}
}
)

Tymon JWT Laravel Vue refresh token stored in localstorage

So I started using Tymon JWT package for Laravel for my SPA. Its all going good ( adding user, signing in, getting Auth user) but when I make an API request it only works for an hour. I understand that the token I stored on on login expires so when I make a request to the API after 60 minutes it doesnt work. My question is how do I refresh the token and restore it in my local storage? On a new request? Every 59 minutes?
AuthController.php
public function authenticate(Request $request)
{
// grab credentials from the request
$credentials = $request->only('email', 'password');
try {
// attempt to verify the credentials and create a token for the user
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Sorry, we cant find you.']);
}
} catch (JWTException $e) {
// something went wrong whilst attempting to encode the token
return response()->json(['error' => 'could_not_create_token'], 500);
}
// all good so return the token
$user = JWTAuth::toUser($token);
//Fire off the login event
event( new LoginSuccessful($user) );
return response()->json( compact('token', 'user') );
}
Login.vue
axios.post('/api/authenticate',{
email: this.email,
password: this.password
})
.then(response => {
if(response.data.error){
//Show the error
this.error = response.data.error
this.loading = false;
} else {
this.loading = false;
//Store the items in storage
localStorage.setItem('jwt_token', response.data.token);
localStorage.setItem('user', JSON.stringify(response.data.user));
//Mutate the state
this.$store.commit('login');
//Now go to the dashboard
this.$router.push('dashboard');
}
})
.catch(error => {
});
in my head tag
<script>
window.hopbak = {
'jwt_token': localStorage.getItem('jwt_token'),
'csrfToken': {!! json_encode( csrf_token() ) !!},
};
</script>
in my bootstrap.js
let token = window.hopbak.jwt_token;
if (token) {
window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
} else {
console.log('no token');
}
I think you need to register the RefreshToken middleware in app/Http/Kernel.php:
protected $routeMiddleware = [
'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken'
];
And then assign it to the routes you want to refresh the token.
Looking at the source code, I can tell that this middleware will handle the refreshing of your token in every request by adding a new token to the response header.
JWT_TTL, JWT_REFRESH_TTL and JWT_BLACKLIST_GRACE_PERIOD values are setted in config/jwt.php file.
How does it work:
The client sends the credentials (email and password) to Laravel and
receives a token (JWT) in response. This token is valid for JWT_TTL
minutes. During this time all requests with the header Authorization
= "Bearer token" will be successful.
For a request made after JWT_TTL minutes, that is, with the token expired, two situations will occur: (1) If there is less than JWT_REFRESH_TTL minutes since the creation of the token (the token carries within it the date of creation on claim IAT), then this token will be invalidated (blacklist) and a new token will be generated and sent as a response to the client. JWT_REFRESH_TTL defines how many minutes after creating the first token the new tokens can be created. For example, for JWT_REFRESH_TTL = 21600, new tokens will be generated for 15 days, after which time the user should reauthenticate. (2) The request occurs after JWT_REFRESH_TTL minutes after the first token was created. In this case, it will not be possible to generate a new token for the client and it must authenticate again. A 401 error will be sent to the client.
When multiple concurrent requests are made with the same JWT,
it is possible that some of them fail, due to token regeneration on
every request. Set grace period in seconds to prevent parallel
request failure, because the JWT will consider to be valid for
JWT_BLACKLIST_GRACE_PERIOD seconds, even if it's on the blacklist.
For more details see this my explanation.

How do Laravel get GET request made by vue.js?

Vue.js HTTP call
methods :{
login(){
var data ={
client_id: 2,
client_secret: '5YVQ6rsSehoh5BOWsxAU3KxGeqT1tCRGHn5dx1iX',
grant_type: 'password',
username : this.email,
password: this.password
}
//send a GET request using Vue-Resource
this.$http.get("http://localhost/kubikt2/public/api/login", data)
.then(response=>{
console.log(response)
})
}
}
Laravel
Route::get('api/login',function(Illuminate\Http\Request $req){
$arr["echo"]=$req->all();
$arr["test"]="OK!!";
return json_encode($arr);
}
As you can see, echo $req->getContent(); return nothing in Laravel.
check this out
How do I access the var data sent by Vue.js in Laravel ?
$req->all() is empty because no data is passed!
A GET request only evaluates data passed as query-string in the URI. It acts like the data parameter is null.
You could send your data as query (like "localhost/kubikt2/public/api/login?email"+email+"&someMore"+someMore) or use a POST request (which would be the better option here)

Resources