-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT REQUEST] Add an example of a route using proxy authenticated proxy route #295
Comments
+1 |
Thanks for opening this issue. We think this is something we missed but we want to make it as easy as possible. We think we'll add a new API to authenticate requests from a storefront context. To help us design this, please can you confirm that you are referring to App proxy requests from a storefront: https://shopify.dev/docs/apps/online-store/app-proxies If you can, we'll make this a priority. |
Yes that will be so cool. And yes Im talking about those app proxies. |
any update ?? |
Hi @pkyek1 I am hoping to prioritize it after the unauthenticated admin client ships, which seems to be affecting more people right now. |
Excited to see this making progress! Thanks @byrichardpowell! |
I also need this, thanks @byrichardpowell |
That would be really cool to have :) I'm also trying to figure out how to make a proxy route with remix |
Hey everyone 👋 Please can you confirm the following API suits your needs: // app/routes/**/*.jsx
import {authenticate} from "~/shopify.server"
export async function loader({ request }) {
const {admin, session} = await authenticate.public.storefrontAppProxy(request);
admin.graphql
admin.rest
admin.rest.resources
// ... etc
} If possible, I would also be grateful for a sentence or two that describes you use case. Thanks in advance 🙏 |
@byrichardpowell Thanks for getting back so quickly! Really appreciate your fast turn around of the Remix changes! My use case I need to create discount codes using a third party loyalty points system. |
Hi @byrichardpowell Thank for you & team for the fast development. My use case is I want client call to this request will required pass this authentication. Then we have a param or function returned to we can call an Admin API or Storefront API (Rest or Graphql). At this moment of my project, I want to call storefront api product by variant id param. Thanks for advance! |
Thanks @sam-masscreations . That makes sense. @huykon Are you able to achieve what you need using the admin API? We think we should return a storefront API client, but that might take us a little longer, because it's a new concept for the package. |
@byrichardpowell yes I think to grap admin API, our package is supporting now, I want to get storefront API at my app proxy remix loader route so do you have idea to get it? |
Hey @huykon, Right now I'm fairly sure we'll be adding the storefront client to the Remix package, but hopefully the docs above can be helpful in the meantime. |
Hey everyone 👋 I think we are going to tackle this in two releases. Release 1 import {authenticate} from "~/shopify.server"
export async function loader({ request }) {
// Throws Response if request is not valid
await authenticate.public.appProxy(request);
const {searchParams} = new URL(request)
const customerId = searchParams.get("logged_in_customer_id")
// Do whatever you need here
} This satisfies the use case where you do not need Shopify's API's, as described by @sam-masscreations:
This will ship when this PR ships (hopefully next week). Release 2 // app/shopify.server.js
const shopify = shopifyApp({
// Specify the token to use for storefront access tokens
// privateAppStorefrontAccessToken will also work, but will marked as deprecated.
privateStorefrontAccessToken: "12abc"
// etc.
}) // app/routes/**/*.js
import {authenticate} from "~shopify.server"
import { json } from "@remix-run/node";
export async function loader() {
const {storefront} = authenticate.public.appProxy(request)
const response = storefront.graphql("...QUERY", {
variables: {
"my": "variable"
}
})
const data = await response.json();
return json(data)
} We are still figuring out the best DX here, but would love your input if anything stands out. What about Admin API Access? Would love to hear your thoughts and any counterpoints here. |
Hey, thanks for considering this. Online Store Example I'm wondering what an example of the theme app extension would look like from a liquid snippet for instance. Admin Access App proxies are often used to update specific customer data or metadata (metafields/metaobjects). How is this possible with the current approach using the SF API? Thanks! |
Thanks @blanklob Online Store Example
Do you mean how Remix would respond with liquid? If so, I assume something like:
Is that what you mean? Admin Access
Good point. I'm going to chat with a few people internally about this. Technically you could do this:
But it may be better if we return the admin context directly from |
Awesome thanks! I wan't talking about returning Liquid I was talking how would the |
@byrichardpowell Thanks for being active on this. I am not able to use the I can only use Note: I am new to Remix and overall Shopify App development so any info you can provide is highly appreciated. |
Hey @itszoose The |
Update import {authenticate} from "~/shopify.server"
export async function loader({request}) {
const {admin, session, liquid} = authenticate.public.appProxy(request)
// If there is a session for the shop you can access admin API's
// admin.graphql()
// admin.rest.get()
// admin.rest.resources
// If there is no session, these properties will be undefined
// The signature of liquid function matches Remix's json function:
// https://remix.run/docs/en/main/utils/json
// Except it takes a 3rd argument `{layout: false}`
// If passed Shopify will render the liquid Response outside of themes layout.
return liquid("Hello {{shop.name}}")
} This means we will return the admin API clients if we can. |
This will really be cool if shipped can't wait! How is the online store fetch will look like. I am assuming something like this? export async function getSomething() {
const response = await fetch('/app/proxy', {
method: 'GET',
headers: ??
});
const data = await response.text()
return data;
} |
@blanklob Yep, exactly. Worth noting that your Remix app could respond with JSON. So if you want it access your app proxy from a fetch request you don't have to return liquid. |
@byrichardpowell Does that mean that in the meantime we have no way of authenticating the proxy requests? Also if you could shed some light on what the |
@byrichardpowell how is the request is authenticated from an Online Store call is there any headers that we should be aware of? |
Unfortunately. Really sorry about that. We should release a new version of
|
@blanklob You can read about how to auth an app proxy request here: https://shopify.dev/docs/apps/online-store/app-proxies The WIP implementation of this is:
As far as I can see, I don't think there are any special headers involved in authentication. It's all URL Params which are added by Shopify. |
@byrichardpowell Does that mean that I can use the |
@itszoose It's strictly for checkout requests. Imagine it's called |
Hey everyone 👋 We've released version Please upgrade Returning Liquid Responses// app/routes/**\/.ts
import {authenticate} from '~/shopify.server';
export async function loader({request}) {
const {liquid} = authenticate.public.appProxy(request);
return liquid('Hello {{shop.name}}');
} Using the admin GraphQL API// app/routes/**\/.ts
import {authenticate} from '~/shopify.server';
export async function loader({request}) {
const {liquid, admin} = authenticate.public.appProxy(request);
const response = await admin.graphql('QUERY');
const json = await response.json();
return json(json);
} WIP: Storefront APIThis release does not contain the storefront API, but that is next on my list. I'm still figuring this out, but it may look something like this: // app/routes/**\/.ts
import {authenticate} from '~/shopify.server';
export async function loader({request}) {
const {storefront} = authenticate.public.appProxy(request);
const response = await storefront.graphql("QUERY GOES HERE")
const json = await response.json();
return json(json);
} You won't be able to use this storefront API until a later release |
Awesome thanks! |
Hello @byrichardpowell, So if the extension make an api call to my app: {appDomain}/api/{resource} , should the api use public auth, like this?
|
Hey @LHongy That looks correct to me, incase it helps here is a tutorial that includes authenticating a checkout request: https://shopify.dev/docs/apps/checkout/product-offers/post-purchase/getting-started#define-the-offer-and-sign-changeset-endpoints |
@byrichardpowell
|
Thanks a lot! |
@byrichardpowell @blanklob @byrichardpowell this update is really great just want to know about admin api post request the usecase is i am trying to create checkout with admin api the code
}); it create checkout but in response line_items is empty array and note is null and note_attribute is also {} may be there is syntax error or the post request is not working can anyone help me in this |
@byrichardpowell @huykon @huykon any update ?? |
any updates on this? how to handle the CORS? the other methods like autehnticate.public exposed a cors fucntion to return |
Hey everyone 👋 We've released version 1.3.0 of App Proxy import {json} from '@remix-run/node';
import {authenticate} from '~/shopify.server';
export async function loader({request}) {
const {storefront} = await authenticate.public.appProxy(request);
const response = await storefront.graphql('{blogs(first: 10) {nodes{id}}}');
return json(await response.json());
} Unauthenticated Storefront import {json} from '@remix-run/node';
import {unauthenticated} from '~/shopify.server';
import {customAuthenticateRequest} from '~/helpers';
export async function loader({request}) {
await customAuthenticateRequest(request);
const {storefront} = await unauthenticated.storefront(
'my-shop.myshopify.com',
);
const response = await storefront.graphql('{blogs(first: 10) {nodes{id}}}');
return json(await response.json());
} There is a lot of discussion in this PR, but the original post is about App Proxy. To solve this we've released:
Given this solves the discussions around App Proxy I'm going to close this issue. @pkyek1 since this is a question about the GraphQL API please could you open a separate issue or ask in our partner Slack: https://join.slack.com/t/shopifypartners/shared_invite/zt-sdr2quab-mGkzkttZ2hnVm0~8noSyvw @mikesosa in my experiments CORS wasn't an issue since App Proxy is a server to server request. You should be able to configure your app proxy, and then use |
@blanklob or anyone else run into signature validation errors with actions? I've opened Shopify/shopify-app-js#455 with details of what I've run into. Thanks for sharing your thoughts. |
Can anybody help? I'm trying to return a liquid response from a remix app proxy route using the app template.
But I'm getting the following error:
How do I include the liquid function? |
@joeainsworth Looks like you may be missing an const { admin, session, liquid } = await authenticate.public.appProxy(
request,
); Unfortunately I found that client side JS doesn't work on app proxy pages, have an issue open here: #436 - hopefully it gets addressed at some point and there's a way to build in client-side JS. |
It seems most all the examples here do not work. I cannot interact with Admin or Storefront API. Even using copy & paste. |
Would be really appreciated to provide an example route (or documentation for developers) for integrating a proxy route
app/proxy
that can be queried from an online store channel.-- Idea --
A good example would include a simple authenticated fetch request to update customer data from a theme app extension or a metafield ressource on the customer that is created by the app from an app block.
The text was updated successfully, but these errors were encountered: