Skip to content

Authentication routing clears item routing on page reload #123

Open
campb303 opened this issue Nov 17, 2020 · 26 comments
Open

Authentication routing clears item routing on page reload #123

campb303 opened this issue Nov 17, 2020 · 26 comments
Labels
bug An issue that results in webqueue2 breaking handoff Issues that will not be fixed by the first webqueue2 team (after 7/16/21)

Comments

@campb303
Copy link
Collaborator

Authentication routing serves the application view at / and if a user is not authenticated they are rerouted to /login. Because this check occurs on every page reload, the URL gets reset on page refresh and break viewing an item by going to /<queue>/<number>. This should be addressed with subrouting as shown in react-router docs here.

@campb303 campb303 added bug An issue that results in webqueue2 breaking frontend labels Nov 17, 2020
@campb303 campb303 added this to the v1 milestone Nov 17, 2020
@campb303 campb303 self-assigned this Nov 17, 2020
@campb303 campb303 added the high-priority Needs immediate extra focus label Nov 25, 2020
@campb303 campb303 removed the high-priority Needs immediate extra focus label Dec 7, 2020
@campb303 campb303 added the high-priority Needs immediate extra focus label Jan 5, 2021
@campb303 campb303 added this to To do in v1.0 Mar 8, 2021
@campb303
Copy link
Collaborator Author

campb303 commented Mar 12, 2021

This is likely caused by Apache attempting to load files that correspond to router locations and can be addressed by URL rewrite rules. See Serving Apps w/ Client Side Routing for details on Apache rewrite rules to address this.

# Enable the rewrite module
RewriteEngine On

# Reverse proxy all requests to the API to the API CGI script
# See mod_rewrite docs: https://httpd.apache.org/docs/current/mod/mod_rewrite.html
RewriteRule ^api/(.*)$ http://localhost:5000/api/$1 [P]

+# Defer requests that are not files to client side routing
+# See: https://create-react-app.dev/docs/deployment/#serving-apps-with-client-side-routing
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteRule ^ index.html [QSA,L]

+# Uncomment the following line to serve a maintenance message.
+#RewriteRule .* https://engineering.purdue.edu/webqueue/webqueue2/build/index-maintenance.html [P]
+#DirectoryIndex index-maintenance.html

# Diable Auth
Satisfy any

@campb303
Copy link
Collaborator Author

This was not fixed by adding the client side routing deferral described above but page reloading was fixed reloading. It may be the case that nested routing is the solution for this first issue in this thread. See: https://reactrouter.com/web/example/nesting

@campb303
Copy link
Collaborator Author

Starting to work on this.

@campb303
Copy link
Collaborator Author

Due to React's component rendering lifecycle, the state variables holding login state will render twice every time. On the first render, the state variable will be its default value, in this case false. On the second render, an attempt to refresh the access token is made and if it is successful the state variable will become true. This means that every time there is a change in auth state, the user is temporarily logged out and the login page is re-rendered causing both the login page to flash and the routing to be lost. All of this logic exists in the PrivateRoute component.

The quick fix for this is to keep a copy of the URL match that directed a user to the PrivateRoute (the referer) and on successful login redirect them to the referrer.

The long term fix for this would be to somehow memoize the login state per session or to add a check in AuthProvider's useEffect to preset the state variable for logged in.

@campb303
Copy link
Collaborator Author

Implementing the quick fix for a release now.

@campb303
Copy link
Collaborator Author

It would actually not be too much work to move the token to localstorage and load it form local storage to set a default state value that doesn't cause the login page to render everytime. For now the page is functional. This will be put on hold to get a release out.

@campb303 campb303 modified the milestones: v1-proof-of-concept, v2-production-ready-read-only Mar 16, 2021
@campb303 campb303 removed the frontend label Mar 17, 2021
@campb303 campb303 removed the high-priority Needs immediate extra focus label Mar 29, 2021
@campb303 campb303 modified the milestones: v2-production-ready-read-only, v1-proof-of-concept Mar 29, 2021
@campb303 campb303 removed this from To do in v1.0 Mar 29, 2021
@campb303 campb303 added the high-priority Needs immediate extra focus label Apr 5, 2021
@campb303 campb303 removed the high-priority Needs immediate extra focus label Apr 27, 2021
@campb303
Copy link
Collaborator Author

