I am using Laravel Sanctum with Vuejs SPA. Both reside on same top level domain
Laravel backend : app.demo.localhost
Vue SPA : app-spa.demo.localhost
Login and logout (endpoints) are working correctly when called from VueJS SPA using axios and XSRF-TOKEN is succesfully set, but when I call other api end points it gives me 401 unauthorized.
In axios this is being set
axios.defaults.withCredentials = true;
I have the below configurations
In Laravel .env
SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost
In Routes/Api.php
Route::middleware('auth:sanctum')->get('api/user', function (Request $request) {
return $request->user();
});
In cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
Could someone help me out please?
If you are using php artisan serve add the port number to SANCTUM_STATEFUL_DOMAINS. So if your port number is 8000:
SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost:8000
Your SANCTUM_STATEFUL_DOMAINS must match the url in your browser. The port number should not be on the SESSION_DOMAIN.
Following are the 8 steps that I follow while setting up Laravel sanctum check if you missed anything
Step1 composer require laravel/sanctum
Step2 php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider
Step3 php artisan migrate (you can ignore this if you're using spa)
Step4 uncomment this line from app/http/kernel.php \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
Step5 In config/cors.php update 'supports_credentials' => true,
Step6 In .env file update SESSION_DRIVER=cookie & add new line of SESSION_DOMAIN=localhost (even if your using any port like 8080 just mention localhost in session_domain)
Step7 In config/sanctum.php add your client domain along with port(if local) in stateful as follows, in my case for vue CLI it's usually localhost:8080 & for nuxt its localhost:3000 , code is as follows
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:8000,localhost:8080,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
Mostly if your stateful (step7) is not setup properly you will get 401 unauthorized or it will try to redirect you to the home page along with cors policy error
Step8 Do not forget to await until sanctum/csrf-cookie promise is resolved
async login() {
await axios.get("http://localhost:8000/sanctum/csrf-cookie");
await axios.post("http://localhost:8000/login", {
email: "kunal#gmail.com",
password: "password",
});
let response = await axios.get("http://localhost:8000/api/user");
console.log(response.data);
},
For anyone dealing with localhost:
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:8080(port number you use)
I just encountered the same problem. I configured all the options according to the official documentation, but I couldn't get the authorization.
Then I use routes/web.php instead of routes/api.php, so I can use sanctum middleware very well.
Now the problem seems obvious,Axios withCredentials maybe need to place in the correct way.
const http = axios.create({
baseURL: API_URL,
withCredentials: true
})
maybe not work. So I add {withCredentials: true} like
http.get('/api/whoami', {withCredentials: true})
.then(res => {
console.log(res.data)
})
Then it works.
But the very strange thing is that it is normal now, no matter whether I clear the browser cache, cookies or Laravel's various caches, there is no previous situation
For me i just had to place the host with port number:
SANCTUM_STATEFUL_DOMAINS=127.0.0.1:5173
and it started working.
Maybe this helps someone.
My problema was.... (no read with attention)
If your SPA needs to authenticate with private / presence broadcast channels, you should place the Broadcast::routes method call within your routes/api.php file:
Hi i found a solution.
My SPA is Vue v3 working on 3000 port.
Also my backend is working on 80 port. (laravel 8.1)
Make Stateful Domains in config/sanctum.php like that
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost:3000',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
Adding only one and correct domain on their, worked for me magically. I wrote before there whole possible variant of ports, it made me crazy and cost a couple days and nights.
My issue was I setup the domain in the wrong place.
I thought was an array of domains, in config/sanctum.php, but not, needs to be placed within the string:
OK:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,myownlocaldomain.test,myownlocaldomain.test:8080', <-------- OK
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
BAD:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '',
'myownlocaldomain.test', <----- BAD
'myownlocaldomain.test:8080', <---- BAD
))),
I hope I save days of work to someone else...
I am using node.js in my application, with shopify-api-node (v3.2.0), to authenticate customer login along with other features if shopify. As per shopify documentation (https://shopify.dev/docs/storefront-api/reference/mutation/customeraccesstokencreate) I am using GraphQL to access shopify API.
My code looks something like this below :-
const Shopify = require('shopify-api-node');
const shopify = new Shopify({
shopName: process.env.SHOPIFY_DOMAIN_NAME,
apiKey: process.env.SHOPIFY_API_KEY,
password: process.env.SHOPIFY_API_KEY_PASSWORD
});
const query = `mutation {
customerAccessTokenCreate (input: {
email: "user#mail.com",
password: "password123"
}
)
{
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}`;
shopify
.graphql(query)
.then((output) => {
console.log(output);
})
.catch((err) => {
console.error(err)
});
After this I am getting below error :-
Error: Field 'customerAccessTokenCreate' doesn't exist on type 'Mutation'
at got.then (/Users/admin/Documents/Code/shopify-node-app/node_modules/shopify-api-node/index.js:239:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
locations: [ { line: 2, column: 5 } ],
path: [ 'mutation', 'customerAccessTokenCreate' ],
extensions:
{ code: 'undefinedField',
typeName: 'Mutation',
fieldName: 'customerAccessTokenCreate' }
Even I am getting the same thing from postman itself.
Any help would be appreciated.
There are two types of GraphQL:
the storefront GraphQL - https://shopify.dev/docs/storefront-api/reference
the admin GraphQL - https://shopify.dev/docs/admin-api/graphql/reference
While they seems similar the strorefront is much more limited but can be used on the front-end, while the admin one is more rich in method and functionality but can't be used safely on the font-end.
The documentation and the method you are trying to make is referring to the Storefront API, but the package you are using is for the Admin GraphQL API.
You can create a storefront access token via the storefrontAccessToken method if you want to make storefront request but the Admin API GraphQL allows for more customization.
So you need to make sure you are using the proper API.
If you plan to use the storefront API, you shouldn't use NodeJS and just create a private app ( from Admin -> APP -> Private App) which will provide you a Store Front Access Token (if you enable it at the bottom and select the proper scopes) that can be used directly on the front-end.
If you plan to use the Admin API, you will need to create a public app and host it, then you can use NodeJS and pass the information via a Proxy in Shopify.
Summary
You are making a request to the Storefront API, while using a library for the Admin API.
I've got a problem with axios and heroku. Maybe some short introduction before.
The problem with CORS has been solved and i my apps run on localhost and on herokuapp.com. The only thing which is currently not working is my app running with heroku local web.
For the backend call I using axios which is referencing my backend api from an environment file:
axios
.get(process.env.VUE_APP_ROOT_API + "/resource")
.then(response => (this.receipt = response.data));
}
.env.local:
VUE_APP_ROOT_API=http//:0.0.0.0:5002 #5002 is my backend
This produces the following wrong axios call:
GET http://0.0.0.0:5001/http//:0.0.0.0:5002/resource #5001 is my frontend
I cannot explain how this GET is generated. Printing out the request url with
axios.interceptors.request.use(request => {
console.log("Starting Request", request);
return request;
});
is showing the correct URL http//:0.0.0.0:5002/resource...
Any solutions?
This is embarassing, I had a type:
http:// instead of http//:
See: Quasar Axios request wrong URL (Double URL)
I created a test app on facebook and set the domain and the site url to localhost and http://localhost:4200 respectively.
The app is in development mode, as the documentation says "You will still be able to use HTTP with “localhost” addresses, but only while your app is still in development mode", nevertheless I get the error "The method FB.login will soon stop working when called from http pages. Please update your site to use https for Facebook Login." when I invoke the FB.login() api.
Sometimes the facebook window to log the user is not displayed , other times the window opens with the error "Login Error: There is an error in logging you into this application. Please try again later." within.
Update
I'm over https in locale and the relative error is disappeared.
This is the function invoked by the "Login with Facebook" button
loginWithFacebook() {
this.btnLoaderFB = true;
this.auth.facebookInitializer()
.then(() => {
this.auth.facebookInitialized = true;
return this.auth.facebookLoginStatus();
})
.then((loginStatusResponse) => {
console.log(loginStatusResponse);
if (loginStatusResponse.status !== 'connected') {
return this.auth.facebookLogin();
} else {
return this.auth.getFacebookProfileInfo();
}
})
.then((profileInfo) => {
console.log(profileInfo);
this.auth.loginWithFacebookRemote(profileInfo)
.subscribe(
res => {
this.btnLoaderFB = false;
}
);
})
.catch(err => {
console.log(err);
this.translate.get('t.validation.error_fb_login').pipe(takeUntil(this.unsubscribe)).subscribe(
t => {
this.error = t;
this.btnLoaderFB = false;
});
});
The first time I call this function I receive the response from facebookLoginStatus() logged on the console
I enter the fb credential and I get this error
If I try to click again on the button I receive the same response from facebookLoginStatus() I showed in the first image and the facebook popup window shows the same error message in the previous image.
If I reload the page the facebookLoginStatus() response is what I expect for a logged user on facebook and the login process ends without error
I can recommend using https even on localhost, especially because you will have a system for testing that is more similar to the live environment. This solves the Facebook https issue once and for all.
For Node.js, it is very easy with this tool: https://github.com/davewasmer/devcert
For PHP, you may want to take a look at this thread: How do I allow HTTPS for Apache on localhost?
For Angular CLI: Get angular-cli to ng serve over HTTPS
I am trying to write a simple electron app to interface with a REST server. The server doesn't have the appropriate certificates. When I try to make a 'GET' request (using fetch()), I get the following error message:
Failed to load resource: net::ERR_BAD_SSL_CLIENT_AUTH_CERT
Fixing the certs is not currently an option. I tried to use the 'ignore-certificates-error' flag (see below). It seems like it should allow me to skip over this error, but it doesn't.
var electron = require('electron');
var app = electron.app
app.commandLine.appendSwitch('ignore-certificate-errors');
...
The result is the same error.
Questions:
I am correct in assuming this options is supposed to help here?
If so, any ideas what I am doing wrong?
Electron version: 1.2.8
Thanks!
You can update your version of electron and use this callback:
app.on('certificate-error', (event, webContents, link, error, certificate, callback) => {
if ('yourURL/api/'.indexOf(link) !== -1) {
// Verification logic.
event.preventDefault();
callback(true);
} else {
callback(false);
}
});
That you going do the fetch to your api with https.