https://supertokens.com/ logo
Title
r

ronflai

12/20/2022, 10:28 PM
Hello everyone ! I'm trying to setup supertokens with appsync but I have trouble to make it works. I created a lambda with this code https://supertokens.com/docs/passwordless/serverless/with-aws-lambda/authorizer#2-add-code-to-the-lambda-function-handler and I added a new authorization provider in appsync with this lambda authorizer. Then when I try to test it by using the queries tool in aws console appsync with as authorization token the user_id I got in my front end app after successfully logged in I got the following error message:
{
  "errors": [
    {
      "errorType": "AuthorizerFailureException",
      "message": "The adapter was unable to infer a handler to use for the event. This is likely related to how the Lambda function was invoked. (Are you testing locally? Make sure the request payload is valid for a supported handler.)"
    }
  ]
}
Someone have any idea how to fix this ? Thanks.
n

nkshah2

12/21/2022, 5:07 AM
Hi
@porcellus might be able to help, he’ll be in later today
p

porcellus

12/21/2022, 8:59 AM
Hi, I'm not sure how the queries tool work, but using the userId as an authorization token doesn't sound right. You could try the access-token, but I'm not sure if it'll work as the authorizer uses cookies from the request.
r

ronflai

12/21/2022, 9:14 AM
Hello @porcellus Thanks for the answer ! So If I understand well, the lambda authorizer use cookies from the request to validate the authentication ? Im' not sure to understand because in the code I linked the
user_id
is used in the
generate_allow
function
What should I do in my react app then to send the right property in my graphql calls ?
p

porcellus

12/21/2022, 9:58 AM
if the react app is using our SDK, it's handled automatically
it sends the access-token
about the authorizer and cookies: the authorizer uses the cookies of the request to get/check the access token which contains the userid that you can use in generate_allow
r

ronflai

12/21/2022, 11:45 AM
We are using different domain for front and back, and on my front end app I can see se set-cookie header in response to the consume call and I can even see the
sAccessToken
cookie with my backend domain but after refreshing the page the
sAccessToken
and the
sRefreshToken
disappear . Is it because we're not using the same domain between front and back ?
p

porcellus

12/21/2022, 12:16 PM
It's most likely just not showing up in the dev tools, because by default it only shows the cookies of the current domain.
r

ronflai

12/21/2022, 12:36 PM
ok buy why when I do ```const accessTokenPayload = await Session.getAccessTokenPayloadSecurely(); const customClaimValue = accessTokenPayload.customClaim console.log("accessTokenPayload: ", accessTokenPayload) console.log("customClaimValue: "), customClaimValue```I got
{}
and
undefined
?
p

porcellus

12/21/2022, 2:26 PM
Oh sorry, I missed this notification. How did you add
customClaim
into the access token payload?
r

ronflai

12/21/2022, 2:28 PM
I don't have custom claim sorry but I should be able to see the access token ? why do I get an empty object ?
p

porcellus

12/21/2022, 2:29 PM
This is the access token payload, not the entire access token. We use HTTP-only cookies to store the token for security reasons
r

ronflai

12/21/2022, 2:31 PM
what does it mean ? That I can't log the access token in the console ? Btw I also try to call
await Session.attemptRefreshingSession();
just to test and I got a 401 but I have an existing session
p

porcellus

12/21/2022, 2:33 PM
Yeah, your front-end code doesn't have access to it.
By default. You can potentially change how these things work if necessary.
Oh, and if you have a valid session, you should not get a 401. That's something we could investigate. What does the response look like? (body/response headers)
r

ronflai

12/21/2022, 2:58 PM
This is for the consume call:
p

porcellus

12/21/2022, 3:01 PM
This is looking ok
r

ronflai

12/21/2022, 3:05 PM
And I don't know why but I don't see the refresh call in the network
p

porcellus

12/21/2022, 3:06 PM
Well, attemptRefreshingSession should always call that
r

ronflai