campb303 commented May 5, 2021

See #15 for more info on authentication and routing.

@wrigh393
Copy link
Collaborator

wrigh393 commented May 7, 2021

I have been doing research on how we can securely store a user session even after they refresh the page. Here are some resources that I have looked at:

  • The Ultimate Guide to handling JWTs on frontend clients (GraphQL)
    • this article discusses a method where we store the access token in memory and the refresh token in a cookie. It goes into detail about how to implement this workflow into a project. I know we aren't using GraphQL so I need to do some further research on how to implement this in our project.
  • JWT Authentication Node.js Tutorial with GraphQL and React
    • This video goes through the process of implementing the strategy from the above article. Some of the processes won't be relevant to our project because we are using different tools but I think a general idea implemented will be helpful in developing an idea of how this may work in webqueue2.

After I finish watching the tutorial I will update this issue with any relevant information.

@wrigh393 wrigh393 added the high-priority Needs immediate extra focus label May 19, 2021
@wrigh393
Copy link
Collaborator

wrigh393 commented May 19, 2021

After looking at the different ways in which to store a user session we were able to look at a few important pieces of info.

  • Storing a user's session by storing the state of the loggedIn state variable is possible but causes some issues with other cookies. When storing this value in localStorage the cookies used to store a users active queues were not read.
  • Storing data in localStorage if not properly implemented can leave an application vulnerable to Cross Site Scripting (XSS) attack, meaning a malicious script can be injected into a site. These usually occur in places where an application uses input from a user within the output it generates without validating or encoding it.

We think that the best course of action may be to develop a way to check if an access token is valid.

@wrigh393
Copy link
Collaborator

After doing some research I found this article that describes how we can store a state variable to local storage so that it persists even after a refresh. The article details creating a custom hook call usePersistedState. Below I will explain how the hook works.


What is localStorage

localStorage is a way to store data on the client's computer. This lets us save data to a users web browser as a key/value pair. localStorage can only be accessed by javascript. The data is stored with no expiration date and is never sent to the server. The downsides of localStorage are that it is plaintext, so it isn't secure, they only accept string data so the need to be serialized.

How to write the hook

We are storing the state variable in localStorage and this means we need to have a key and a value to pass to localStorage so these will be passed to the hook. We will also return both a state and setState.

function usePersistedState(key, defaultValue) {
  const [state, setState] = React.useState(defaultValue);
  return [state, setState];
}

Next, we will set the hook to get data from local storage. We will set the code up so that the state variable is set to the value that is stored in local storage if available or the default value that we pass to the hook. Also in order to make sure that we aren't reading from localStorage on every render we pass a function to the useState hook so that it is only run once.

We also need to serialize our objects due to localStorage only accepting string value. This is accomplished by using the JSON.parse method when getting our data from localStorage and JSON.strigify when we store our data.

function usePersistedState = (key, defaultValue) => {
	const [state, setState] = useState(() => {
		const persistedState = localStorage.getItem(key);
		return persistedState ? JSON.parse(persistedState) : defaultValue;
	});
}

The last step to making this hook work is actually passing the data to localStorage. We will use a useEffect hook as it will allow us to only change the value of the localStorage when certain values change, specifically the key and the state.

function usePersistedState = (key, defaultValue) => {
	const [state, setState] = useState(() => {
		const persistedState = localStorage.getItem(key);
		return persistedState ? JSON.parse(persistedState) : defaultValue;
	});
	useEffect(() => {
		localStorage.setItem(key, JSON.stringify(state));
	}, [state, key]);
	return [state, setState];
}

While this code work for storing the value of the login state thus not clearing routing on refresh it has caused problems with how the QueueSelector component runs and what state values change in the AppView component . One of the things that I have noticed after doing some debugging is that with the state stored in localStorage, the value of the access token is changed when the page is refreshed. When the value is not stored in localStorage the value of the selectedQueues state variable is never changed to the values that are stored in the cookie. I need to do further testing to find out why these things are occurring.

