How can I get data from api when backend is secured by laravel sanctum?
when I use useFetch I do not get any data.
const {data: cat} = await useFetch('/api/categories')
Laravel docs told to use axios but in nuxt3 axios module not working.
Can someone help?
I was try use useFetch with method get to get csrf cookie but it's doesn't work
const {data} = await useFetch('/sanctum/csrf-cookie', {method: 'get'}).then(Response => {
})
To get data when using sanctum,
You are already getting the csrf token above by going to the route /sanctum/csrf-cookie.
However, that is not enough.
For every request that you want to make which is secured, you need to send a token that is generated using sanctum.
Usually, for an app, you would follow these steps
Login user then generate a sanctum token using
$user->createToken('TokenName');
Once token is generated, you can save this token using cookies on your application. Every time you make a subsequent request to your app, simply send the token along with your request headers as a Bearer Token.
The header would be something like this
"Authorization": "Bearer " + TOKEN_VALUE;
All depends how you are sending the request.
More documentation is available On this link on Laravel Documentation
Also, ensure you have
Accept: Application/json
As part of your headers as well.
If you do not send that token in your headers, your requests will give you an error "Unauthenticated".
Below is an example of what I send to the API
And for Authorization, select the option of Bearer Token
Hope this helps.
The endpoint /sanctum/csrf-cookie does not return content in the body of the response, that's why you get HTTP 204 No Content, during this request Laravel Sanctum will set an XSRF-TOKEN cookie containing the current CSRF token, you have two ways to use the token: it can be passed via X-XSRF-TOKEN header from your requests, or from the original XSRF-TOKEN cookie.
https://laravel.com/docs/9.x/sanctum#csrf-protection
Here's an exemple using the XSRF-TOKEN cookie:
// the browser load the XSRF-TOKEN cookie
await fetch("https://myapi.com/sanctum/csrf-cookie", {
"method": "GET",
"mode": "cors",
"credentials": "include"
});
// now the browser can send a POST request
await fetch("https://myapi.com/api/register", {
"method": "POST",
"body": JSON.stringfy({name: 'Joe': email: 'joe#gmail.com'})
"mode": "cors",
"credentials": "include"
});
I am working on simple package enabling easy integration of laravel sanctum with nuxt3. Maybe it can help you until official auth module for nuxt3 is released.
https://github.com/dystcz/nuxt-sanctum-auth
Related
I've recently started using Postman and I am testing an API where I get a CSRF token and then login but I always get a CSRF token mismatch. I am including X-XSRF-TOKEN header but I think the issue is around the cookies not being stored correctly.
I am calling a Laravel Sanctum endpoint to get a CSRF token and when I look in the in the console I can see Set-Cookie response headers
However, when I look in the cookies tab it says no cookies were received from the server
However, when I look at the cookies store they are listed for my test domain (home.local)
Due to this issue, when I send a request to the login, the session cookies are not sent in the request as shown in the console on the request to the login endpoint
I can do this fine using Insomnia.Rest client so I know the API is working as expected - I am however trying to replace Insomnia with Postman.
I've tried Google, but I've only found some bugs that were introduced that seemed to cause something similar back in 2016
Update
I managed to Postman working with production fine using a pre-request script to get the CSRF token and set the environment variable using the below:
const url = pm.environment.get('base_url');
const referer = pm.environment.get('Referer');
pm.sendRequest({
url: `${url}/sanctum/csrf-cookie`,
method: 'GET',
}, function (err, response, {cookies}) {
if (!err) {
console.log("cookies", cookies);
pm.environment.set('xsrf_token', cookies.get('XSRF-TOKEN'))
}
});
Although this worked on production and successfully did the POST request, on my local dev PC, I was still getting the CSRF mismatch.
Although the request/response looked the same between dev/and prod I for some reason had the idea to change my dev URL from my-app.home.local to my-app.home.com and now the cookies are received and send in the next request to login without getting a CSRF token mismatch.
There's clearly an issue with postman here but not sure if it's something I'm doing or a bug in Postman. Does .local mean something different?
CSRF Token Mismatch when using Thunder Cilent to test Laravel Sanctum API. Works fine on app, just not when testing API outside app.
Trying to test API with Laravel Sanctum with Thunder Cilent (Think Postman but VSCode extension). However, despite setting the xsrf-token and Cookie, I'm always getting CSRF token mismatch.
Note logging on works fine in the app, it's only the api testing with thundercilent that's failing.
Getting the CSRF Token
GET http://localhost:8000/sanctum/csrf-cookie
Response Cookies
xsrf-token: eyJpdiI6ImN6Q3JLVEQrYnhXVXhyVWFQWC9YQlE9PSIsInZhbHVlIjoia2F2aTNjNDU2cTZURHRSSTN5Ny9ETnFJMGZoN0I2dmZ3bTA0UEZ6UjhzdCtCRjRPam9OSW5TWVkzYzAvMTQ0ZEp6b2JvYVdhRWg2TGsrejlkcnYzTGY3eGNFcTRGN253dUUxZjE3YXJBSFlVUHk4aGM5RmVYRWF6UFY2ZGRnYUEiLCJtYWMiOiI4OWU3OGI3MzQ3ZTdiNTNiZDQ2Yjg0ZDE3YWNiYmVhNDQ1NTI0MmI3MTY1NjdlZGI5ZGJlZDJlN2Q5NTc0ZjRhIiwidGFnIjoiIn0%3D
laravel_session: eyJpdiI6IjV6VTV4di9IMXNST1ZvNVh0K1pZelE9PSIsInZhbHVlIjoiTSsycEVWdjJ1VTc4dU81TVNJWTJ4aTRHOE81WTVHVW1OeU55OEt3cVU3bHc5N090dEdPQy9yZGJsamhOaDUzaFZmZVp0Z2FTeGp4UWJyVFVmSDdnVytTNS9SZTF5c0daak9EZ1I1V0w3aWpjTnVESWtIRmR2QzNGZ1VqWlZHZ2oiLCJtYWMiOiI0Mzg4NGI4MTc5MGQ1MDE1NTUxY2VmNGRmNGFkNjUyYmI1MjUwMTJiODQ4NmY4M2E5OTRlZGRlNTM3NjAzNTg1IiwidGFnIjoiIn0%3D
Logging in
POST http://localhost:8000/login
Body: {
"email": "example#example.com",
"password": "password"
}
Raw Headers:
User-Agent: Thunder Client (https://www.thunderclient.com)
Accept: application/json
Referer: http://localhost:3000
xsrf-token: eyJpdiI6ImN6Q3JLVEQrYnhXVXhyVWFQWC9YQlE9PSIsInZhbHVlIjoia2F2aTNjNDU2cTZURHRSSTN5Ny9ETnFJMGZoN0I2dmZ3bTA0UEZ6UjhzdCtCRjRPam9OSW5TWVkzYzAvMTQ0ZEp6b2JvYVdhRWg2TGsrejlkcnYzTGY3eGNFcTRGN253dUUxZjE3YXJBSFlVUHk4aGM5RmVYRWF6UFY2ZGRnYUEiLCJtYWMiOiI4OWU3OGI3MzQ3ZTdiNTNiZDQ2Yjg0ZDE3YWNiYmVhNDQ1NTI0MmI3MTY1NjdlZGI5ZGJlZDJlN2Q5NTc0ZjRhIiwidGFnIjoiIn0%3D
Cookie: XSRF-TOKEN=eyJpdiI6ImN6Q3JLVEQrYnhXVXhyVWFQWC9YQlE9PSIsInZhbHVlIjoia2F2aTNjNDU2cTZURHRSSTN5Ny9ETnFJMGZoN0I2dmZ3bTA0UEZ6UjhzdCtCRjRPam9OSW5TWVkzYzAvMTQ0ZEp6b2JvYVdhRWg2TGsrejlkcnYzTGY3eGNFcTRGN253dUUxZjE3YXJBSFlVUHk4aGM5RmVYRWF6UFY2ZGRnYUEiLCJtYWMiOiI4OWU3OGI3MzQ3ZTdiNTNiZDQ2Yjg0ZDE3YWNiYmVhNDQ1NTI0MmI3MTY1NjdlZGI5ZGJlZDJlN2Q5NTc0ZjRhIiwidGFnIjoiIn0;laravel_session=eyJpdiI6IjV6VTV4di9IMXNST1ZvNVh0K1pZelE9PSIsInZhbHVlIjoiTSsycEVWdjJ1VTc4dU81TVNJWTJ4aTRHOE81WTVHVW1OeU55OEt3cVU3bHc5N090dEdPQy9yZGJsamhOaDUzaFZmZVp0Z2FTeGp4UWJyVFVmSDdnVytTNS9SZTF5c0daak9EZ1I1V0w3aWpjTnVESWtIRmR2QzNGZ1VqWlZHZ2oiLCJtYWMiOiI0Mzg4NGI4MTc5MGQ1MDE1NTUxY2VmNGRmNGFkNjUyYmI1MjUwMTJiODQ4NmY4M2E5OTRlZGRlNTM3NjAzNTg1IiwidGFnIjoiIn0%3D;
I copied how this SO Postman example, but it's not working at all. Thunder Cilent doesn't have pre-run scripts so I can't add cookies that way.
Open thunder client, switch to Env and create an environment.
Click on the options button of your collection and choose settings.
Add a test to your collection by navigating to the Tests tab, then select Set Env Variable, set query to cookie.xsrf-token and value to {{XSRF-TOKEN}}
In the Headers tab, add an header named X-XSRF-TOKEN with value {{XSRF-TOKEN | urlDecode}}.
Create a request to /sanctum/csrf-cookie to refresh CSRF Token if it expires
This should fix CSRF Token.
Consult docs for more information: https://github.com/rangav/thunder-client-support
Decided just to use token based auth for API testing instead. Much easier then messing around with CSRF cookies.
Notes for my future self.
When testing the Token based auth, you need to set the accept to application/json otherwise it won't work.
If using collections, don't delete the Accept header in the request, just untick the box. Otherwise the request would override the collection header with something else and not work.
what i got:
created a new jetstream project (inertia) and Features::api() enabled in jetstream.php config,
web.php:
Route::middleware(['auth:sanctum', 'verified'])->get('/testweb', function () {
return "test web called";
})->name('testweb');
api.php:
Route::get('/testapi', function(){
return 'api called';
})->middleware('auth:sanctum');
also i created a test API token
now when I call /testweb in the browser and I am logged in I get "test web called"
when I am logged out and call it I get redirected to login view
when I make the API request WITH the token
I get the expected result "api called"
BUT
when I don't add a token to the request
I don't get a 401 or so but I get a 200 with an "empty" view (with livewire i see it is the loginview, so i think with inertia it is the loginview too)
what is the cause o that? do i have to handle it myself? if yes, where and how??
additional note:
I made the API request with POSTMAN, does it differ if I do not set the header as Accept: application/json?
When the request is made with that head included
Accept: application/json
then the Authenticate Middleware will know what to do and decide
if it will redirect it or
just send back a 401 response.
I am host angular 4 app on my localhost , Since I need to make api request to my backend which is hosted on web (say https://example.com ) I am using proxy . Here is my proxy config file.
"*": {"target":"https://example.com",
"secure": false,
"logLevel": "debug",
"changeOrigin": true }
So that every request I make goes through the target url . When I make my first request to login page with credentials included I receive cookies in response.But then when I make another request ( POST ) to https://example.com/images I am redirected to the login page . I can see in my network that there are no cookies being sent with the Request headers, however I did receive them from my first login request . I checked out many solutions to this problem. Many of them asked to include {withCredentials=true} in my ajax request which I did in every request.Here is my request
$.ajax({
url: "https://example.com/images",
type: "POST",
crossDomain:true,
headers: {
// includes necessary headers .
},
xhrFields: {
withCredentials: true
},
data:data1 ,
//data1 is json formatted
success: function (res) {
console.log(res)
},
error: function (xhr, status) {
console.log(status);
}
});
But this did not solve the problem. I suspect the cookies are getting lost due to proxy , or the browser is not handling them correctly. I checked I have allowed third party cookies . I need to send those session cookies with this second request . I tried to manually add them but I did not find a way to get and send them along with this request. how can I tackle this issue ? If I remove proxy then I will get the CORS issue . I do not have access to the backend server. hence I tried handling CORS using proxy which works correctly for login request. But this second request is not being sent with cookies. Anyone who can help with this ?
Why are you using jQuery in your angular app, and why use it to do ajax requests, if angular provides an http client?
You better use it and then, use interceptors to add headers to the requests.
When using Angular, do it the Angular way. And use its tools/libraries/patterns.
Making Successive Requests for Data
TL;DR
After authentication, I cannot request data from my app's Front-End -- but only through server-side views and Postman can I make subsequent requests for data after logging in, or by authenticating my user in Postman and then making the data request in my app.
First off, I'm a newbie on the server-side.
I've a SailsJS backend which I'm using for REST. Creating and authenticating a user, using LocalStrategy, works fine -- and really, even making subsequent requests for data works fine -- but not via AJAX from my app.
I can use Postman or server-side views to access data, such as /list; making requests after authentication in my app doesn't work -- UNLESS I jump back into Postman and login, then jump back to my app and remake the request.
I do notice that my set-cookie's in my app are different between the first authentication request and the request for /list.
If necessary, I can show some code, but this seems I'm missing a very high-level, basic concept in making authenticated AJAX requests.
EDIT:
My front-end is on a different domain -- Sails runs on localhost:1337 while my UI runs on localhost:8100.
Here's what my /api/config/cors.js looks like:
module.exports.cors = {
allRoutes: true,
origin: '*',
credentials: true,
// methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
// headers: 'content-type'
};
I'm using angular on the front-end, and the subsequent requests are using withCredentials: true -- do I need to add this to the login request too? Must I send the username/email along in the request also?
How do I allow all my subsequent requests for data authenticated after login?
If your frontend application has as a different origin than your backend application the AJAX requests will not include the session cookie by default.
If you are using jQuery:
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
This option has to be used for all AJAX requests, so the server can treat them as belonging to the same session.
You also have to configure the server side to allow CORS requests.