12/21/2022, 3:07 PM
but what I can see is the response from my API to the refresh:
{
  "statusCode": 401,
  "headers": {
    "content-length": "26",
    "id-refresh-token": "remove",
    "access-control-expose-headers": "id-refresh-token",
    "content-type": "application/json; charset=utf-8",
    "access-control-allow-credentials": "****",
    "access-control-allow-origin": "http://localhost:3001",
    "vary": "Origin"
  },
  "multiValueHeaders": {
    "set-cookie": [
      "sAccessToken=\"\"; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/; SameSite=none; Secure",
      "sIdRefreshToken=\"\"; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/; SameSite=none; Secure",
      "sRefreshToken=\"\"; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/session/refresh; SameSite=none; Secure"
    ]
  },
  "body": "{\"message\":\"unauthorised\"}",
  "isBase64Encoded": false
}
Ok I finaly found the request in my network
So this is the refresh request:
General:
  Request URL: https://staging.api.lizy.io/auth/api/session/refresh
  Request Method: POST
  Status Code: 401
  Remote Address: 54.192.111.7:443
  Referrer Policy: strict-origin-when-cross-origin

Response Headers:
  access-control-allow-credentials: true
  access-control-allow-origin: http://localhost:3001
  access-control-expose-headers: id-refresh-token
  content-length: 26
  content-type: application/json; charset=utf-8
  date: Wed, 21 Dec 2022 15:16:54 GMT
  id-refresh-token: remove
  set-cookie: sAccessToken=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/; SameSite=none; Secure
  set-cookie: sIdRefreshToken=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/; SameSite=none; Secure
  set-cookie: sRefreshToken=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/session/refresh; SameSite=none; Secure
  vary: Origin
  via: 1.1 d3dc7fce70a4cf01f01f6bf06755098c.cloudfront.net (CloudFront)
  x-amz-apigw-id: dgJ4HFaqFiAFYlA=
  x-amz-cf-id: ZMSacDcpMOL7FEoAkKlZhV4NMTXGVcmWgI3ekY3gUZS8XUZOmVr8oQ==
  x-amz-cf-pop: MRS52-P2
  x-amzn-remapped-content-length: 26
  x-amzn-requestid: 822ea0b4-3143-4aa0-88b9-e61d66b514da
  x-amzn-trace-id: Root=1-63a32366-167c0d65779e98173ef0df8a;Sampled=0
  x-cache: Error from cloudfront

Response:
  {"message":"unauthorised"}
p

porcellus

12/21/2022, 3:23 PM
I'll check it out in a few minutes
It looks like the backend SDK is not getting the cookies. Can you also show the request headers?
r

ronflai