@wrigh393
Copy link
Collaborator

I still haven't been able to identify why storing the login state in localStorage causes the application to behave the way it does with the above implementation. It appears that storing the login state in localStorage is causing issues with how access tokens are given. I have taken a look at how the login state interacts with the access tokens but I haven't been able to identify any relationship that would cause this behavior. Tomorrow @campb303 and I will both take a look to see if we can identify what the cause of this issue is.

@campb303
Copy link
Collaborator Author

Instead of storing the logged in state in local storage, we can store the entire JWT. If the JWT is present on page load, we assume the user is logged in; no key, not logged in. This would allow the user to bypass the login page on first load but presents two new problems.

The first problem is that the only checks for JWT validity right now are HMAC equality (see jwt.io) and expiration time. I think the expiration time we're using now, 15 minutes, is a reasonable amount of time given the automatic refresh on the frontend and the 30 day refresh validity. However, with the only other check being the HMAC equality there is no association of a where the JWT can be used therefore if an attacker were to take the entire JWT and use it in a different session then they could gain unauthorized access.

To counter this, we could store issued keys and some type of fingerprint about where they can be used in the API and if the fingerprint doesn't match we force a new login. For example, if that fingerprint were an IP we would say keyA is only valid for IP address B and if the request's IP address is not B; login again.

@campb303
Copy link
Collaborator Author

It appears that when using the localStorage API in AuthProvider, QueueSelector's useEffect exits prematurely.

// Prepopulate Active Queues from Cookies
useEffect(_ => {
	if (access_token === null) {
		return undefined;
	}
	if (isFirstRender) {
		(async _ => {
			// Get queue counts
			let queueCountsJson = await getQueueCounts(access_token);
			// Find queue count info for queue names in active queues
			let activeQueuesInfo = activeQueues.map((queueName) => (
				queueCountsJson.find(({ name }) => queueName === name)
			));
			// Filter undefined values
			activeQueuesInfo = activeQueuesInfo.filter((entry) => entry !== undefined);
			setValue(activeQueuesInfo);
			setIsFirstRender(false);
		})();
	}
}, []);

The setValue and setIsFirstRender do not run. In testing, even synchronous code places after activeQueuesInfo = ... does not run. I've no idea why this would happen.

To troubleshoot, @wrigh393 is going to undo all changes and implement the same changes one line at a time with testing.

@wrigh393
Copy link
Collaborator

wrigh393 commented May 26, 2021

We were able to find a partial solution to getting the authentication to stay on refresh. Below I will detail what was implemented, how it works, and what problems we still need to address.

What was implemented

We initialize the token state variable to the value of our access token that we stored in localStorage

	const [token, setToken] = useState(localStorage.getItem('access_token'));

We then use the state of the token variable to set the state of the loggedIn variable

	const [loggedIn, setLoggedIn] = useState(token ? true : false)

In the AuthProvider component, we have a function that gets a user a new access token. Here we store the access token that we receive from the API in localStorage to be used in the above implementations.

	async function tryRefresh(csrf_refresh_token) {
		if (csrf_refresh_token === undefined) {
			return false;
		}
		const new_access_token = await refresh(csrf_refresh_token);
		if (!new_access_token) {
			console.error("Failed to refresh access token.")
			return false;
		}
+		localStorage.setItem('access_token', new_access_token)
+		setToken(localStorage.getItem('access_token'));
	}

Issues present

While this allows us to navigate to a specific item by URL this only works if the queue is active in the QueueSelector component. If one were to try to navigate to an item without an active queue it wouldn't open the item. We are still looking into a way to open the ItemView by navigating to the URL. Currently, the ItemView is opened based on the state of the setSidebarOpen state variable in the AppView component and closed inItemViewAppBar component. The important thing to note is that in order for the ItemView to be visible the setSidebarOpen state must be set to true. This is important because we need this to be possible in order to integrate with Slack.

