@commercetools-frontend/mc-dev-authentication 22.2.0 → 22.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) commercetools GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -18,13 +18,14 @@ var path__default = /*#__PURE__*/_interopDefault(path);
|
|
|
18
18
|
|
|
19
19
|
function logoutRoute(response) {
|
|
20
20
|
var _context;
|
|
21
|
-
|
|
22
21
|
let additionalCookieParameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
23
22
|
// NOTE: removing the cookie only works if your are running the MC API
|
|
24
23
|
// locally, otherwise the cookie won't get removed as it's set to a
|
|
25
24
|
// proper domain (e.g. commercetools.com), which we can't unset from localhost.
|
|
26
|
-
response.setHeader('Set-Cookie', _concatInstanceProperty__default["default"](_context = ["mcAccessToken=''",
|
|
27
|
-
|
|
25
|
+
response.setHeader('Set-Cookie', _concatInstanceProperty__default["default"](_context = ["mcAccessToken=''",
|
|
26
|
+
// <-- unset the value
|
|
27
|
+
'Path=/', "Expires=".concat(new Date(0).toUTCString()),
|
|
28
|
+
// <-- put a date in the past
|
|
28
29
|
'HttpOnly']).call(_context, additionalCookieParameters).join('; '));
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -32,17 +33,15 @@ const pages$1 = {
|
|
|
32
33
|
"loginPage": "<html>\n <head>\n <title>Login (development only)</title>\n <style>\n html,\n body {\n font: 1em sans-serif;\n padding: 0;\n margin: 0;\n height: 100vh;\n width: 100vw;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n margin-top: 32px;\n }\n\n body > * + * {\n margin-top: 32px;\n }\n\n .title {\n width: 355px;\n }\n\n form {\n display: flex;\n flex-direction: column;\n width: 355px;\n }\n\n form > * + * {\n margin: 16px 0 0;\n }\n\n .field {\n border: 0;\n }\n\n .field > * + * {\n margin: 8px 0 0;\n }\n\n label {\n display: block;\n }\n\n input {\n width: 100%;\n height: 24px;\n outline: none;\n }\n\n input:focus {\n border: 1px solid cornflowerblue;\n }\n\n input:focus:invalid {\n border-color: red;\n }\n\n abbr {\n text-decoration: none;\n color: orangered;\n }\n\n #errors > div {\n background-color: red;\n color: #eee;\n padding: 8px;\n border-radius: 4px;\n }\n\n .info {\n background-color: #b5e1fd;\n padding: 8px;\n border-radius: 4px;\n }\n </style>\n </head>\n <body>\n <div class=\"title\">\n <h3>\n Welcome to the Merchant Center authorization page for local development\n </h3>\n <small>\n This page is only available in development mode and is necessary to\n authenticate yourself. In production environment, we use our own\n authentication service.\n </small>\n </div>\n <form id=\"login\">\n <div id=\"errors\"></div>\n <div class=\"field\">\n <label for=\"email\">\n Email<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input id=\"email\" name=\"email\" type=\"text\" required=\"required\" />\n </div>\n <div class=\"field\">\n <label for=\"password\">\n Password<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required=\"required\"\n />\n </div>\n <div>\n <button type=\"submit\" aria-label=\"Sign in\">Sign in 🚀</button>\n </div>\n </form>\n <script>\n /* eslint-disable no-var,vars-on-top */\n /**\n * NOTE:\n * This code is only used in development mode.\n * It authenticates a developer using the same mechanisms\n * as when not running in development. However,\n * this runs on the same domain as the developer.\n */\n window.addEventListener('load', function loaded() {\n var form = document.getElementById('login');\n form.addEventListener('submit', function onSubmit(event) {\n event.preventDefault();\n authorize();\n });\n\n function authorize() {\n var data = new FormData(form);\n var payload = {\n email: data.get('email'),\n password: data.get('password'),\n };\n\n var queryParams = new URLSearchParams(window.location.search);\n if (queryParams.has('response_type')) {\n // OIDC params\n payload.client_id = queryParams.get('client_id');\n payload.response_type = queryParams.get('response_type');\n payload.scope = queryParams.get('scope');\n payload.state = queryParams.get('state');\n payload.nonce = queryParams.get('nonce');\n }\n\n var container = document.getElementById('errors');\n // Clean up error message elements\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const url = '__MC_API_URL__/tokens';\n\n window\n .fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(payload),\n })\n .then(function handleResponse(response) {\n if (response.ok) {\n return response.json().then(function onSuccess(result) {\n // Handle OIDC redirect.\n if (queryParams.has('response_type')) {\n window.location.replace(result.redirectTo);\n } else {\n window.localStorage.setItem('isAuthenticated', true);\n var searchParams = new URLSearchParams(\n window.location.search\n );\n var redirectTo = searchParams.get('redirectTo') || '/';\n window.location.replace(redirectTo);\n }\n });\n }\n return response.text().then(function onError(responseText) {\n var message;\n try {\n var parsedResponse = JSON.parse(responseText);\n message = parsedResponse.message;\n } catch (e) {\n console.warn(\n `Failed to parse error response for ${url}:`,\n responseText\n );\n\n message = responseText;\n }\n var errorMessage = document.createTextNode(message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n })\n .catch(function onNetworkError(error) {\n var errorMessage = document.createTextNode(error.message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n }\n });\n </script>\n </body>\n</html>\n",
|
|
33
34
|
"logoutPage": "<html>\n <head>\n <title>Logout (development only)</title>\n <script>\n window.localStorage.removeItem('isAuthenticated');\n window.localStorage.removeItem('loginStrategy');\n window.localStorage.removeItem('activeProjectKey');\n </script>\n </head>\n <body>\n <div>\n <h3>This is the logout page for local development.</h3>\n <p>\n Be aware that you might still have an active session as the cookie is\n assigned to a production domain (e.g. commercetools.com) which we can't\n unset from localhost. This is only a problem on local development and we\n intend fix this in the future.\n </p>\n <p>\n You can\n <a href=\"#\" onclick=\"window.location='/login'+window.location.search;\"\n >go to the login page</a\n >\n now.\n </p>\n </div>\n </body>\n</html>\n"
|
|
34
35
|
};
|
|
35
|
-
|
|
36
36
|
// https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros
|
|
37
|
-
const trimTrailingSlash$1 = value => value.replace(/\/$/, '');
|
|
38
37
|
|
|
38
|
+
const trimTrailingSlash$1 = value => value.replace(/\/$/, '');
|
|
39
39
|
function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
40
40
|
const htmlLogin = pages$1.loginPage.replace(new RegExp('__MC_API_URL__', 'g'), trimTrailingSlash$1(applicationConfig.env.mcApiUrl));
|
|
41
41
|
const htmlLogout = pages$1.logoutPage;
|
|
42
42
|
const isDevAuthenticationMiddlewareDisabled = String(applicationConfig.env.disableAuthRoutesOfDevServer) === 'true' || applicationConfig.env.servedByProxy;
|
|
43
43
|
return (request, response, next) => {
|
|
44
44
|
var _applicationConfig$en, _applicationConfig$en2;
|
|
45
|
-
|
|
46
45
|
if (request.originalUrl === '/api/graphql') {
|
|
47
46
|
response.statusCode = 404;
|
|
48
47
|
response.setHeader('Content-Type', 'application/json');
|
|
@@ -51,21 +50,17 @@ function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
|
51
50
|
}));
|
|
52
51
|
return;
|
|
53
52
|
}
|
|
54
|
-
|
|
55
53
|
if ((_applicationConfig$en = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en !== void 0 && (_applicationConfig$en2 = _applicationConfig$en.oidc) !== null && _applicationConfig$en2 !== void 0 && _applicationConfig$en2.authorizeUrl) {
|
|
56
54
|
var _applicationConfig$en3, _applicationConfig$en4, _context;
|
|
57
|
-
|
|
58
55
|
// Handle login page for OIDC workflow when developing against a local MC API.
|
|
59
56
|
if ((_applicationConfig$en3 = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en3 !== void 0 && (_applicationConfig$en4 = _applicationConfig$en3.oidc) !== null && _applicationConfig$en4 !== void 0 && _startsWithInstanceProperty__default["default"](_context = _applicationConfig$en4.authorizeUrl).call(_context, 'http://localhost')) {
|
|
60
57
|
var _context2;
|
|
61
|
-
|
|
62
58
|
if (_startsWithInstanceProperty__default["default"](_context2 = request.originalUrl).call(_context2, '/login/authorize')) {
|
|
63
59
|
if (isDevAuthenticationMiddlewareDisabled) {
|
|
64
60
|
next();
|
|
65
61
|
} else {
|
|
66
62
|
response.send(htmlLogin);
|
|
67
63
|
}
|
|
68
|
-
|
|
69
64
|
return;
|
|
70
65
|
}
|
|
71
66
|
}
|
|
@@ -76,23 +71,18 @@ function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
|
76
71
|
} else {
|
|
77
72
|
response.send(htmlLogin);
|
|
78
73
|
}
|
|
79
|
-
|
|
80
74
|
return;
|
|
81
75
|
}
|
|
82
|
-
|
|
83
76
|
if (request.originalUrl === '/logout') {
|
|
84
77
|
logoutRoute(response);
|
|
85
|
-
|
|
86
78
|
if (isDevAuthenticationMiddlewareDisabled) {
|
|
87
79
|
next();
|
|
88
80
|
} else {
|
|
89
81
|
response.send(htmlLogout);
|
|
90
82
|
}
|
|
91
|
-
|
|
92
83
|
return;
|
|
93
84
|
}
|
|
94
85
|
}
|
|
95
|
-
|
|
96
86
|
next();
|
|
97
87
|
};
|
|
98
88
|
}
|
|
@@ -101,22 +91,21 @@ const pages = {
|
|
|
101
91
|
"loginPage": "<html>\n <head>\n <title>Login (development only)</title>\n <style>\n html,\n body {\n font: 1em sans-serif;\n padding: 0;\n margin: 0;\n height: 100vh;\n width: 100vw;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n margin-top: 32px;\n }\n\n body > * + * {\n margin-top: 32px;\n }\n\n .title {\n width: 355px;\n }\n\n form {\n display: flex;\n flex-direction: column;\n width: 355px;\n }\n\n form > * + * {\n margin: 16px 0 0;\n }\n\n .field {\n border: 0;\n }\n\n .field > * + * {\n margin: 8px 0 0;\n }\n\n label {\n display: block;\n }\n\n input {\n width: 100%;\n height: 24px;\n outline: none;\n }\n\n input:focus {\n border: 1px solid cornflowerblue;\n }\n\n input:focus:invalid {\n border-color: red;\n }\n\n abbr {\n text-decoration: none;\n color: orangered;\n }\n\n #errors > div {\n background-color: red;\n color: #eee;\n padding: 8px;\n border-radius: 4px;\n }\n\n .info {\n background-color: #b5e1fd;\n padding: 8px;\n border-radius: 4px;\n }\n </style>\n </head>\n <body>\n <div class=\"title\">\n <h3>\n Welcome to the Merchant Center authorization page for local development\n </h3>\n <small>\n This page is only available in development mode and is necessary to\n authenticate yourself. In production environment, we use our own\n authentication service.\n </small>\n </div>\n <form id=\"login\">\n <div id=\"errors\"></div>\n <div class=\"field\">\n <label for=\"email\">\n Email<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input id=\"email\" name=\"email\" type=\"text\" required=\"required\" />\n </div>\n <div class=\"field\">\n <label for=\"password\">\n Password<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required=\"required\"\n />\n </div>\n <div>\n <button type=\"submit\" aria-label=\"Sign in\">Sign in 🚀</button>\n </div>\n </form>\n <script>\n /* eslint-disable no-var,vars-on-top */\n /**\n * NOTE:\n * This code is only used in development mode.\n * It authenticates a developer using the same mechanisms\n * as when not running in development. However,\n * this runs on the same domain as the developer.\n */\n window.addEventListener('load', function loaded() {\n var form = document.getElementById('login');\n form.addEventListener('submit', function onSubmit(event) {\n event.preventDefault();\n authorize();\n });\n\n function authorize() {\n var data = new FormData(form);\n var payload = {\n email: data.get('email'),\n password: data.get('password'),\n };\n\n var queryParams = new URLSearchParams(window.location.search);\n if (queryParams.has('response_type')) {\n // OIDC params\n payload.client_id = queryParams.get('client_id');\n payload.response_type = queryParams.get('response_type');\n payload.scope = queryParams.get('scope');\n payload.state = queryParams.get('state');\n payload.nonce = queryParams.get('nonce');\n }\n\n var container = document.getElementById('errors');\n // Clean up error message elements\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const url = '__MC_API_URL__/tokens';\n\n window\n .fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(payload),\n })\n .then(function handleResponse(response) {\n if (response.ok) {\n return response.json().then(function onSuccess(result) {\n // Handle OIDC redirect.\n if (queryParams.has('response_type')) {\n window.location.replace(result.redirectTo);\n } else {\n window.localStorage.setItem('isAuthenticated', true);\n var searchParams = new URLSearchParams(\n window.location.search\n );\n var redirectTo = searchParams.get('redirectTo') || '/';\n window.location.replace(redirectTo);\n }\n });\n }\n return response.text().then(function onError(responseText) {\n var message;\n try {\n var parsedResponse = JSON.parse(responseText);\n message = parsedResponse.message;\n } catch (e) {\n console.warn(\n `Failed to parse error response for ${url}:`,\n responseText\n );\n\n message = responseText;\n }\n var errorMessage = document.createTextNode(message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n })\n .catch(function onNetworkError(error) {\n var errorMessage = document.createTextNode(error.message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n }\n });\n </script>\n </body>\n</html>\n",
|
|
102
92
|
"logoutPage": "<html>\n <head>\n <title>Logout (development only)</title>\n <script>\n window.localStorage.removeItem('isAuthenticated');\n window.localStorage.removeItem('loginStrategy');\n window.localStorage.removeItem('activeProjectKey');\n </script>\n </head>\n <body>\n <div>\n <h3>This is the logout page for local development.</h3>\n <p>\n Be aware that you might still have an active session as the cookie is\n assigned to a production domain (e.g. commercetools.com) which we can't\n unset from localhost. This is only a problem on local development and we\n intend fix this in the future.\n </p>\n <p>\n You can\n <a href=\"#\" onclick=\"window.location='/login'+window.location.search;\"\n >go to the login page</a\n >\n now.\n </p>\n </div>\n </body>\n</html>\n"
|
|
103
93
|
};
|
|
104
|
-
|
|
105
94
|
// https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros
|
|
106
|
-
const trimTrailingSlash = value => value.replace(/\/$/, ''); // Make sure any symlinks in the project folder are resolved:
|
|
107
|
-
// https://github.com/facebook/create-react-app/issues/637
|
|
108
95
|
|
|
96
|
+
const trimTrailingSlash = value => value.replace(/\/$/, '');
|
|
109
97
|
|
|
98
|
+
// Make sure any symlinks in the project folder are resolved:
|
|
99
|
+
// https://github.com/facebook/create-react-app/issues/637
|
|
110
100
|
const appDirectory = fs__default["default"].realpathSync(process.cwd());
|
|
111
|
-
|
|
112
101
|
const resolveApp = relativePath => path__default["default"].resolve(appDirectory, relativePath);
|
|
113
|
-
|
|
114
102
|
const paths = {
|
|
115
103
|
appBuild: resolveApp('public')
|
|
116
|
-
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// This transformer will generate a development `login` and `logout` HTML files
|
|
117
107
|
// and copy them to the application public folder.
|
|
118
108
|
// This is necessary to run the application locally in production mode.
|
|
119
|
-
|
|
120
109
|
const transformerLocal = compiledHtml => {
|
|
121
110
|
const htmlLogin = pages.loginPage.replace(new RegExp('__MC_API_URL__', 'g'), trimTrailingSlash(compiledHtml.env.mcApiUrl));
|
|
122
111
|
const htmlLogout = pages.logoutPage;
|
|
@@ -18,13 +18,14 @@ var path__default = /*#__PURE__*/_interopDefault(path);
|
|
|
18
18
|
|
|
19
19
|
function logoutRoute(response) {
|
|
20
20
|
var _context;
|
|
21
|
-
|
|
22
21
|
let additionalCookieParameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
23
22
|
// NOTE: removing the cookie only works if your are running the MC API
|
|
24
23
|
// locally, otherwise the cookie won't get removed as it's set to a
|
|
25
24
|
// proper domain (e.g. commercetools.com), which we can't unset from localhost.
|
|
26
|
-
response.setHeader('Set-Cookie', _concatInstanceProperty__default["default"](_context = ["mcAccessToken=''",
|
|
27
|
-
|
|
25
|
+
response.setHeader('Set-Cookie', _concatInstanceProperty__default["default"](_context = ["mcAccessToken=''",
|
|
26
|
+
// <-- unset the value
|
|
27
|
+
'Path=/', "Expires=".concat(new Date(0).toUTCString()),
|
|
28
|
+
// <-- put a date in the past
|
|
28
29
|
'HttpOnly']).call(_context, additionalCookieParameters).join('; '));
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -32,17 +33,15 @@ const pages$1 = {
|
|
|
32
33
|
"loginPage": "<html>\n <head>\n <title>Login (development only)</title>\n <style>\n html,\n body {\n font: 1em sans-serif;\n padding: 0;\n margin: 0;\n height: 100vh;\n width: 100vw;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n margin-top: 32px;\n }\n\n body > * + * {\n margin-top: 32px;\n }\n\n .title {\n width: 355px;\n }\n\n form {\n display: flex;\n flex-direction: column;\n width: 355px;\n }\n\n form > * + * {\n margin: 16px 0 0;\n }\n\n .field {\n border: 0;\n }\n\n .field > * + * {\n margin: 8px 0 0;\n }\n\n label {\n display: block;\n }\n\n input {\n width: 100%;\n height: 24px;\n outline: none;\n }\n\n input:focus {\n border: 1px solid cornflowerblue;\n }\n\n input:focus:invalid {\n border-color: red;\n }\n\n abbr {\n text-decoration: none;\n color: orangered;\n }\n\n #errors > div {\n background-color: red;\n color: #eee;\n padding: 8px;\n border-radius: 4px;\n }\n\n .info {\n background-color: #b5e1fd;\n padding: 8px;\n border-radius: 4px;\n }\n </style>\n </head>\n <body>\n <div class=\"title\">\n <h3>\n Welcome to the Merchant Center authorization page for local development\n </h3>\n <small>\n This page is only available in development mode and is necessary to\n authenticate yourself. In production environment, we use our own\n authentication service.\n </small>\n </div>\n <form id=\"login\">\n <div id=\"errors\"></div>\n <div class=\"field\">\n <label for=\"email\">\n Email<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input id=\"email\" name=\"email\" type=\"text\" required=\"required\" />\n </div>\n <div class=\"field\">\n <label for=\"password\">\n Password<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required=\"required\"\n />\n </div>\n <div>\n <button type=\"submit\" aria-label=\"Sign in\">Sign in 🚀</button>\n </div>\n </form>\n <script>\n /* eslint-disable no-var,vars-on-top */\n /**\n * NOTE:\n * This code is only used in development mode.\n * It authenticates a developer using the same mechanisms\n * as when not running in development. However,\n * this runs on the same domain as the developer.\n */\n window.addEventListener('load', function loaded() {\n var form = document.getElementById('login');\n form.addEventListener('submit', function onSubmit(event) {\n event.preventDefault();\n authorize();\n });\n\n function authorize() {\n var data = new FormData(form);\n var payload = {\n email: data.get('email'),\n password: data.get('password'),\n };\n\n var queryParams = new URLSearchParams(window.location.search);\n if (queryParams.has('response_type')) {\n // OIDC params\n payload.client_id = queryParams.get('client_id');\n payload.response_type = queryParams.get('response_type');\n payload.scope = queryParams.get('scope');\n payload.state = queryParams.get('state');\n payload.nonce = queryParams.get('nonce');\n }\n\n var container = document.getElementById('errors');\n // Clean up error message elements\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const url = '__MC_API_URL__/tokens';\n\n window\n .fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(payload),\n })\n .then(function handleResponse(response) {\n if (response.ok) {\n return response.json().then(function onSuccess(result) {\n // Handle OIDC redirect.\n if (queryParams.has('response_type')) {\n window.location.replace(result.redirectTo);\n } else {\n window.localStorage.setItem('isAuthenticated', true);\n var searchParams = new URLSearchParams(\n window.location.search\n );\n var redirectTo = searchParams.get('redirectTo') || '/';\n window.location.replace(redirectTo);\n }\n });\n }\n return response.text().then(function onError(responseText) {\n var message;\n try {\n var parsedResponse = JSON.parse(responseText);\n message = parsedResponse.message;\n } catch (e) {\n console.warn(\n `Failed to parse error response for ${url}:`,\n responseText\n );\n\n message = responseText;\n }\n var errorMessage = document.createTextNode(message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n })\n .catch(function onNetworkError(error) {\n var errorMessage = document.createTextNode(error.message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n }\n });\n </script>\n </body>\n</html>\n",
|
|
33
34
|
"logoutPage": "<html>\n <head>\n <title>Logout (development only)</title>\n <script>\n window.localStorage.removeItem('isAuthenticated');\n window.localStorage.removeItem('loginStrategy');\n window.localStorage.removeItem('activeProjectKey');\n </script>\n </head>\n <body>\n <div>\n <h3>This is the logout page for local development.</h3>\n <p>\n Be aware that you might still have an active session as the cookie is\n assigned to a production domain (e.g. commercetools.com) which we can't\n unset from localhost. This is only a problem on local development and we\n intend fix this in the future.\n </p>\n <p>\n You can\n <a href=\"#\" onclick=\"window.location='/login'+window.location.search;\"\n >go to the login page</a\n >\n now.\n </p>\n </div>\n </body>\n</html>\n"
|
|
34
35
|
};
|
|
35
|
-
|
|
36
36
|
// https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros
|
|
37
|
-
const trimTrailingSlash$1 = value => value.replace(/\/$/, '');
|
|
38
37
|
|
|
38
|
+
const trimTrailingSlash$1 = value => value.replace(/\/$/, '');
|
|
39
39
|
function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
40
40
|
const htmlLogin = pages$1.loginPage.replace(new RegExp('__MC_API_URL__', 'g'), trimTrailingSlash$1(applicationConfig.env.mcApiUrl));
|
|
41
41
|
const htmlLogout = pages$1.logoutPage;
|
|
42
42
|
const isDevAuthenticationMiddlewareDisabled = String(applicationConfig.env.disableAuthRoutesOfDevServer) === 'true' || applicationConfig.env.servedByProxy;
|
|
43
43
|
return (request, response, next) => {
|
|
44
44
|
var _applicationConfig$en, _applicationConfig$en2;
|
|
45
|
-
|
|
46
45
|
if (request.originalUrl === '/api/graphql') {
|
|
47
46
|
response.statusCode = 404;
|
|
48
47
|
response.setHeader('Content-Type', 'application/json');
|
|
@@ -51,21 +50,17 @@ function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
|
51
50
|
}));
|
|
52
51
|
return;
|
|
53
52
|
}
|
|
54
|
-
|
|
55
53
|
if ((_applicationConfig$en = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en !== void 0 && (_applicationConfig$en2 = _applicationConfig$en.oidc) !== null && _applicationConfig$en2 !== void 0 && _applicationConfig$en2.authorizeUrl) {
|
|
56
54
|
var _applicationConfig$en3, _applicationConfig$en4, _context;
|
|
57
|
-
|
|
58
55
|
// Handle login page for OIDC workflow when developing against a local MC API.
|
|
59
56
|
if ((_applicationConfig$en3 = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en3 !== void 0 && (_applicationConfig$en4 = _applicationConfig$en3.oidc) !== null && _applicationConfig$en4 !== void 0 && _startsWithInstanceProperty__default["default"](_context = _applicationConfig$en4.authorizeUrl).call(_context, 'http://localhost')) {
|
|
60
57
|
var _context2;
|
|
61
|
-
|
|
62
58
|
if (_startsWithInstanceProperty__default["default"](_context2 = request.originalUrl).call(_context2, '/login/authorize')) {
|
|
63
59
|
if (isDevAuthenticationMiddlewareDisabled) {
|
|
64
60
|
next();
|
|
65
61
|
} else {
|
|
66
62
|
response.send(htmlLogin);
|
|
67
63
|
}
|
|
68
|
-
|
|
69
64
|
return;
|
|
70
65
|
}
|
|
71
66
|
}
|
|
@@ -76,23 +71,18 @@ function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
|
76
71
|
} else {
|
|
77
72
|
response.send(htmlLogin);
|
|
78
73
|
}
|
|
79
|
-
|
|
80
74
|
return;
|
|
81
75
|
}
|
|
82
|
-
|
|
83
76
|
if (request.originalUrl === '/logout') {
|
|
84
77
|
logoutRoute(response);
|
|
85
|
-
|
|
86
78
|
if (isDevAuthenticationMiddlewareDisabled) {
|
|
87
79
|
next();
|
|
88
80
|
} else {
|
|
89
81
|
response.send(htmlLogout);
|
|
90
82
|
}
|
|
91
|
-
|
|
92
83
|
return;
|
|
93
84
|
}
|
|
94
85
|
}
|
|
95
|
-
|
|
96
86
|
next();
|
|
97
87
|
};
|
|
98
88
|
}
|
|
@@ -101,22 +91,21 @@ const pages = {
|
|
|
101
91
|
"loginPage": "<html>\n <head>\n <title>Login (development only)</title>\n <style>\n html,\n body {\n font: 1em sans-serif;\n padding: 0;\n margin: 0;\n height: 100vh;\n width: 100vw;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n margin-top: 32px;\n }\n\n body > * + * {\n margin-top: 32px;\n }\n\n .title {\n width: 355px;\n }\n\n form {\n display: flex;\n flex-direction: column;\n width: 355px;\n }\n\n form > * + * {\n margin: 16px 0 0;\n }\n\n .field {\n border: 0;\n }\n\n .field > * + * {\n margin: 8px 0 0;\n }\n\n label {\n display: block;\n }\n\n input {\n width: 100%;\n height: 24px;\n outline: none;\n }\n\n input:focus {\n border: 1px solid cornflowerblue;\n }\n\n input:focus:invalid {\n border-color: red;\n }\n\n abbr {\n text-decoration: none;\n color: orangered;\n }\n\n #errors > div {\n background-color: red;\n color: #eee;\n padding: 8px;\n border-radius: 4px;\n }\n\n .info {\n background-color: #b5e1fd;\n padding: 8px;\n border-radius: 4px;\n }\n </style>\n </head>\n <body>\n <div class=\"title\">\n <h3>\n Welcome to the Merchant Center authorization page for local development\n </h3>\n <small>\n This page is only available in development mode and is necessary to\n authenticate yourself. In production environment, we use our own\n authentication service.\n </small>\n </div>\n <form id=\"login\">\n <div id=\"errors\"></div>\n <div class=\"field\">\n <label for=\"email\">\n Email<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input id=\"email\" name=\"email\" type=\"text\" required=\"required\" />\n </div>\n <div class=\"field\">\n <label for=\"password\">\n Password<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required=\"required\"\n />\n </div>\n <div>\n <button type=\"submit\" aria-label=\"Sign in\">Sign in 🚀</button>\n </div>\n </form>\n <script>\n /* eslint-disable no-var,vars-on-top */\n /**\n * NOTE:\n * This code is only used in development mode.\n * It authenticates a developer using the same mechanisms\n * as when not running in development. However,\n * this runs on the same domain as the developer.\n */\n window.addEventListener('load', function loaded() {\n var form = document.getElementById('login');\n form.addEventListener('submit', function onSubmit(event) {\n event.preventDefault();\n authorize();\n });\n\n function authorize() {\n var data = new FormData(form);\n var payload = {\n email: data.get('email'),\n password: data.get('password'),\n };\n\n var queryParams = new URLSearchParams(window.location.search);\n if (queryParams.has('response_type')) {\n // OIDC params\n payload.client_id = queryParams.get('client_id');\n payload.response_type = queryParams.get('response_type');\n payload.scope = queryParams.get('scope');\n payload.state = queryParams.get('state');\n payload.nonce = queryParams.get('nonce');\n }\n\n var container = document.getElementById('errors');\n // Clean up error message elements\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const url = '__MC_API_URL__/tokens';\n\n window\n .fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(payload),\n })\n .then(function handleResponse(response) {\n if (response.ok) {\n return response.json().then(function onSuccess(result) {\n // Handle OIDC redirect.\n if (queryParams.has('response_type')) {\n window.location.replace(result.redirectTo);\n } else {\n window.localStorage.setItem('isAuthenticated', true);\n var searchParams = new URLSearchParams(\n window.location.search\n );\n var redirectTo = searchParams.get('redirectTo') || '/';\n window.location.replace(redirectTo);\n }\n });\n }\n return response.text().then(function onError(responseText) {\n var message;\n try {\n var parsedResponse = JSON.parse(responseText);\n message = parsedResponse.message;\n } catch (e) {\n console.warn(\n `Failed to parse error response for ${url}:`,\n responseText\n );\n\n message = responseText;\n }\n var errorMessage = document.createTextNode(message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n })\n .catch(function onNetworkError(error) {\n var errorMessage = document.createTextNode(error.message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n }\n });\n </script>\n </body>\n</html>\n",
|
|
102
92
|
"logoutPage": "<html>\n <head>\n <title>Logout (development only)</title>\n <script>\n window.localStorage.removeItem('isAuthenticated');\n window.localStorage.removeItem('loginStrategy');\n window.localStorage.removeItem('activeProjectKey');\n </script>\n </head>\n <body>\n <div>\n <h3>This is the logout page for local development.</h3>\n <p>\n Be aware that you might still have an active session as the cookie is\n assigned to a production domain (e.g. commercetools.com) which we can't\n unset from localhost. This is only a problem on local development and we\n intend fix this in the future.\n </p>\n <p>\n You can\n <a href=\"#\" onclick=\"window.location='/login'+window.location.search;\"\n >go to the login page</a\n >\n now.\n </p>\n </div>\n </body>\n</html>\n"
|
|
103
93
|
};
|
|
104
|
-
|
|
105
94
|
// https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros
|
|
106
|
-
const trimTrailingSlash = value => value.replace(/\/$/, ''); // Make sure any symlinks in the project folder are resolved:
|
|
107
|
-
// https://github.com/facebook/create-react-app/issues/637
|
|
108
95
|
|
|
96
|
+
const trimTrailingSlash = value => value.replace(/\/$/, '');
|
|
109
97
|
|
|
98
|
+
// Make sure any symlinks in the project folder are resolved:
|
|
99
|
+
// https://github.com/facebook/create-react-app/issues/637
|
|
110
100
|
const appDirectory = fs__default["default"].realpathSync(process.cwd());
|
|
111
|
-
|
|
112
101
|
const resolveApp = relativePath => path__default["default"].resolve(appDirectory, relativePath);
|
|
113
|
-
|
|
114
102
|
const paths = {
|
|
115
103
|
appBuild: resolveApp('public')
|
|
116
|
-
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// This transformer will generate a development `login` and `logout` HTML files
|
|
117
107
|
// and copy them to the application public folder.
|
|
118
108
|
// This is necessary to run the application locally in production mode.
|
|
119
|
-
|
|
120
109
|
const transformerLocal = compiledHtml => {
|
|
121
110
|
const htmlLogin = pages.loginPage.replace(new RegExp('__MC_API_URL__', 'g'), trimTrailingSlash(compiledHtml.env.mcApiUrl));
|
|
122
111
|
const htmlLogout = pages.logoutPage;
|
|
@@ -6,13 +6,14 @@ import path from 'path';
|
|
|
6
6
|
|
|
7
7
|
function logoutRoute(response) {
|
|
8
8
|
var _context;
|
|
9
|
-
|
|
10
9
|
let additionalCookieParameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
11
10
|
// NOTE: removing the cookie only works if your are running the MC API
|
|
12
11
|
// locally, otherwise the cookie won't get removed as it's set to a
|
|
13
12
|
// proper domain (e.g. commercetools.com), which we can't unset from localhost.
|
|
14
|
-
response.setHeader('Set-Cookie', _concatInstanceProperty(_context = ["mcAccessToken=''",
|
|
15
|
-
|
|
13
|
+
response.setHeader('Set-Cookie', _concatInstanceProperty(_context = ["mcAccessToken=''",
|
|
14
|
+
// <-- unset the value
|
|
15
|
+
'Path=/', "Expires=".concat(new Date(0).toUTCString()),
|
|
16
|
+
// <-- put a date in the past
|
|
16
17
|
'HttpOnly']).call(_context, additionalCookieParameters).join('; '));
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -20,17 +21,15 @@ const pages$1 = {
|
|
|
20
21
|
"loginPage": "<html>\n <head>\n <title>Login (development only)</title>\n <style>\n html,\n body {\n font: 1em sans-serif;\n padding: 0;\n margin: 0;\n height: 100vh;\n width: 100vw;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n margin-top: 32px;\n }\n\n body > * + * {\n margin-top: 32px;\n }\n\n .title {\n width: 355px;\n }\n\n form {\n display: flex;\n flex-direction: column;\n width: 355px;\n }\n\n form > * + * {\n margin: 16px 0 0;\n }\n\n .field {\n border: 0;\n }\n\n .field > * + * {\n margin: 8px 0 0;\n }\n\n label {\n display: block;\n }\n\n input {\n width: 100%;\n height: 24px;\n outline: none;\n }\n\n input:focus {\n border: 1px solid cornflowerblue;\n }\n\n input:focus:invalid {\n border-color: red;\n }\n\n abbr {\n text-decoration: none;\n color: orangered;\n }\n\n #errors > div {\n background-color: red;\n color: #eee;\n padding: 8px;\n border-radius: 4px;\n }\n\n .info {\n background-color: #b5e1fd;\n padding: 8px;\n border-radius: 4px;\n }\n </style>\n </head>\n <body>\n <div class=\"title\">\n <h3>\n Welcome to the Merchant Center authorization page for local development\n </h3>\n <small>\n This page is only available in development mode and is necessary to\n authenticate yourself. In production environment, we use our own\n authentication service.\n </small>\n </div>\n <form id=\"login\">\n <div id=\"errors\"></div>\n <div class=\"field\">\n <label for=\"email\">\n Email<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input id=\"email\" name=\"email\" type=\"text\" required=\"required\" />\n </div>\n <div class=\"field\">\n <label for=\"password\">\n Password<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required=\"required\"\n />\n </div>\n <div>\n <button type=\"submit\" aria-label=\"Sign in\">Sign in 🚀</button>\n </div>\n </form>\n <script>\n /* eslint-disable no-var,vars-on-top */\n /**\n * NOTE:\n * This code is only used in development mode.\n * It authenticates a developer using the same mechanisms\n * as when not running in development. However,\n * this runs on the same domain as the developer.\n */\n window.addEventListener('load', function loaded() {\n var form = document.getElementById('login');\n form.addEventListener('submit', function onSubmit(event) {\n event.preventDefault();\n authorize();\n });\n\n function authorize() {\n var data = new FormData(form);\n var payload = {\n email: data.get('email'),\n password: data.get('password'),\n };\n\n var queryParams = new URLSearchParams(window.location.search);\n if (queryParams.has('response_type')) {\n // OIDC params\n payload.client_id = queryParams.get('client_id');\n payload.response_type = queryParams.get('response_type');\n payload.scope = queryParams.get('scope');\n payload.state = queryParams.get('state');\n payload.nonce = queryParams.get('nonce');\n }\n\n var container = document.getElementById('errors');\n // Clean up error message elements\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const url = '__MC_API_URL__/tokens';\n\n window\n .fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(payload),\n })\n .then(function handleResponse(response) {\n if (response.ok) {\n return response.json().then(function onSuccess(result) {\n // Handle OIDC redirect.\n if (queryParams.has('response_type')) {\n window.location.replace(result.redirectTo);\n } else {\n window.localStorage.setItem('isAuthenticated', true);\n var searchParams = new URLSearchParams(\n window.location.search\n );\n var redirectTo = searchParams.get('redirectTo') || '/';\n window.location.replace(redirectTo);\n }\n });\n }\n return response.text().then(function onError(responseText) {\n var message;\n try {\n var parsedResponse = JSON.parse(responseText);\n message = parsedResponse.message;\n } catch (e) {\n console.warn(\n `Failed to parse error response for ${url}:`,\n responseText\n );\n\n message = responseText;\n }\n var errorMessage = document.createTextNode(message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n })\n .catch(function onNetworkError(error) {\n var errorMessage = document.createTextNode(error.message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n }\n });\n </script>\n </body>\n</html>\n",
|
|
21
22
|
"logoutPage": "<html>\n <head>\n <title>Logout (development only)</title>\n <script>\n window.localStorage.removeItem('isAuthenticated');\n window.localStorage.removeItem('loginStrategy');\n window.localStorage.removeItem('activeProjectKey');\n </script>\n </head>\n <body>\n <div>\n <h3>This is the logout page for local development.</h3>\n <p>\n Be aware that you might still have an active session as the cookie is\n assigned to a production domain (e.g. commercetools.com) which we can't\n unset from localhost. This is only a problem on local development and we\n intend fix this in the future.\n </p>\n <p>\n You can\n <a href=\"#\" onclick=\"window.location='/login'+window.location.search;\"\n >go to the login page</a\n >\n now.\n </p>\n </div>\n </body>\n</html>\n"
|
|
22
23
|
};
|
|
23
|
-
|
|
24
24
|
// https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros
|
|
25
|
-
const trimTrailingSlash$1 = value => value.replace(/\/$/, '');
|
|
26
25
|
|
|
26
|
+
const trimTrailingSlash$1 = value => value.replace(/\/$/, '');
|
|
27
27
|
function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
28
28
|
const htmlLogin = pages$1.loginPage.replace(new RegExp('__MC_API_URL__', 'g'), trimTrailingSlash$1(applicationConfig.env.mcApiUrl));
|
|
29
29
|
const htmlLogout = pages$1.logoutPage;
|
|
30
30
|
const isDevAuthenticationMiddlewareDisabled = String(applicationConfig.env.disableAuthRoutesOfDevServer) === 'true' || applicationConfig.env.servedByProxy;
|
|
31
31
|
return (request, response, next) => {
|
|
32
32
|
var _applicationConfig$en, _applicationConfig$en2;
|
|
33
|
-
|
|
34
33
|
if (request.originalUrl === '/api/graphql') {
|
|
35
34
|
response.statusCode = 404;
|
|
36
35
|
response.setHeader('Content-Type', 'application/json');
|
|
@@ -39,21 +38,17 @@ function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
|
39
38
|
}));
|
|
40
39
|
return;
|
|
41
40
|
}
|
|
42
|
-
|
|
43
41
|
if ((_applicationConfig$en = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en !== void 0 && (_applicationConfig$en2 = _applicationConfig$en.oidc) !== null && _applicationConfig$en2 !== void 0 && _applicationConfig$en2.authorizeUrl) {
|
|
44
42
|
var _applicationConfig$en3, _applicationConfig$en4, _context;
|
|
45
|
-
|
|
46
43
|
// Handle login page for OIDC workflow when developing against a local MC API.
|
|
47
44
|
if ((_applicationConfig$en3 = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en3 !== void 0 && (_applicationConfig$en4 = _applicationConfig$en3.oidc) !== null && _applicationConfig$en4 !== void 0 && _startsWithInstanceProperty(_context = _applicationConfig$en4.authorizeUrl).call(_context, 'http://localhost')) {
|
|
48
45
|
var _context2;
|
|
49
|
-
|
|
50
46
|
if (_startsWithInstanceProperty(_context2 = request.originalUrl).call(_context2, '/login/authorize')) {
|
|
51
47
|
if (isDevAuthenticationMiddlewareDisabled) {
|
|
52
48
|
next();
|
|
53
49
|
} else {
|
|
54
50
|
response.send(htmlLogin);
|
|
55
51
|
}
|
|
56
|
-
|
|
57
52
|
return;
|
|
58
53
|
}
|
|
59
54
|
}
|
|
@@ -64,23 +59,18 @@ function createMcDevAuthenticationMiddleware(applicationConfig) {
|
|
|
64
59
|
} else {
|
|
65
60
|
response.send(htmlLogin);
|
|
66
61
|
}
|
|
67
|
-
|
|
68
62
|
return;
|
|
69
63
|
}
|
|
70
|
-
|
|
71
64
|
if (request.originalUrl === '/logout') {
|
|
72
65
|
logoutRoute(response);
|
|
73
|
-
|
|
74
66
|
if (isDevAuthenticationMiddlewareDisabled) {
|
|
75
67
|
next();
|
|
76
68
|
} else {
|
|
77
69
|
response.send(htmlLogout);
|
|
78
70
|
}
|
|
79
|
-
|
|
80
71
|
return;
|
|
81
72
|
}
|
|
82
73
|
}
|
|
83
|
-
|
|
84
74
|
next();
|
|
85
75
|
};
|
|
86
76
|
}
|
|
@@ -89,22 +79,21 @@ const pages = {
|
|
|
89
79
|
"loginPage": "<html>\n <head>\n <title>Login (development only)</title>\n <style>\n html,\n body {\n font: 1em sans-serif;\n padding: 0;\n margin: 0;\n height: 100vh;\n width: 100vw;\n }\n\n body {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n margin-top: 32px;\n }\n\n body > * + * {\n margin-top: 32px;\n }\n\n .title {\n width: 355px;\n }\n\n form {\n display: flex;\n flex-direction: column;\n width: 355px;\n }\n\n form > * + * {\n margin: 16px 0 0;\n }\n\n .field {\n border: 0;\n }\n\n .field > * + * {\n margin: 8px 0 0;\n }\n\n label {\n display: block;\n }\n\n input {\n width: 100%;\n height: 24px;\n outline: none;\n }\n\n input:focus {\n border: 1px solid cornflowerblue;\n }\n\n input:focus:invalid {\n border-color: red;\n }\n\n abbr {\n text-decoration: none;\n color: orangered;\n }\n\n #errors > div {\n background-color: red;\n color: #eee;\n padding: 8px;\n border-radius: 4px;\n }\n\n .info {\n background-color: #b5e1fd;\n padding: 8px;\n border-radius: 4px;\n }\n </style>\n </head>\n <body>\n <div class=\"title\">\n <h3>\n Welcome to the Merchant Center authorization page for local development\n </h3>\n <small>\n This page is only available in development mode and is necessary to\n authenticate yourself. In production environment, we use our own\n authentication service.\n </small>\n </div>\n <form id=\"login\">\n <div id=\"errors\"></div>\n <div class=\"field\">\n <label for=\"email\">\n Email<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input id=\"email\" name=\"email\" type=\"text\" required=\"required\" />\n </div>\n <div class=\"field\">\n <label for=\"password\">\n Password<abbr title=\"This field is mandatory\">*</abbr>\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required=\"required\"\n />\n </div>\n <div>\n <button type=\"submit\" aria-label=\"Sign in\">Sign in 🚀</button>\n </div>\n </form>\n <script>\n /* eslint-disable no-var,vars-on-top */\n /**\n * NOTE:\n * This code is only used in development mode.\n * It authenticates a developer using the same mechanisms\n * as when not running in development. However,\n * this runs on the same domain as the developer.\n */\n window.addEventListener('load', function loaded() {\n var form = document.getElementById('login');\n form.addEventListener('submit', function onSubmit(event) {\n event.preventDefault();\n authorize();\n });\n\n function authorize() {\n var data = new FormData(form);\n var payload = {\n email: data.get('email'),\n password: data.get('password'),\n };\n\n var queryParams = new URLSearchParams(window.location.search);\n if (queryParams.has('response_type')) {\n // OIDC params\n payload.client_id = queryParams.get('client_id');\n payload.response_type = queryParams.get('response_type');\n payload.scope = queryParams.get('scope');\n payload.state = queryParams.get('state');\n payload.nonce = queryParams.get('nonce');\n }\n\n var container = document.getElementById('errors');\n // Clean up error message elements\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const url = '__MC_API_URL__/tokens';\n\n window\n .fetch(url, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n credentials: 'include',\n body: JSON.stringify(payload),\n })\n .then(function handleResponse(response) {\n if (response.ok) {\n return response.json().then(function onSuccess(result) {\n // Handle OIDC redirect.\n if (queryParams.has('response_type')) {\n window.location.replace(result.redirectTo);\n } else {\n window.localStorage.setItem('isAuthenticated', true);\n var searchParams = new URLSearchParams(\n window.location.search\n );\n var redirectTo = searchParams.get('redirectTo') || '/';\n window.location.replace(redirectTo);\n }\n });\n }\n return response.text().then(function onError(responseText) {\n var message;\n try {\n var parsedResponse = JSON.parse(responseText);\n message = parsedResponse.message;\n } catch (e) {\n console.warn(\n `Failed to parse error response for ${url}:`,\n responseText\n );\n\n message = responseText;\n }\n var errorMessage = document.createTextNode(message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n })\n .catch(function onNetworkError(error) {\n var errorMessage = document.createTextNode(error.message);\n var errorContainer = document.createElement('div');\n errorContainer.appendChild(errorMessage);\n container.appendChild(errorContainer, container);\n });\n }\n });\n </script>\n </body>\n</html>\n",
|
|
90
80
|
"logoutPage": "<html>\n <head>\n <title>Logout (development only)</title>\n <script>\n window.localStorage.removeItem('isAuthenticated');\n window.localStorage.removeItem('loginStrategy');\n window.localStorage.removeItem('activeProjectKey');\n </script>\n </head>\n <body>\n <div>\n <h3>This is the logout page for local development.</h3>\n <p>\n Be aware that you might still have an active session as the cookie is\n assigned to a production domain (e.g. commercetools.com) which we can't\n unset from localhost. This is only a problem on local development and we\n intend fix this in the future.\n </p>\n <p>\n You can\n <a href=\"#\" onclick=\"window.location='/login'+window.location.search;\"\n >go to the login page</a\n >\n now.\n </p>\n </div>\n </body>\n</html>\n"
|
|
91
81
|
};
|
|
92
|
-
|
|
93
82
|
// https://babeljs.io/blog/2017/09/11/zero-config-with-babel-macros
|
|
94
|
-
const trimTrailingSlash = value => value.replace(/\/$/, ''); // Make sure any symlinks in the project folder are resolved:
|
|
95
|
-
// https://github.com/facebook/create-react-app/issues/637
|
|
96
83
|
|
|
84
|
+
const trimTrailingSlash = value => value.replace(/\/$/, '');
|
|
97
85
|
|
|
86
|
+
// Make sure any symlinks in the project folder are resolved:
|
|
87
|
+
// https://github.com/facebook/create-react-app/issues/637
|
|
98
88
|
const appDirectory = fs.realpathSync(process.cwd());
|
|
99
|
-
|
|
100
89
|
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
|
101
|
-
|
|
102
90
|
const paths = {
|
|
103
91
|
appBuild: resolveApp('public')
|
|
104
|
-
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// This transformer will generate a development `login` and `logout` HTML files
|
|
105
95
|
// and copy them to the application public folder.
|
|
106
96
|
// This is necessary to run the application locally in production mode.
|
|
107
|
-
|
|
108
97
|
const transformerLocal = compiledHtml => {
|
|
109
98
|
const htmlLogin = pages.loginPage.replace(new RegExp('__MC_API_URL__', 'g'), trimTrailingSlash(compiledHtml.env.mcApiUrl));
|
|
110
99
|
const htmlLogout = pages.logoutPage;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commercetools-frontend/mc-dev-authentication",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.3.0",
|
|
4
4
|
"description": "Authentication views when running webpack-dev-server in development mode",
|
|
5
5
|
"bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
"directory": "packages/mc-dev-authentication"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://docs.commercetools.com/custom-applications",
|
|
12
|
-
"keywords": [
|
|
12
|
+
"keywords": [
|
|
13
|
+
"javascript",
|
|
14
|
+
"frontend",
|
|
15
|
+
"react",
|
|
16
|
+
"toolkit"
|
|
17
|
+
],
|
|
13
18
|
"license": "MIT",
|
|
14
19
|
"publishConfig": {
|
|
15
20
|
"access": "public"
|
|
@@ -28,11 +33,12 @@
|
|
|
28
33
|
"@babel/runtime-corejs3": "^7.20.13"
|
|
29
34
|
},
|
|
30
35
|
"devDependencies": {
|
|
31
|
-
"@
|
|
36
|
+
"@types/express": "^4.17.17",
|
|
32
37
|
"@tsconfig/node16": "^1.0.3",
|
|
33
|
-
"express": "4.18.2"
|
|
38
|
+
"express": "4.18.2",
|
|
39
|
+
"@commercetools-frontend/application-config": "22.3.0"
|
|
34
40
|
},
|
|
35
41
|
"engines": {
|
|
36
42
|
"node": "16.x || >=18.0.0"
|
|
37
43
|
}
|
|
38
|
-
}
|
|
44
|
+
}
|