12/21/2022, 3:35 PM
yes
authority: staging.api.lizy.io
  :method: POST
  :path: /auth/api/session/refresh
  :scheme: https
  accept: */*
  accept-encoding: gzip, deflate, br
  accept-language: en-US,en;q=0.9
  cache-control: no-cache
  content-length: 0
  cookie: sAccessToken="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInZlcnNpb24iOiIyIn0%3D.eyJzZXNzaW9uSGFuZGxlIjoiZmMyYTYwMjAtNjg4MC00ZGM2LTlmMDQtZTcyZDk2MjcwMWI0IiwidXNlcklkIjoiOGQ3NzcxZjgtYmU1Ni00YTBmLTlkMGUtMTkyZDMxNGFlZGE3IiwicmVmcmVzaFRva2VuSGFzaDEiOiJlM2RiNWQ0MThhMzc0MzI1NjM1ZmYwYzMzMTA1YmE1NmJlYTI0Y2VlYWI0MzEzZTAzZDllNDAzMzU4ODA4MDZmIiwicGFyZW50UmVmcmVzaFRva2VuSGFzaDEiOm51bGwsInVzZXJEYXRhIjp7fSwiYW50aUNzcmZUb2tlbiI6bnVsbCwiZXhwaXJ5VGltZSI6MTY3MTY0MDYyNjYwOSwidGltZUNyZWF0ZWQiOjE2NzE2MzcwMjY2MDksImxtcnQiOjE2NzE2MzcwMjY2MDl9.G6IfZRX9pm9RlMZKz4Gmq6v7mDg9iQH9GokcYJGikfzCi9I5xNmqdOUohzDstd7dFY8siqKTCoibUnFjqpJGSHlgoLiC7YFia2ssBz6bFaEH9PPYtiRPVpFf/ijw6S7UzlQTIzvhkApqIz1tLwe7FDEiRf8Csv5qwOa0b60YLZXJl/3nbWN5X%2BZgW6QiczOdRED%2BfaZdZ54CBedHXOsgrAhvX1dYJoihoiuf9E4VKe0o5mH3irW2cSMCuacmnBucS6ETokcjf2VDhccy2uzYMoPwNWIyyReexHgYRityMpTcJnihO3nmMZDYsWKvJiAbBRIFmZBOnUZha9q8mBvYLA%3D%3D"; sIdRefreshToken=d100f5a1-69bd-4fb6-bd55-9bc554bacbb4
  fdi-version: 1.8,1.9,1.10,1.11,1.12,1.13,1.14,1.15
  origin: http://localhost:3001
  pragma: no-cache
  referer: http://localhost:3001/
  rid: session
  sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Brave";v="108"
  sec-ch-ua-mobile: ?0
  sec-ch-ua-platform: "Linux"
  sec-fetch-dest: empty
  sec-fetch-mode: cors
  sec-fetch-site: cross-site
  sec-gpc: 1
  user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
this is the request headers
p

porcellus

12/21/2022, 3:47 PM
r

ronflai

12/21/2022, 3:50 PM
It has to be set on the back or the front end config ? or both ?
And why the create code and the verify requests works but not the refresh one ?
p

porcellus

12/21/2022, 3:57 PM
create/consume code and others like it work, because I assume you've set the
apiBasePath
on the frontend to include the gateway path as well.
verify calls work because the access token cookie is sent with every request to the backend domain
refresh fails to work because the
apiBasePath
settings on the frontend and backend do not match. If they do, there is some other issue.
r

ronflai

12/21/2022, 3:59 PM
alright I got it. Thanks for the investigation and the answers. I 'll test it and tell you if t's work !
p

porcellus

12/21/2022, 4:05 PM
happy to help 🙂
r

ronflai

12/21/2022, 4:35 PM
I tried to add
api_gateway_path=f"/{get_current_stage()}"
in the backend config but it did not work and I noticed that for the
api_domain
setting we are using
api_domain = (
    "https://api.lizy.io"
    if get_current_stage() == Stage.PROD
    else f"https://{get_current_stage()}.api.lizy.io"
)
so it should already have the notion of stage
to have better view I'll share my front end and backend conf
This is the front end conf :
SuperTokens.init({
      appInfo: {
        apiDomain:
          process.env.BACKEND == "production"
            ? "https://api.lizy.io"
            : "https://staging.api.lizy.io",
        apiBasePath: "/auth/api",
        appName: "Lizy authentication",
      },
      recipeList: [Session.init(), Passwordless.init()],
    });
and the backend config:
api_domain = (
    "https://api.lizy.io"
    if get_current_stage() == Stage.PROD
    else f"https://{get_current_stage()}.api.lizy.io"
)
website_domain = (
    "https://www.lizy.be" if get_current_stage() == Stage.PROD else "https://staging.www.lizy.be/"
)

init(
    app_info=InputAppInfo(
        app_name="Lizy authentication services",
        api_domain=api_domain,
        website_domain=website_domain,
        api_base_path="/",
        website_base_path="/auth",
    ),
    supertokens_config=SupertokensConfig(
        connection_uri= ********,
        api_key= ********
    ),
    framework="fastapi",
    recipe_list=[
        session.init(cookie_same_site="none"),
        passwordless.init(
            flow_type="MAGIC_LINK",
            contact_config=ContactEmailOnlyConfig(),
        ),
    ],
    mode="asgi",
)
and in the backend the
api_base_path
is "/" because we also have
handler = Mangum(app, api_gateway_base_path="/auth/api")
p

porcellus

12/21/2022, 5:07 PM
this isn't really about staging environments - the
apiBasePath
needs match on the frontend and backend.
in this case it looks like you should add
/auth/api
as the api_gateway_path on the backend
r

ronflai

12/21/2022, 5:17 PM
i figured out when I sent the message to you ^^
Thanks for the help the refresh token is working. Do you have any idea on what to do next to integrate with appsync and securing grapqhl call ?
p

porcellus

12/21/2022, 5:30 PM
The last time I tried it, all I did was what we wrote here: https://supertokens.com/docs/passwordless/serverless/with-aws-lambda/appsync-integration
I mean I never tried to use the query tool in aws, I just started using the frontend