There is also a problem with the access not properly refreshing. We are still looking into the cause of this issue.

@wrigh393
Copy link
Collaborator

In order for items to be opened based on URL two things need to happen:

  1. The sidebarOpen state variable needs to be set to true when navigating to an item via the URL
  2. The activeQueues cookie needs to be set to the proper queue when navigating to an item based on the URL

This may require changes in a few places:

  1. The AppView component. This is where the state of sidebarOpen variable is used to determine if the ItemView component will render
  2. The ItemTable component. In the ItemTable when a row is selected the URL is changed to that item and the sidebar containing the ItemView component is opened
  3. The QueueSelector component. This is where the activeQueues cookie is set. This cookie is used to populate the queues in the QueueSelector. One of the behaviors that I have observed is that if you navigate to an item by URL without the queue being selected in the QueueSelector it won't open until that queue is selected. This is because when there is no queue selected the activeQueues cookie is empty.

I believe that the main two changes that will fix this problem are finding a way to set the sidebar open when navigating to an item with the URL and populating the activeQueues cookie based on the URL. I felt it important to note how ItemTable interacts with these, but I feel that we won't need to change how that functions. My next steps are to look into a way that I can set the state based on what the current route is.

@campb303
Copy link
Collaborator Author

The only place that should need changed is QueueSelector. Modify the activeQueues assignment here to look both at the stored cookie value then at the URL.

Here's a state table for testing:

Value of activeQueues Cookie Value of URL Expected Value fo activeQueues
undefined / []
'bidc' / ['bidc']
'bidc,ce' / ['bidc', 'ce']
undefined /che/1 ['che']
'bidc,ce' /che/1 ['bidc', 'ce', 'che']
'bidc,ce' /bidc/1 ['bidc', 'ce']

@wrigh393
Copy link
Collaborator

While react-router provides a useParams hook that allows us to get the params from our URL this only works if the component is the child of the Route where those params are present. Because the QueueSelector is not a child of the necessary route we can get the URL using window.location.href.

The next step is to parse the URL so that we can get the queue and item number from the URL. The queue that we get from parsing the URL can be used to set the active queues when the cookie doesn't have a value. After getting those values from the URL we need to modify the activeQueues assignment so that it also gets values from the URL and adds them to the array.

We also need to be able to handle situations where we don't get data that we want as well as validating if the queue enters into the URL is a valid queue.

@wrigh393
Copy link
Collaborator

wrigh393 commented Jun 1, 2021

Here are some things that I have found after doing some more experimenting with the QueueSelector component.

  • Initially activeQueues is set to the value of the active-queues cookie and that string is split. This means that it can't be interacted with like an array but normally activeQueues will be an array.
    • This is because it gets the value from the selectedQueues state variable that is defined in the AppView component and is passed to the QueueSelector props.
  • As noted in a previous comment the queue value from the URL needs to be passed to the array that sets the values that are present in the array that contains the values from the cookie.
    • The problem with this is that this occurs in the handleChange function so it would only run when the value is changed by selected a queue in the dropdown that is opened when using the QueueSelector .

Initial activeQueues call

// activeQueues can't be interacted with like an array here because cookies['active-queues'] is not an array.  
//Setting it as an array would put an array in an array when adding queues with the QueueSelector.
 const activeQueues = cookies['active-queues'] !== undefined && filteredUrl === undefined ? cookies['active-queues'].split(',') : 

handleChange funtion

const handleChange = (event, newValue) => {
//Here setValue is called so that we can set the value state variable to whatever the newValue is
        setValue(newValue)

        // Set active-queues cookie to csv of selected queue names
        const activeQueueOptions = {
            path: "/",
            expires: (_ => {
                let expiration_date = new Date();
                expiration_date.setDate(expiration_date.getDate() + 365);
                return expiration_date;
            })()
        };
        const activeQueues = newValue.map((value) => value.name).join(',');
        setCookie("active-queues", activeQueues, activeQueueOptions);
    };

