Skip to content

Commit 74c468b

Browse files
committed
Implementing short sessions for external authentication.
1 parent e8ffae6 commit 74c468b

3 files changed

Lines changed: 29 additions & 6 deletions

File tree

src/containers/ExternalLogin/ExternalLoginBox.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import { FormattedMessage, injectIntl } from 'react-intl';
66
import Button from '../../components/widgets/TheButton';
77
import Box from '../../components/widgets/Box';
88
import Callout from '../../components/widgets/Callout';
9+
import Explanation from '../../components/widgets/Explanation';
910
import { LinkIcon, LoadingIcon, SuccessIcon } from '../../components/icons';
11+
import NiceCheckbox from '../../components/forms/NiceCheckbox';
12+
1013
import { externalLogin, externalLoginFailed, statusTypes } from '../../redux/modules/auth.js';
1114
import { statusSelector, loginErrorSelector } from '../../redux/selectors/auth.js';
1215
import { hasErrorMessage, getErrorMessage } from '../../locales/apiErrorMessages.js';
@@ -17,22 +20,27 @@ export const openPopupWindow = url =>
1720
: null;
1821

1922
class ExternalLoginBox extends Component {
20-
state = { pending: false, lastError: null };
23+
state = { pending: false, lastError: null, short: false };
2124

2225
constructor(props) {
2326
super(props);
2427
this.popupWindow = null;
2528
this.pollPopupClosed = null;
2629
}
2730

31+
setShort = () => {
32+
this.setState({ short: !this.state.short });
33+
};
34+
2835
// Handle the messages from our popup window...
2936
messageHandler = e => {
37+
const { shortSessionConfig, login } = this.props;
3038
const token = e.data; // the message should be the external JWT token
3139

3240
if (token !== null && e.source === this.popupWindow && this.popupWindow !== null) {
3341
// cancel the window and the interval
3442
this.popupWindow.postMessage('received', e.origin);
35-
this.props.login(token, this.popupWindow, error => {
43+
login(token, this.state.short && shortSessionConfig ? shortSessionConfig * 60 : null, this.popupWindow, error => {
3644
if (hasErrorMessage(error)) {
3745
this.setState({ lastError: error });
3846
}
@@ -93,6 +101,7 @@ class ExternalLoginBox extends Component {
93101
const {
94102
name,
95103
helpUrl,
104+
shortSessionConfig = null,
96105
loginStatus,
97106
loginError,
98107
intl: { formatMessage },
@@ -150,6 +159,18 @@ class ExternalLoginBox extends Component {
150159
</p>
151160
)}
152161

162+
{shortSessionConfig && shortSessionConfig > 0 && (
163+
<NiceCheckbox name="external.short" checked={this.state.short} onChange={this.setShort}>
164+
<FormattedMessage id="app.loginForm.short" defaultMessage="Short session" /> ({shortSessionConfig} min)
165+
<Explanation id="loginForm.shortSession">
166+
<FormattedMessage
167+
id="app.loginForm.short.explanation"
168+
defaultMessage="Use short session on public computers to reduce the risk of unauthorized access to your account (if you forget to log out)."
169+
/>
170+
</Explanation>
171+
</NiceCheckbox>
172+
)}
173+
153174
{!pending && (loginStatus === statusTypes.LOGIN_FAILED || this.state.lastError) && (
154175
<Callout variant="danger" className="mt-3">
155176
{loginError || this.state.lastError ? (
@@ -170,6 +191,7 @@ ExternalLoginBox.propTypes = {
170191
url: PropTypes.string.isRequired,
171192
service: PropTypes.string.isRequired,
172193
helpUrl: PropTypes.string,
194+
shortSessionConfig: PropTypes.number,
173195
loginStatus: PropTypes.string,
174196
loginError: PropTypes.object,
175197
login: PropTypes.func.isRequired,
@@ -184,8 +206,8 @@ export default connect(
184206
loginError: loginErrorSelector(state, service),
185207
}),
186208
(dispatch, { service, afterLogin = null }) => ({
187-
login: (token, popupWindow, errorHandler = null) => {
188-
const promise = dispatch(externalLogin(service, token, popupWindow));
209+
login: (token, expiration, popupWindow, errorHandler = null) => {
210+
const promise = dispatch(externalLogin(service, token, expiration, popupWindow));
189211
return (afterLogin ? promise.then(afterLogin) : promise).catch(e => errorHandler && errorHandler(e));
190212
},
191213
fail: () => dispatch(externalLoginFailed(service)),

src/pages/Login/Login.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class Login extends Component {
182182
service={EXTERNAL_AUTH_SERVICE_ID}
183183
helpUrl={EXTERNAL_AUTH_HELPDESK_URL}
184184
afterLogin={this.redirectAfterLogin}
185+
shortSessionConfig={SHORT_SESSION}
185186
/>
186187
</Col>
187188
)}

src/redux/modules/auth.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ export const validatePasswordStrength = password =>
6262
body: { password },
6363
});
6464

65-
export const externalLogin = (service, token, popupWindow = null) =>
65+
export const externalLogin = (service, token, expiration = null, popupWindow = null) =>
6666
createApiAction({
6767
type: actionTypes.LOGIN,
6868
method: 'POST',
6969
endpoint: `/login/${service}`,
70-
body: { token },
70+
body: { token, expiration },
7171
meta: { service, popupWindow },
7272
});
7373

0 commit comments

Comments
 (0)