Open asp3 opened 1 year ago
Hi @asp3, thank you for opening this issue. I've taken a look at it and haven't yet reproduced this issue. However I have some follow up questions:
@aws-amplify/<module>
vs aws-amplify
)getServerSideProps
method here?Here's is what is working for me as expected:
import { Amplify, Auth, withSSRContext } from 'aws-amplify';
import awsExports from "../src/aws-exports";
Amplify.configure({ ...awsExports, ssr: true });
...
export async function getServerSideProps(ctx){
const SSR = withSSRContext(ctx);
try {
const session = await SSR.Auth.currentSession();
return {
props: { msg: session.idToken.payload }
}
} catch (e) {
console.log("ERROR", e);
return {
props: { msg: e }
}
}
}
...
With the above, I am able to get my custom claims in my props including token_use: 'id'
. Are you doing this differently from the above? Any additional context will be helpful here.
Hi @nadetastic thank you for the response!
That code snippet works for me as well, and I am able to see the custom claims in my next app as well. However, the issue I have is with appsync graphql calls, the claims there seem to only include the access token
const { API, Auth } = withSSRContext(context);
const session = await Auth.currentSession();
console.log("session", session.idToken.payload); // Works as expected
const userId = await fetchUserId(Auth);
const { textbookId, code } = context.query;
let textbook = null;
let serverUser = null;
if (!userId && !code) {
return {
props: {
textbook: null,
serverUser: null,
},
};
} else {
// This call only has the access token payload
serverUser = API.graphql({
query: gql(getCurrentUser),
variables: {
input: {
userId,
},
},
})
.then(res => res?.data?.getCurrentUser)
.catch(console.error);
}
Thanks for the help!
Ok thanks you @asp3 for the additional context - to confirm, are you passing code
and textbook
in the query parameters of the URL?
@nadetastic Yeah, the call hits our lambda code, which gets called from Appsync.
The appsync resolver,
getCurrentUser(input: GetCurrentUserInput): UserDetails!
which is connected to the lambda code that just prints the event
passed in to the lambda handler, which is pasted above as event.identity
.
So I assume that the withSSRContext API library works differently than the other one, somehow?
@asp3 I'd like to clarify my understanding of the flow, which I am assuming is the following:
WithSSRContext().API.graphql
)If this is correct, what part seems to have the issue?
I am also curious what const userId = await fetchUserId(Auth)
does under the hood and if it successfully returns userId
So fetchUserId is just a simple wrapper around the Auth library
export const fetchUserId = async (Auth): Promise<string> => {
try {
const userId = (await Auth.currentAuthenticatedUser()).signInUserSession.idToken.payload.ID;
refreshToken(Auth);
return userId;
} catch {
return null;
}
};
It does successfully return, which means from SSRContext, we are able to get the idToken payload. However, the issue is that when we make the graphql call and the appsync is invoked, the payload is that of the accessToken, not the idToken. (printing the event
from the lambda handler of the appsync query/mutation)
@nadetastic
After doing some digging, I can see that the error happens here:
However, when running the same function in my getServerSideProps call, Auth.currentSession().getAccessToken().getJwtToken()
, it return the token successfully.
@nadetastic
Also some other info that we found out:
The error that we were getting, No Current User, has been fixed! We figured out the issue happened since we had been destructuring the return from withSSRContext
.
const {Auth, API} = withSSRContext(context)
...
API.graphql(....)
// FAILS - No Current User
Changed to
const SSR = withSSRContext(context)
SSR.API.graphql(...)
// NO error thrown
However, the issue stated at the beginning of the issue still stands, where the event in the parameters that is received in our lambda (called through appsync) does not contain the info of the authenticated user, since it only has the accessToken info, instead of the idToken info.
The only way I have found that fixes this issue so far is by changing https://github.com/aws-amplify/amplify-js/blob/main/packages/api-graphql/src/GraphQLAPI.ts#L174 to
- Authorization: session.getAccessToken().getJwtToken(),
+ Authorization: session.getIdToken().getJwtToken(),
After this patch, I can see the proper information in my lambda! I wonder if this is configurable through some parameter, and if this is a safe change to make. @nadetastic
A bit more into this,
looks like turning off Device Tracking from Cognito User Pool Settings fixes this!
https://stackoverflow.com/questions/46879876/aws-cognito-invalid-refresh-token
Not sure why, but I turned on debug logging, and it seems that the Refresh Session did not work because of this, and works as expected after turning this off. Very weird! @nadetastic
Hi @asp3 a fix for SSR with API as discussed in https://github.com/aws-amplify/amplify-js/issues/10786 was released with https://github.com/aws-amplify/amplify-js/pull/10831
Could you test with 5.0.10
?
Following up on this issue, I was able to reproduce with aws-amplify@5.0.10
. Updating the title to better reflect the problem
Before opening, please confirm:
JavaScript Framework
React, Next.js
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
Describe the bug
IDENTITY when called from ssr.
IDENTITY from client side call.
The problem seems pretty straightforward, the
token_use
key is access instead of ID, which I also assume is the reason why the data from the PreTokenTrigger is not populated as well. We use custom fields (like a custom username field), which is why it is necessary to get the overridden fields from the PreToken generation.Expected behavior
SSRContext should have the same auth information as the client side call.
Reproduction steps
set up amplify environment, and set up a pretoken trigger on the user pool that is used. Then, make client side and server side calls and see the differences in payload in appsync.
Code Snippet
The value of the identity is above, printed in lambda (called from AppSync)
Log output
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response