One point of confusion for me is in the handleChange function. I'm not sure exactly where the newValue variable is coming from. I can tell that its value is equal to the value state variable but I do know that it is important for me to understand its role in this function. I think that one of the biggest hurdles is finding a way to add the queue from the URL into the array outside of the handleChange function

@campb303
Copy link
Collaborator Author

campb303 commented Jun 1, 2021

  • Initially activeQueues is set to the value of the active-queues cookie and that string is split. This means that it can't be interacted with like an array but normally activeQueues will be an array.

You're right that the value of the cookie cannot be directly interacted with as an array because it is a string. However, String.split(delimiter: str) creates an array form a string delimited by delimiter so this shouldn't be an issue using the original code e.g:

"a,b,c".split(",")
// ["a", "b", "c"]
  • This is because it gets the value from the selectedQueues state variable that is defined in the AppView component and is passed to the QueueSelector props.

This is backwards. selectedQueues is initialized as an empty array in AppView but set to an array value from within QueueSelector. This doesn't affect parsing values from the cookie or URL.

  • As noted in a previous comment the queue value from the URL needs to be passed to the array that sets the values that are present in the array that contains the values from the cookie.
    • The problem with this is that this occurs in the handleChange function so it would only run when the value is changed by selected a queue in the dropdown that is opened when using the QueueSelector.

AppView's selectedQueues state variable is referenced and modified by QueueSelector's value and setValue respectively. The setValue function is called inside the handleChange callback after QueueSelector's activeQueues variable is set on initial render. So on first render, both the cookie value and URL value can and should be parsed even on first load.

The solution here is just to initialize the activeQueues variable in QueueSelector to a combination of the cookie value and URL value. This could roughly look like:

const activeQueues = ( _ => (
    let queuesFromURL = getQueuesFromURL();
    let queuesFromCookie = getQueuesFromCookie();
    return queuesFromURL + queuesFromCookie;
))();

This solution requires one change on one line within QueueSelector and no other refactoring. It allows for queues from both locations to be used on every render of QueueSelector including the first. No other changes are needed and the code for this has already been loosely written.

@wrigh393
Copy link
Collaborator

wrigh393 commented Jun 2, 2021

I was able to get a rough implementation working that would allow us to get a queue from the URL and add it to the array of queues stored in the active-queues cookie. Below you will find the code used to get this functionality:

 const activeQueues = (() => {
        //get URL
        const url = window.location.href;
        //parse URL
        const urlParts = url.split("/");
        //get queue and number from parsed URL
        const [queue, number] = urlParts.splice(-2);
        //filter parsed value so queue is not set to base URL. if it is equal to baseurl set to undefined else convert value to a string.
        //localhost should be replaced with the process.env.PUBLIC_URL
        const urlQueue = queue == `localhost:3001` ? undefined : queue.toString()

        const cookieQueues = cookies['active-queues'] !== undefined ? cookies['active-queues'] : [];
        const queueArray = urlQueue === undefined ? cookieQueues.split(",") : (cookieQueues + "," + urlQueue).split(",")

        return queueArray
    })();

There are a few things to note about this implementation:

  1. Before this is added to staging the urlQueue constant currently filters out localhost. In production this should be process.env.PUBLIC_URL
  2. There needs to be error handling for when a queue does not exist. Right now even if a queue doesn't exist it is added to the cookie. This should not happen.
  3. We need to check if a queue that is typed into the URL is already in the array. For example, if bidc is already in the array that is stored in the active-queue cookie and it is typed into the URL, it will be added to the cookie again. This doesn't duplicate it in the QueueSelector UI.

@wrigh393
Copy link
Collaborator

wrigh393 commented Jun 4, 2021

The work for this fix was done in a branch that didn't contain the most recent API changes that are present in production so a new branch was created from the staging branch.

@campb303 and I were able to find a way to get the queue from the URL. In order to add the queues from the URL to the active-queues cookie, we created a function that set the value of the cookie to an array of queues. This was necessary because we were now setting the cookie in three places: in the activeQueues function, the useEffect function that populates the activeQueues on the first render, and in the handleChange function that is used by the dropdown to set and unset the activeQueues.

