amplify-js
                                
                                
                                
                                    amplify-js copied to clipboard
                            
                            
                            
                        Authenticated graphql requests with SSR missing custom attributes
Describe the bug
We have recently switched to using SSR with Next.js, and we have been trying to modify some of our api calls to be able to be used with server side rendering. However, we ran into an issue because in our backend, we use the identity.claims in an appsync call to determine the identity of a user and get some of their common attributes, but when using API.graphql from withSSRContext, it looks like those fields were omitted. We believe this is because the type of authentication is token_use: access instead of token_use: id, but looking through the docs there does not seem to be a good way to change our server side calls to use the ID Token.
Expected behavior
As you can see below, when an auth is made by initializing a graphql client on client side , there is extra information in identity.claims such as Name, referral, classInfo, etc. However, when the same API call is made using API.graphql() using const { API } = withSSRContext(context), the identity.claims has the generic values. When calling Auth.currentAuthenticatedUser in both SSR and on client side, the payload returns correctly, and all of the added values are visible in the payload (user.signInUserSession.idToken.payload).
Code Snippet
API call made from client side
"identity": {
    "claims": {
      "sub": "...",
      "access_pool": "0",
      "cognito:groups": [
        "Teachers"
      ],
      "email_verified": true,
      "iss": "...",
      "cognito:username": "...",
      "aud": "...",
      "referral": "...",
      "classinfo": "...",
      "token_use": "id",
      "auth_time": 1595474525,
      "name": "...",
      "ID": "...",
      "exp": 1595478125,
      "iat": 1595474525,
      "access_pool_expiry": "0",
      "email": "..."
    },
    "defaultAuthStrategy": "ALLOW",
    "groups": [
      "Teachers"
    ],
    "issuer": "...",
    "sourceIp": [
      "..."
    ],
    "sub": "...",
    "username": "..."
  },
API Call made from SSR
  "identity": {
    "claims": {
      "sub": "...",
      "device_key": "...",
      "cognito:groups": [
        "Teachers"
      ],
      "token_use": "access",
      "scope": "aws.cognito.signin.user.admin",
      "auth_time": 1614323009,
      "iss": "...",
      "exp": 1614326991,
      "iat": 1614323391,
      "jti": "...",
      "client_id": "...",
      "username": "..."
    },
    "defaultAuthStrategy": "ALLOW",
    "groups": [
      "Teachers"
    ],
    "issuer": "...",
    "sourceIp": [
      "..."
    ],
    "sub": "...",
    "username": "..."
  },
                                    
                                    
                                    
                                
Any update on this? Seems like you are currently unable to use email as the identityClaim using Next JS
Can you share more code on how to reproduce or see this behavior?  For starters, it sounds like Auth. currentAuthenticatedUser() is correct on both client & server, but API.graphql is missing email.  How could I reproduce & see that?
There's been testing to validate that Auth & API work as expected with SSR, but it seems like there's more nuanced behavior that hasn't been validated.
Hey @ericclemmons I'll post what code I was using to encounter the error.
So I was using the following code for Amplify.configure:
Amplify.configure({
  ...awsconfig,
  // https://github.com/aws-amplify/amplify-cli/issues/3794
  graphql_headers: async () => {
    try {
      const token = (await Auth.currentSession()).idToken.jwtToken;
      return { Authorization: token };
    } catch (e) {
      console.error(e);
      return {};
    }
  },
  ssr: true,
});
and then for example, in one of my dynamic route pages, I have this code for getServersideProps:
export const getServerSideProps: GetServerSideProps = async (context) => {
  const { req } = context;
  const SSR = withSSRContext({ req });
  const input: GetBoardQueryVariables = {
    id: context?.params?.id as string,
  };
  const response = (await SSR.API.graphql({
    query: getBoard,
    variables: input,
    authMode: GRAPHQL_AUTH_MODE.AMAZON_COGNITO_USER_POOLS,
  })) as { data: GetBoardQuery; errors: any[] };
  return {
    props: {
      board: response.data.getBoard,
    },
  };
};
IIRC, the error was "No current user" in the console.error, inside the catch of the Amplify.configure.
The getServersideProps code worked fine until I modified the  graphql_headers to try and use email for identityClaim.
When I changed that graphql_headers though, it stopped working, saying No current user on the server-side.
For now, I've just made all my authenticated requests client-side - which isn't that big of a deal for my project.
Let me know if you need any more information.
I have a repo for this code if that would be more helpful. The two pages can be found here:
Note you might need to be on the multi-user branch
_app.tsx
/board/[id].tsx - The commented out section at the bottom does not work with my setup.
Closing this out as we are now on v6 of aws-amplify and have been unable to reproduce this issue. If it occurs and is consistently reproducible in v6, please open a new issue with environment info, package versions, and reproduction steps.