Repository: ProjectMirador/mirador (js)

Issue:
Origin parameter should be parsed with query string library
The origin parameter is being [appended to the end of the login url with direct string manipulation](https://github.com/ProjectMirador/mirador/blob/30a281108453d70410f05ebe67409a6cb401fc25/src/components/AccessTokenSender.js#L33), e.g. `${url}?origin=${window.origin}`

This is problematic in some use cases where pre-existing parameters may need to be passed through to the login service. In the case where pre-existing parameters exist in the origin url, this results in a url with two “?” delimiters, one for the pre-existing parameters and another for the origin at the end. Therefore, any pre-existing existing parameters will not be readable by the login service. In our use case at Harvard Library, we do have some pre-existing parameters that are required for the login process. We're currently working around the issue by processing the url to remove the redundant "?" delimiter before it is parsed by the login service.

Ideally, this would be done in Mirador by appending the origin parameter using a string parsing library (such as the builtin [UrlSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) library). This will allow any pre-existing parameters to be properly parsed and added in to the url when it's reconstructed by the Mirador code.

Pull request description:
URL-encoding access token service source url; fixes #3902

Patch:
diff --git a/src/components/AccessTokenSender.js b/src/components/AccessTokenSender.js
index c6580aa1..ade30b8c 100644
--- a/src/components/AccessTokenSender.js
+++ b/src/components/AccessTokenSender.js
@@ -12,13 +12,17 @@ export function AccessTokenSender({ handleAccessTokenMessage, url = undefined })
 
   if (!url) return null;
 
+  const src = new URL(url);
+  src.searchParams.append('origin', window.origin);
+  src.searchParams.append('messageId', url);
+
   /**
   login, clickthrough/kiosk open @id, wait for close
   external, no-op
   */
   return (
     <IIIFIFrameCommunication
-      src={`${url}?origin=${window.origin}&messageId=${url}`}
+      src={src.toString()}
       title="AccessTokenSender"
       handleReceiveMessage={onReceiveAccessTokenMessage}
     />


Test patch:
diff --git a/__tests__/src/components/AccessTokenSender.test.js b/__tests__/src/components/AccessTokenSender.test.js
index 377f379c..a0cb575f 100644
--- a/__tests__/src/components/AccessTokenSender.test.js
+++ b/__tests__/src/components/AccessTokenSender.test.js
@@ -22,7 +22,7 @@ describe('AccessTokenSender', () => {
   it('renders properly', () => {
     const { container } = createWrapper({ url: 'http://example.com' });
 
-    expect(container.querySelector('iframe')).toHaveAttribute('src', 'http://example.com?origin=http://localhost&messageId=http://example.com'); // eslint-disable-line testing-library/no-node-access, testing-library/no-container
+    expect(container.querySelector('iframe')).toHaveAttribute('src', 'http://example.com/?origin=http%3A%2F%2Flocalhost&messageId=http%3A%2F%2Fexample.com'); // eslint-disable-line testing-library/no-node-access, testing-library/no-container
   });
 
   it('triggers an action when the iframe sends a message', () => {