SetActiveQueues function

  /**
     * Set the value of the `active-queues` cookie.
     * @param {Array} queues Array of queue names.
     * @example
     * setActiveQueuesCookie(["che", "bme"])
     */
      const setActiveQueuesCookie = (queues) => {
        const activeQueueOptions = {
            path: "/",
            expires: (_ => {
                let expiration_date = new Date();
                expiration_date.setDate(expiration_date.getDate() + 365);
                return expiration_date;
            })()
        };
        const activeQueues = queues.join(',');
        setCookie("active-queues", activeQueues, activeQueueOptions);
    }

activeQueues

activeQueues was rewritten so that it could get the queue from a URL that contains the queue and number. This is where the problem with the currently implementation is. we should be able to pass process.env.PUBLIC_URL as the first argument of url.replace but the its value seems to be an empty string.

-    const activeQueues = cookies['active-queues'] !== undefined ? cookies['active-queues'].split(',') : [];
+    const activeQueues = (() => {
+       // Get full URL
+        const url = window.location.href;
+       // Get Query Path
+        const queryPath = url.replace("http://localhost:3000", "");
+        // Split Query Path
+        // TODO: Sanitize Output
+        const [_, queue, number] = queryPath.split("/");
+        // Get Queues from Cookie
+       const queuesFromCookie = cookies['active-queues'] !== undefined ? cookies['active-queues'].split(",") : [];
+        // Append Queues from URL to Queues from Cookie
+       if (queue !== "" && !queuesFromCookie.includes(queue)) {
+            queuesFromCookie.push(queue);
+       }
+        return queuesFromCookie
+    })();

Populate queues from cookie

   useEffect( _ => {
        if (access_token === null){
            return undefined;
        }

        if (isFirstRender) {
            ( async _ => {
                // Get queue counts
                let queueCountsJson = await getQueueCounts(access_token);

                // Find queue count info for queue names in active queues
                let activeQueuesInfo = activeQueues.map((queueName) => (
                    queueCountsJson.find( ({ name }) => queueName === name )
                ));

                // Filter undefined values
                activeQueuesInfo = activeQueuesInfo.filter( (entry) => entry !== undefined);

+                setActiveQueuesCookie(activeQueues);
                setValue(activeQueuesInfo);
                setIsFirstRender(false);
            })();
        }
    }, []);

###handleChange
Here we added a variable to hold the array of queues from dropdown so that they could be passed to the function that we created to set the value of the active-queues cookie. We also removed the code that sets the cookie and the options that were being passed to it as this code is now in the setActiveQueuesCookie function.

   const handleChange = (event, newValue) => {
+    let queueNames = [];
+        newValue.map( ({name}) => queueNames.push(name) )
        setValue(newValue)
+        setActiveQueuesCookie(queueNames);
-       // Set active-queues cookie to csv of selected queue names
-      const activeQueueOptions = {
-         path: "/",
-           expires: (_ => {
-                let expiration_date = new Date();
-                expiration_date.setDate(expiration_date.getDate() + 365);
-                return expiration_date;
-            })()
-        };
-        const activeQueues = newValue.map( (value) => value.name).join(',');
-        setCookie("active-queues", activeQueues, activeQueueOptions);
    };

This code should be ready for production once we figure out the issue with process.env.PUBLIC_URL.

@wrigh393
Copy link
Collaborator

wrigh393 commented Jun 7, 2021

Here is a brief update on some findings related to this issue.

  • When passing a path to the homepage in the package.json file the process.env.PUBLIC_URL is set to the value of the homepage. If you pass an entire URL, process.env.PUBLIC_URL is set to an empty string.

  • It seems that this issue stems from the fact that we are in development mode and in development mode, create-react-app only gets the path of process.env.PUBLIC_URL based on this similar issue here.

  • I was able to achieve similar functionality by using window.location.origin in place of explicitly defining the URL

 const activeQueues = (() => {
       // Get full URL
       const url = window.location.href;
       // Get Query Path
-        const queryPath = url.replace("http://localhost:3000", "");
+        const queryPath = url.replace(window.location.origin, "");
        // Split Query Path
        // TODO: Sanitize Output
        const [_, queue, number] = queryPath.split("/");
        // Get Queues from Cookie
       const queuesFromCookie = cookies['active-queues'] !== undefined ? cookies['active-queues'].split(",") : [];
        // Append Queues from URL to Queues from Cookie
       if (queue !== "" && !queuesFromCookie.includes(queue)) {
            queuesFromCookie.push(queue);
       }
        return queuesFromCookie
    })();

