I'm having the exact same issue described in this question. But the solution doesn't work for me. The app_uninstalled webhook works perfectly fine and I'm disabling the access token upon deletion and also removing the store from the active shops list. I'm using Shopify CLI and Node.
This is what I'm doing:
Install the app
Delete the app
Click on the back button to go back to the app page. The URL format is: https://[store]/admin/apps/[random id]/?shop=[store]&host=[random hex]. I also found that this is not even hitting my app anymore (i.e. no logs after the uninstall).
I'm seeing a "There’s no page at this address" error.
Code corresponding to webhooks:
router.post("/webhooks", async (ctx) => {
try {
console.log(
`Getting called successfully. Context object: ${JSON.stringify(ctx)}`
);
let topic = ctx.get('x-shopify-topic')
if(topic && topic === `app/uninstalled`){
const shop = ctx.get('x-shopify-shop-domain')
console.warn(`App uninstalled from shop: ${shop}. Removing shop from active shopify shops list`)
delete ACTIVE_SHOPIFY_SHOPS[shop]
console.debug(`App uninstalled from shop: ${shop}. Successfully removed shop from active shopify shops list. Current list is: ${JSON.stringify(ACTIVE_SHOPIFY_SHOPS)}`)
console.warn(`App uninstalled from shop: ${shop}. Attempting to mark token as disabled...`)
const record = await getShopToken(shop, true)
console.debug(`Token record from DB for ${shop}: ${JSON.stringify(record)}`)
if(record){
await storeShopToken(record.SHOP, record.ACCESS_TOKEN, record.SCOPE, `DISABLED`)
console.debug(`Successfully disabled access token for ${shop}.`)
}else{
console.warn(`Could not find the current token entry for ${shop}. Unable to mark token as disabled.`)
}
}
await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
}
});
This is preventing the app from getting certified. Please advise.
If you are finding this message only on the reinstalling app cases, you need to delete the shop.shopify_token and the shop.shopify_domain fields after you receive the uninstall webhook.
What I did was to create a new uninstalled_domain column, passed the value of shop.shopify_domain to that new column after receiving the uninstall WH and then I deleted the shop.shopify_domain column.
When a user logins, I check if uninstalled_domain exists, if so, it means the user is not new, but reinstalling. Then I switch to that row in the DB and delete the just created row.
That way the user finds all his data after reinstalling.
Related
The requested resource /Services/serviceSSID/VerificationCheck was not found is the eroor showing in the console
my code is
otpLogin:async (req,res)=>{
console.log(req.body.otp);
try {
const isOTP = await client.verify.services(serviceSSID).verificationChecks.create({
to:`+91${req.body.phone}`,
code:req.body.otp
})
if(isOTP)console.log(isOTP);
return res.status(200).json({message:" mobile number verified"})
} catch (error) {
console.log(error.message)
return res.status(500).json({message:"something went wrong"})
}
}
Twilio developer evangelist here.
From the documentation:
Twilio deletes the verification SID once it’s:
expired (10 minutes)
approved
when the max attempts to check a code have been reached
If any of these occur, verification checks will return a 404 not found error like this:
Unable to create record: The requested resource /Services/VAXXXXXXXXXXXXX/VerificationCheck was not found
If you’d like to double check what happened with a given verification - please use the logs found in the Twilio Console under your Verification Service:
I've found that if you submit a form twice by clicking a submit button twice quickly, that the verification is successfully checked and then because it was a success deleted, then the second check fails with a 404 like this and that is the error result you see. To avoid this, you should stop users from being able to submit the form twice by disabling the submit button after the first attempt.
I can confirm that philnash 2nd statement is correct. However wouldn't it have been handled way better if instead we just get a response from client.verify.services(serviceSSID).verificationChecks that the 2nd (and so on checks) failed??
What could cause specific users to have their local storage cleared, but the rest of the users are unaffected? Is it their firewalls? Is it their anti-virus? Browser? Browser version?
Any help would be greatly appreciated.
The application -
I have a website that requires login. Certain routes require the user receive a token(from the login step) if not they will be redirected to the login page.
The run down-
Two users have come forward and mentioned they couldn't log in. After some trouble shooting and looking at logs I found they were successfully logging in. So I screen shared with one user and I watched the localstorage in the dev console. I saw that they acquired a token successfully. Then they go to navigate to the myorderCards page and suddenly the token is cleared from the storage and they are routed back to the login page. This then puts them in a loop because every time they login successfully I have a return parameter which sends them back to myorderCards which then clears the token etc...
So the problem I am facing is that I can not recreate this issue. I have tested locally and on the published site. I have tested on and off network. I have tested 3 different browsers and even tested on a mac device(the two users in question are using macs) This issue only happens for the two users that have submitted a ticket. Still I can not figure out how the local storage is clearing. the only place that clears the token are the two lines you see below.
Additional Information-
I have tried changing my browser settings to have a high security setting. However, it continues to work for me. I have changed the browser settings to not allow cookies at all but that breaks the entire website.
P.S there are no errors or exceptions to go off of. Either on the server or the browser side.
app.module.ts
RouterModule.forRoot([
{ path: 'myorderCards/:id', component: MyOrderComponent,canActivate:[MyAuthGuard] },]),
In auth guard class
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const token = this.storage.getLocalStorageValue('mycurrentUser');
if (token != null && Object.keys(token).length != 0) {
const exTime = token.expires;
if (new Date(exTime.toString()) > new Date(Date.now())) {
return true;
}
else {
this.storage.clearLocalStorage('mycurrentUser');
this.router.navigate(["/mylogin"], { queryParams: { returnUrl: state.url } });
return false;
}
}
else {
this.storage.clearLocalStorage('mycurrentUser');
this.router.navigate(["/mylogin"], { queryParams: { returnUrl: state.url } });
return false;
}
}
}
Your token's expiration time comparison isn't timezone agnostic.
The issue is: If, one way or another, your token includes a time that doesn't provide its timezone assumption, like 9/13/21 5:30 PM (or epoch format not based in UTC), then it would already be expired to the end user who's 1 hour ahead of you. Etc.
As a solution, you could provide all datetimes in UTC, and even then convert it to Unix epoch to discourage people trying to manually 'read' it in their local time.
But for OAuth2, it's more common to include 'expires in' rather than 'expires at'. So the body of an OAuth2 access token is typically this:
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create"
}
expires_in is how long (seconds) the token is valid/alive. When the client receives this token, they assume it expires that long from 'now' (where 'now' is subjective depending on geography). So they calculate the expiration date/time themselves and store it, which sidesteps the issue of timezone conversion altogether.
Then, for two customers authenticating at the same time, one in New York may store 6:00 PM while the one in Chicago may store 5:00 PM as an expiration date, even though they both expire the same moment.
I am using react-native-iap package. I am trying to get latest subscription and check its validity
await RNIap.validateReceiptIos(receiptBody, true).then((receipt) => {
try {
const renewalHistory = receipt.latest_receipt_info
const expiration = renewalHistory[0].expires_date_ms
expired = Date.now() > expiration
productId = renewalHistory[0].product_id
} catch (error) {}
})
I am multiple auto renewal subscription in a single group. I subscribe to one and I execute code above give me the subscribed product and i tag it as subscribed. First try works fine. Now after that I subscribe again another package and run code above gives me the previous subscription not the current that i subscribed. Sometime second steps also works fine but issue came in third step. Reason I found is I am not getting latest subscribed receipt info in latest_receipt_info above.
Have a look to this tutoriel on YouTube it may help you : https://youtu.be/4JLHRV2kiCU
Also, here is what he said in the comment section :
where I write renewalHistory[renewalHistory.length - 1], this works fine in the test environment. HOWEVER, it seems that when the app is published, this doesn't work and you should instead do renewalHistory[0].
I fixed this in my app by first trying to validate using the production URL, using renewalHistory[0].
If you receive a 21007 status code after trying to validate with the production URL, you validate using the test URL using renewalHistory[renewalHistory.length - 1]
This is my query:
var timesRef = db.collection('times');
var timesWeek = timesRef
.where('Date', '>=', this.mon)
.where('Date', '<=', this.sun)
.where('Task', '==', this.task)
.where('User', '==', this.user);
timesWeek.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.data());
});
})
.catch(function(error) {
console.log('Error getting documents: ', error);
});
It yields this error:
Error: The query requires an index. You can create it here:
https://console.firebase.google.com/project/myprojectlog-bd174/database/firestore/indexes?create_index=EgV0aW1lcxoICgRUYXNr...CGggKBERhdGUQAhoMCghfX25hbWVfXxAC
Problem is, when I click that link I arrive at a page with an error message in the middle: "There was an unknown error while processing the request. Try again". Every single time.
Could there be a typical reason why this happens?
I know I can create a composite index manually but I wasn't able to do so successfully (I tried to create one with Date: ascending, Task: ascending, User: ascending, I'm getting the same error).
Just in case here's a screenshot of the browser console.
Verify that the project corresponds with your current account, or try logout / login with the corresponding account for that project.
I think you are creating an index on a different project or you are using wrong project ID somewhere in your code. Your URL points to project myprojectlog-bd174, and in browser console screenshot it is timelog-bd174. Or you replaced manually when pasting here in question? :) Try opening that link from browser console in incognito window, you might have been logged in with wrong user on Firebase console or you have reached a limit for free plan.
I added a route in my docpad.coffee file to handle form submissions, that I validate using the express-validator middleware. Now depending on the validation, I want to redirect the users to the same contact page but displaying either a success message when validation is successful (here I'll send an email), or display the error messages.
I didn't manage to pass the validation message to the template to display it. I tried almost all combinations of dynamic: true/false, res.locals = validationMessages, res.sessions = validationMessages, res.templateData = validationMessages with no success.
Furthermore, adding dynamic: true made the changes to the content not appear at all, whatever refresh strategy I use (private mode, cleaning cache, relaunching Docpad, refreshing without cache, etc.). I should probable file a bug about it.
How to ?
I'm using Docpad 6.53.0 (latest to date), node 0.10.15, on OS X 10.8.4
I cheated on this one a bit by appending a hash to the redirect url (eg: "www.mywebsite.com/#messagesent"). I then use client side javascript to read the hash and then show the appropriate message. Something like this:
if (location.hash == "#messagesent") {
$('#message-sent').show();
setTimeout(function () {
$('#message-sent').fadeOut(1000);
}, 1000);
}
Not quite what you were asking though :)