@deephaven/auth-plugins
Version:
Deephaven Auth Plugins
216 lines (215 loc) • 7.84 kB
JavaScript
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { FadeTransition, LoadingOverlay } from '@deephaven/components';
import { useClient } from '@deephaven/jsapi-bootstrap';
import { useBroadcastLoginListener } from '@deephaven/jsapi-components';
import Log from '@deephaven/log';
import { getErrorMessage } from '@deephaven/utils';
import Cookies from 'js-cookie';
import LoginForm from "./LoginForm.js";
import Login from "./Login.js";
import AuthenticationError from "./AuthenticationError.js";
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
import { Fragment as _Fragment } from "react/jsx-runtime";
var AUTH_TYPE = 'io.deephaven.authentication.psk.PskAuthenticationHandler';
var PSK_QUERY_PARAM_KEY = 'psk';
var PSK_TOKEN_KEY = 'io.deephaven.web.client.auth.psk.token';
var log = Log.module('AuthPluginPsk');
function getWindowToken() {
return new URLSearchParams(window.location.search).get(PSK_QUERY_PARAM_KEY);
}
function clearWindowToken() {
log.debug2('clearWindowToken');
var url = new URL(window.location.href);
url.searchParams.delete(PSK_QUERY_PARAM_KEY);
window.history.replaceState(null, '', url.href);
}
function readCookieToken() {
var _Cookies$get;
return (_Cookies$get = Cookies.get(PSK_TOKEN_KEY)) !== null && _Cookies$get !== void 0 ? _Cookies$get : null;
}
function storeCookieToken(token) {
log.debug2('Storing token in cookie', token);
if (token != null) {
Cookies.set(PSK_TOKEN_KEY, token, {
secure: true,
sameSite: 'strict'
});
} else {
Cookies.remove(PSK_TOKEN_KEY);
}
}
/**
* AuthPlugin that tries to login using a pre-shared key.
* Add the `psk=<token>` parameter to your URL string to set the token.
*/
function Component(_ref) {
var {
children,
logoPath
} = _ref;
var client = useClient();
var inputField = useRef(null);
var loginPromise = useRef(null);
var [error, setError] = useState();
var [isInputRequired, setIsInputRequired] = useState(false);
var [isLoggedIn, setIsLoggedIn] = useState(false);
var [isLoggingIn, setIsLoggingIn] = useState(false);
var [token, setToken] = useState('');
var login = useCallback(
/*#__PURE__*/
// eslint-disable-next-line @typescript-eslint/no-inferrable-types
function () {
var _ref2 = _asyncToGenerator(function* (loginToken) {
var showError = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
log.info('Logging in...');
setIsLoggingIn(true);
var newLoginPromise = null;
try {
newLoginPromise = client.login({
type: AUTH_TYPE,
token: loginToken
});
loginPromise.current = newLoginPromise;
yield newLoginPromise;
log.info('Logged in successfully');
if (loginPromise.current !== newLoginPromise) {
return;
}
storeCookieToken(loginToken);
setIsLoggedIn(true);
} catch (e) {
if (loginPromise.current !== newLoginPromise) {
return;
}
setIsInputRequired(true);
if (showError) {
var _getErrorMessage;
log.error('Unable to login', e);
var message = (_getErrorMessage = getErrorMessage(e)) !== null && _getErrorMessage !== void 0 ? _getErrorMessage : 'Unable to login: Verify credentials.';
setError(new AuthenticationError(message));
}
}
setIsLoggingIn(false);
});
return function (_x) {
return _ref2.apply(this, arguments);
};
}(), [client]);
var cancelLogin = useCallback(() => {
loginPromise.current = null;
setIsLoggingIn(false);
}, []);
var onLogin = useCallback( /*#__PURE__*/_asyncToGenerator(function* () {
log.debug('onLogin');
// User logged in successfully in another tab, we should be able to read the token from the cookie and login
var newToken = readCookieToken();
if (isLoggedIn || isLoggingIn || newToken == null) {
return;
}
login(newToken, false);
}), [isLoggedIn, isLoggingIn, login]);
var onLogout = useCallback(() => {
storeCookieToken(null);
}, []);
useBroadcastLoginListener(onLogin, onLogout);
useEffect(() => {
var isCanceled = false;
function initialLogin() {
return _initialLogin.apply(this, arguments);
}
function _initialLogin() {
_initialLogin = _asyncToGenerator(function* () {
var _getWindowToken;
var initialToken = (_getWindowToken = getWindowToken()) !== null && _getWindowToken !== void 0 ? _getWindowToken : readCookieToken();
clearWindowToken();
if (initialToken == null) {
setIsInputRequired(true);
return;
}
setIsLoggingIn(true);
try {
yield client.login({
type: AUTH_TYPE,
token: initialToken
});
if (!isCanceled) {
storeCookieToken(initialToken);
setIsLoggedIn(true);
setIsLoggingIn(false);
}
} catch (e) {
if (!isCanceled) {
setIsInputRequired(true);
setIsLoggingIn(false);
}
}
});
return _initialLogin.apply(this, arguments);
}
initialLogin();
return () => {
isCanceled = true;
};
}, [client]);
var handleSubmit = useCallback(() => {
if (!isLoggingIn) {
login(token);
} else {
cancelLogin();
}
}, [cancelLogin, isLoggingIn, login, token]);
useEffect(function autoFocusInput() {
var _inputField$current;
(_inputField$current = inputField.current) === null || _inputField$current === void 0 ? void 0 : _inputField$current.focus();
}, [inputField, isInputRequired]);
return /*#__PURE__*/_jsxs(_Fragment, {
children: [isLoggedIn && children, isInputRequired && /*#__PURE__*/_jsx(FadeTransition, {
in: !isLoggedIn,
mountOnEnter: true,
unmountOnExit: true,
children: /*#__PURE__*/_jsx(Login, {
logoPath: logoPath,
children: /*#__PURE__*/_jsx(LoginForm, {
errorMessage: getErrorMessage(error),
isLoggingIn: isLoggingIn,
onSubmit: handleSubmit,
children: /*#__PURE__*/_jsxs("div", {
className: "form-group",
children: [/*#__PURE__*/_jsx("label", {
htmlFor: "auth-psk-token-input",
children: "Token"
}), /*#__PURE__*/_jsx("input", {
id: "auth-psk-token-input",
name: "token",
className: "input-token form-control",
type: "text",
autoComplete: "username",
autoCapitalize: "none",
autoCorrect: "off",
spellCheck: "false",
ref: inputField,
value: token,
onChange: event => {
setError(undefined);
setToken(event.target.value);
}
})]
})
})
})
}), /*#__PURE__*/_jsx(LoadingOverlay, {
"data-testid": "auth-psk-loading",
isLoaded: isLoggedIn || isInputRequired,
isLoading: !isLoggedIn && !isInputRequired
})]
});
}
var AuthPluginPsk = {
Component,
isAvailable: authHandlers => authHandlers.includes(AUTH_TYPE)
};
export default AuthPluginPsk;
//# sourceMappingURL=AuthPluginPsk.js.map