There is one issue that I can see with this approach: The origin of the window may not be the same value as process.env.PUBLIC_URL so this may not work in the production build of the project. I am still unsure of how to approach the issue with the PUBLIC_URL environment variable. It seems that in production it should work with that being set but without a reliable way to test in development I can't say for sure that it would work.

@wrigh393
Copy link
Collaborator

wrigh393 commented Jun 8, 2021

In order to test what values are passed to the process.env.PUBLIC_URL environment variable when setting the homepage value in package.json, I will conduct a few tests passing different values and record the value that we receive. This is so we can find the best way to get the queue from a URL.

Value table

Some tests were also conducted after adding values to my hosts file. Those value will be denoted with a *

homepage value process.env.PUBLIC_URL output
"" ""
"localhost" "/localhost"
"http://localhost:3000" ""
"localhost:3000" "/3000"
"wq2:3000"* There was no output and the page was blank
"http://wq2.com:3000" ""

@wrigh393
Copy link
Collaborator

wrigh393 commented Jun 8, 2021

After taking a look at the current webqueue2 production build and the source code shown in the browser I believe that we indeed can only pass a pathname for the homepage value. I came to this conclusion by looking a the src value for the icon that is present on the login screen as well as by looking at the request made to the API as both of these have their paths set using the process.env.PUBLIC_URL variable.

Avatar component src in LoginForm

Soruce Code

 <Avatar 
                   src={process.env.PUBLIC_URL + "/logo512.png"}
                  classes={{ root: classes.avatar_root }}
 />

Value in browser

<img src="/webqueue/webqueue2/build/logo512.png" class="MuiAvatar-img">

API Request

Source Code

let loginResponse = await fetch(`${process.env.PUBLIC_URL}/api/login`, loginInit);

Network Request URL
https://engineering.purdue.edu/webqueue/webqueue2/build/api/login

This leads me to believe that we could achieve the functionality that we are trying to get by filtering out both the window.location.origin and the process.env.PUBLIC_URL values.

For example if the URL is https://engineering.purdue.edu/webqueue/webqueue2/build/ and the homepage value was
"/webqueue/webqueue2/build/" these are the values we should expect:

  • window.location.origin would be https://engineering.purdue.edu
  • process.env.PUBLIC_URL would be /webqueue/webqueue2/build/

By adding these two variables together we should be able to filter our the necessary parts of the URL so that we can get just the queue and the number. This also should make it possible to change where the project is served from without having to change any code present.

@campb303
Copy link
Collaborator Author

campb303 commented Jun 8, 2021

I like this. We can just replace process.env.PUBLIC_URL with window.localtion.origin in the replacement step of the URL parsing and we're good to go.

@campb303 campb303 removed this from the proof-of-concept milestone Jul 6, 2021
@campb303 campb303 removed the high-priority Needs immediate extra focus label Jul 6, 2021
@campb303
Copy link
Collaborator Author

campb303 commented Jul 6, 2021

Changes were made to store the JWT in localStorage. For this to be merged into staging, API changes need to be made to securely verify the JWT server side.

This will not be completed by the current team.

@campb303 campb303 added the handoff Issues that will not be fixed by the first webqueue2 team (after 7/16/21) label Jul 6, 2021
Sign in to join this conversation on GitHub.
Labels
bug An issue that results in webqueue2 breaking handoff Issues that will not be fixed by the first webqueue2 team (after 7/16/21)
Projects
None yet
Development

No branches or pull requests

2 participants