Skip to content
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

Getting error on Appsync websocket connection: You are not authorized to make this call #373

Open
ashwinikumar07 opened this issue Oct 2, 2024 · 6 comments

Comments

@ashwinikumar07
Copy link

ashwinikumar07 commented Oct 2, 2024

Screenshot 2024-10-02 190752

You are not authorized to make this call

I am trying to create aws appsync subscription with IAM auth. I am able to query/mutation the appsync with the same IAM credentials, but getting the exception on websocket connection.

import { Sha256 } from '@aws-crypto/sha256-js';
import { HttpRequest } from '@aws-sdk/protocol-http';
import { SignatureV4 } from '@aws-sdk/signature-v4';

const createWSSUrl = async (signer, request) => {
    let headerString = "";
    // Sign the request asynchronously
    return signer.sign(request).then((signedRequest) => {
        // Create the URL with the signed headers (base64-encoded)
        headerString = Buffer.from(JSON.stringify({
            host: signedRequest.headers.host,
            'x-amz-date': signedRequest.headers['x-amz-date'],
            Authorization: signedRequest.headers['Authorization'],
        })).toString('base64');

        console.log('Signed headers:', signedRequest.headers);

        console.log('Header String (base64-encoded):', headerString);

        // Construct the WebSocket URL after signing is complete
        const wssURL = `wss://xxxxxxxxxxxxxxxxxxx.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=${headerString}&payload=e30=`;

        return wssURL; // Return the WebSocket URL
    })
};

export const auth = async () => {
    const endpoint = new URL('https://xxxxxxxxxxxxxxxxxxxxxxx.appsync-api.us-east-1.amazonaws.com/graphql/connect');

    const credentials = {
        accessKeyId: 'xxxxxxxxxxxxxxxxxxxxxxx',
        secretAccessKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    }

    const signer = new SignatureV4({
        region: 'us-east-1',
        service: 'appsync',
        credentials,
        sha256: Sha256
    });

    const request = new HttpRequest({
        url: endpoint,
        method: 'POST',
        data: "{}",
        headers: {
            "accept": "application/json, text/javascript",
            "content-encoding": "amz-1.0",
            "content-type": "application/json; charset=UTF-8",
            host: endpoint.host,
        }
    });

 createWSSUrl(signer, request).then((wssURL) => {
        console.log('WebSocket URL:', wssURL);
        const ws = new WebSocket(wssURL, ["graphql-ws"]);
        
        ws.onopen = (event) => {
            console.log('WebSocket connected:', event);
            ws.send(
                JSON.stringify({
                type: 'connection_init',
            }));
        };
        ws.onmessage = (event) => {
            console.log('Received message:', event.data);
        };
        ws.onerror = (error) => {
            console.error('WebSocket error:', error);
        };
        // Handle connection close
        ws.onclose = (event) => {
            console.log('WebSocket connection closed:', event);
        };
    }).catch((err) => {
        console.error('Error creating WSS URL:', err);
    });
}
@ashwinikumar07
Copy link
Author

Can anyone help me on this?

@jbbasson
Copy link

jbbasson commented Oct 2, 2024

   const authHeaders = {
      Authorization: `Bearer ${token}`, <-- we use authorizer lambda, change as necessary
      host: `${host.replace('https://', '').replace('/graphql', '')}`, // need to strip the 'https://' and '/graphql' from your appsync http url
      // can specify any other custom headers
    };
   
    const encodedHeaders = btoa(JSON.stringify(authHeader));
    const emptyPayload = btoa(JSON.stringify({}));

    // we use rxjs WebSocket wrapper for WebSocket()
    return this.wsFactory.makeSocket({
      url: `${your_websocket_url}?header=${encodedHeaders}&payload=${emptyPayload}`,
      protocol: 'graphql-ws',
      openObserver: {
        next: () => {
          this.webSocket$!.next({ type: 'connection_init' });
        },
      },
      closeObserver: {
        next: () => {},
      },
    });

@ashwinikumar07
Copy link
Author

@jbbasson I am using IAM appsync auth and getting the above error.

@jbbasson
Copy link

jbbasson commented Oct 2, 2024

we had to strip the https:// prefix and /graphql post fix from the https endpoint of appsync before setting is as the host in the auth header

@ashwinikumar07
Copy link
Author

@jbbasson I tried strip the https:// prefix and /graphql post fix from the https endpoint of appsync. But still getting the same error.

@jbbasson
Copy link

jbbasson commented Oct 4, 2024

can you show your current version of code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants