discord/embedded-app-sdk

Help getting my client to talk to my backend with CSP

erikthe-viking opened this issue · 1 comments

Im trying to get my app ported to Discord. My frontend is showing up but i cant get my backend to bypass the CSP. My system is running on docker containers . Do you think nginx is causing these problems? Ive spent all weekend trying to get this to work so any help would be greatly appreciated. H

Heres my stack: Django, Create React APP, Ngnix, Docker

Docker compose file:

`version: '3.8'

services:
  db:
    container_name: database
    image: postgis/postgis:12-3.3
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myuser -d mydb"]
      interval: 10s
      timeout: 10s
      retries: 5
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
      #- postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
      - POSTGRES_DB=mydb
    networks:
      - mynetwork
  backend:
    container_name: backend
    image: backend-image
    build:
      context: ./backend
      dockerfile: DockerFile.dev.backend
    ports:
      - "8000:8000"
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DEBUG=True # Change in production
      - DB_HOST=db
      - DB_PORT=5432
      # Add other environment variables needed for your Django app
    volumes:
      - ./backend:/app
    networks:
      - mynetwork

  frontend:
    container_name: frontend
    image: frontend-image
    build:
      context: ./frontend
      dockerfile: DockerFile.frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend
    volumes:
      - ./frontend:/app
      - /app/node_modules
    networks:
      - mynetwork
      
  nginx:
    container_name: reverse-proxy-nginx
    image: nginx-image
    build:
      context: ./Nginx/
      dockerfile: DockerFile.dev.nginx
    ports:
      - "80:80"
    depends_on:
      - frontend
    networks:
      - mynetwork

  
volumes:
  postgres_data:

networks:
  mynetwork:
    driver: bridge`

  NGINX
  
  `http {
  upstream frontend {
      server frontend:3000;
  }

  upstream backend {
      server backend:8000;
  }

  server {
      listen 80;

      location / {
          # Assuming the frontend handles routing and all URIs should be sent to the frontend
          proxy_pass http://frontend;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }

      location /api/ {
          # Assuming all backend requests start with /api/
          proxy_pass http://backend;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      }
  }
}

events {
  worker_connections 1024;
}`

index.js


`import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom';
import { DiscordSDK, patchUrlMappings } from "@discord/embedded-app-sdk";
import './index.css';
import * as serviceWorker from './serviceWorker';
import 'bootstrap/dist/css/bootstrap.min.css';
import { AuthProvider } from './AuthContext';
import { GoogleOAuthProvider } from '@react-oauth/google';
import App from './app';
import { getApiUrl } from './config/config';

const isProd = process.env.NODE_ENV === 'production';

const DiscordApp = () => {
  const [isSDKReady, setIsSDKReady] = useState(false);
  const [auth, setAuth] = useState(null);
  const [isDiscordEnvironment, setIsDiscordEnvironment] = useState(false);

  useEffect(() => {
    const setupEnvironment = async () => {
      const urlParams = new URLSearchParams(window.location.search);
      const frameId = urlParams.get('frame_id');
      setIsDiscordEnvironment(!!frameId);

      if (isProd && isDiscordEnvironment) {
        await patchUrlMappings([
          { prefix: '/api', target: 'tunnel.clearedgear.com/api' }
        ]);
      }

      if (frameId) {
        const discordSdk = new DiscordSDK(process.env.REACT_APP_DISCORD_CLIENT_ID);

        try {
          await discordSdk.ready();
          console.log("Discord SDK is ready");

          const { code } = await discordSdk.commands.authorize({
            client_id: process.env.REACT_APP_DISCORD_CLIENT_ID,
            response_type: "code",
            state: "",
            prompt: "none",
            scope: ["identify", "guilds"],
          });

          const tokenExchangeUrl = getApiUrl('/discord/token');

          const response = await fetch(tokenExchangeUrl, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({ code }),
          });

          if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
          }

          const { access_token } = await response.json();

          const authResult = await discordSdk.commands.authenticate({ access_token });

          if (authResult == null) {
            throw new Error("Authenticate command failed");
          }

          setAuth(authResult);
          console.log("Discord SDK is authenticated");
        } catch (error) {
          console.error("Error setting up Discord SDK:", error);
        }
      }

      setIsSDKReady(true);
    };

    setupEnvironment();
  }, []);

  if (!isSDKReady) {
    return <div>Loading...</div>;
  }

  return (
    <Router>
      <React.StrictMode>
        <GoogleOAuthProvider clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}>
          <AuthProvider>
            <App discordAuth={auth} isDiscordEnvironment={isDiscordEnvironment} />
          </AuthProvider>
        </GoogleOAuthProvider>
      </React.StrictMode>
    </Router>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<DiscordApp />);

serviceWorker.unregister();`

Have you set up url mappings for your app via the dev portal?

https://discord.com/developers/docs/activities/development-guides#url-mapping