Skip to content

Commit f0528ae

Browse files
author
Brijesh
committed
Login process improvements
1 parent d81fbdc commit f0528ae

8 files changed

Lines changed: 141 additions & 71 deletions

File tree

src/actionCreators/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ export const resetTimeoutForReAuth = (reauthenticate) => (dispatch, getState) =>
8686
export const signOut = () => (dispatch) => {
8787
// clear the local storage in the browser
8888
localStorage.clear();
89-
document.cookie =
90-
'SMSESSION=; path=/; domain=.gov.bc.ca; expires=Thu, 01 Jan 1970 00:00:00 UTC; Secure; SameSite=None';
9189
dispatch(actions.removeAuthDataAndUser());
9290
};
9391

src/components/ReturnPage.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
33
import { parseQuery, getTokenFromSSO, saveAuthDataInLocal, getDataFromLocalStorage } from '../utils';
4-
import { SSO_LOGOUT_ENDPOINT } from '../constants/api';
54
import { REDIRECTING } from '../constants/strings';
65
import { LOCAL_STORAGE_KEY, RETURN_PAGE_TYPE } from '../constants/variables';
6+
import { SSO_LOGOUT_ENDPOINT } from '../constants/api';
77

88
class ReturnPage extends Component {
99
static propTypes = {
@@ -18,8 +18,8 @@ class ReturnPage extends Component {
1818
switch (type) {
1919
case RETURN_PAGE_TYPE.LOGIN:
2020
if (code) {
21-
const { codeVerifier, codeVerifierHash } = getDataFromLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE);
22-
if (!codeVerifier || !codeVerifierHash) {
21+
const pkce = getDataFromLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE);
22+
if (!pkce?.codeVerifier || !pkce?.codeVerifierHash) {
2323
// we cannot proceed without the pkce challenge code
2424
window.close();
2525
} else {

src/components/loginPage/SignInButtons.js

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,60 @@
11
import React, { Component, Fragment } from 'react';
22
import { PrimaryButton } from '../common';
33
import { ELEMENT_ID, LOCAL_STORAGE_KEY } from '../../constants/variables';
4-
import { SSO_LOGIN_ENDPOINT, SSO_BCEID_LOGIN_ENDPOINT } from '../../constants/api';
5-
import { saveDataInLocalStorage } from '../../utils';
6-
import { encode as base64encode } from 'base64-arraybuffer';
4+
import { SSO_BCEID_LOGIN_ENDPOINT, SSO_IDIR_LOGIN_ENDPOINT } from '../../constants/api';
5+
import { getDataFromLocalStorage, saveDataInLocalStorage } from '../../utils';
6+
import { generatePKCE } from '../../utils/pkceUtils';
77

88
class SignInButtons extends Component {
99
openNewTab = (link) => window.open(link, '_blank');
10-
onSigninBtnClick = () => {
11-
this.openNewTab(SSO_LOGIN_ENDPOINT.replace('_CODE_CHALLENGE_VALUE_', this.state.codeVerifierHash));
12-
};
13-
onBceidSigninBtnClick = () => {
14-
this.openNewTab(SSO_BCEID_LOGIN_ENDPOINT.replace('_CODE_CHALLENGE_VALUE_', this.state.codeVerifierHash));
15-
};
16-
17-
constructor() {
18-
super();
19-
this.state = {
20-
codeVerifier: null,
21-
codeVerifierHash: null,
22-
hashComputed: false,
23-
};
24-
}
2510

26-
componentDidMount() {
27-
// generate and save new ones, and update the state
28-
let codeVerifier = '';
29-
30-
const VALID_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
31-
for (let i = 0; i < 128; i++) {
32-
codeVerifier += VALID_CHARS.charAt(Math.floor(Math.random() * VALID_CHARS.length));
11+
onSignInButtonClick = () => {
12+
let loginEndpoint = SSO_BCEID_LOGIN_ENDPOINT.replace(
13+
'_CODE_CHALLENGE_VALUE_',
14+
getDataFromLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE).codeVerifierHash,
15+
);
16+
if (getDataFromLocalStorage(LOCAL_STORAGE_KEY.USER)?.ssoId?.startsWith('idir')) {
17+
loginEndpoint = SSO_IDIR_LOGIN_ENDPOINT.replace(
18+
'_CODE_CHALLENGE_VALUE_',
19+
getDataFromLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE).codeVerifierHash,
20+
);
3321
}
22+
this.openNewTab(loginEndpoint);
23+
};
3424

35-
const encoder = new TextEncoder();
36-
const data = encoder.encode(codeVerifier);
37-
crypto.subtle.digest('SHA-256', data).then((hash) => {
38-
// hash complete
39-
40-
const encodedHash = base64encode(hash).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
41-
42-
this.setState({
43-
...this.state,
44-
codeVerifier: codeVerifier,
45-
codeVerifierHash: encodedHash,
46-
hashComputed: true,
47-
});
48-
25+
componentDidMount() {
26+
generatePKCE().then((pkce) => {
4927
saveDataInLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE, {
50-
codeVerifier: codeVerifier,
51-
codeVerifierHash: encodedHash,
28+
codeVerifier: pkce.codeVerifier,
29+
codeVerifierHash: pkce.codeVerifierHash,
5230
});
5331
});
5432
}
5533

5634
render() {
57-
if (!this.state.hashComputed) {
58-
return <Fragment>...</Fragment>;
35+
if (getDataFromLocalStorage(LOCAL_STORAGE_KEY.USER)?.ssoId?.startsWith('idir')) {
36+
return (
37+
<Fragment>
38+
<PrimaryButton
39+
id={ELEMENT_ID.LOGIN_IDIR_BUTTON}
40+
className="signin__button"
41+
fluid
42+
style={{ height: '45px', marginTop: '15px', marginRight: '0' }}
43+
onClick={this.onSignInButtonClick}
44+
content="Login using IDIR"
45+
/>
46+
</Fragment>
47+
);
5948
}
60-
6149
return (
6250
<Fragment>
6351
<PrimaryButton
6452
id={ELEMENT_ID.LOGIN_BCEID_BUTTON}
6553
className="signin__button"
6654
fluid
6755
style={{ height: '45px', marginTop: '15px', marginRight: '0' }}
68-
onClick={this.onBceidSigninBtnClick}
69-
content="Login"
56+
onClick={this.onSignInButtonClick}
57+
content="Login using BCeID"
7058
/>
7159
</Fragment>
7260
);

src/components/loginPage/index.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import { connect } from 'react-redux';
44
import { Icon } from 'semantic-ui-react';
55
import { IMAGE_SRC, LOCAL_STORAGE_KEY } from '../../constants/variables';
66
import { LOGIN_TITLE, APP_NAME } from '../../constants/strings';
7-
import { detectIE, isTokenExpired, getDataFromLocalStorage } from '../../utils';
7+
import { detectIE, isTokenExpired, getDataFromLocalStorage, saveDataInLocalStorage } from '../../utils';
88
import { fetchUser } from '../../actionCreators';
99
import { Footer, PrimaryButton } from '../common';
1010
import SignInBox from './SignInBox';
1111
import BrowserWarningHeader from './BrowserWarningHeader';
12+
import { SSO_IDIR_LOGIN_ENDPOINT } from '../../constants/api';
13+
import { generatePKCE } from '../../utils/pkceUtils';
1214

1315
export class LoginPage extends Component {
1416
static propTypes = {
@@ -26,8 +28,24 @@ export class LoginPage extends Component {
2628
// try to fetch the user from the server
2729
this.props.fetchUser();
2830
}
31+
generatePKCE().then((pkce) => {
32+
saveDataInLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE, {
33+
codeVerifier: pkce.codeVerifier,
34+
codeVerifierHash: pkce.codeVerifierHash,
35+
});
36+
});
2937
}
3038

39+
staffLoginBtnClicked = () => {
40+
window.open(
41+
SSO_IDIR_LOGIN_ENDPOINT.replace(
42+
'_CODE_CHALLENGE_VALUE_',
43+
getDataFromLocalStorage(LOCAL_STORAGE_KEY.AUTH_PKCE_CODE).codeVerifierHash,
44+
),
45+
'_blank',
46+
);
47+
};
48+
3149
registerBtnClicked = () => {
3250
window.open('https://www.bceid.ca/register/', '_blank');
3351
};
@@ -42,7 +60,19 @@ export class LoginPage extends Component {
4260
<article className="login__header">
4361
<div className="container">
4462
<div className="login__header__content">
45-
<img className="login__header__logo" src={IMAGE_SRC.MYRANGEBC_LOGO} alt="Logo" />
63+
<img
64+
className="login__header__logo"
65+
style={{ textAlign: 'center' }}
66+
src={IMAGE_SRC.MYRANGEBC_LOGO}
67+
alt="Logo"
68+
/>
69+
<div className="login__header__button__container">
70+
<PrimaryButton
71+
className="login__header__signin__button"
72+
content="Staff Login"
73+
onClick={this.staffLoginBtnClicked}
74+
/>
75+
</div>
4676
</div>
4777
</div>
4878
</article>

src/constants/api.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const DEV_API_BASE_URL = process.env.REACT_APP_API_URL || 'https://myrangebc-dev
2424
const DEV = {
2525
// eslint-disable-line no-unused-vars
2626
SSO_BASE_URL: 'https://dev.loginproxy.gov.bc.ca',
27-
SITEMINDER_BASE_URL: 'https://logontest.gov.bc.ca',
27+
SITEMINDER_BASE_URL: 'https://logontest7.gov.bc.ca',
2828
API_BASE_URL: DEV_API_BASE_URL,
2929
};
3030

@@ -42,15 +42,21 @@ export const SSO_BASE_AUTH_ENDPOINT = `${SSO_BASE_URL}/auth/realms/${SSO_REALM_N
4242
export const SSO_LOGIN_REDIRECT_URI = `${window.location.origin}/return-page?type=${RETURN_PAGE_TYPE.LOGIN}`;
4343
export const SSO_LOGIN_ENDPOINT = `${SSO_BASE_AUTH_ENDPOINT}/auth?response_type=code&client_id=${SSO_CLIENT_ID}&redirect_uri=${SSO_LOGIN_REDIRECT_URI}&code_challenge_method=S256&code_challenge=_CODE_CHALLENGE_VALUE_`;
4444
export const SSO_IDIR_LOGIN_ENDPOINT = `${SSO_LOGIN_ENDPOINT}&kc_idp_hint=idir`;
45-
export const SSO_BCEID_LOGIN_ENDPOINT = `${SSO_LOGIN_ENDPOINT}&kc_idp_hint=bceid`;
45+
export const SSO_BCEID_LOGIN_ENDPOINT = `${SSO_LOGIN_ENDPOINT}&kc_idp_hint=bceidboth`;
4646

4747
export const SSO_LOGOUT_REDIRECT_URI = `${window.location.origin}/return-page?type=${RETURN_PAGE_TYPE.LOGOUT}`;
48-
export const SSO_LOGOUT_ENDPOINT = `${SSO_BASE_AUTH_ENDPOINT}/logout?redirect_uri=${SSO_LOGOUT_REDIRECT_URI}`;
48+
export const SSO_LOGOUT_ENDPOINT =
49+
`${SSO_BASE_AUTH_ENDPOINT}/logout?post_logout_redirect_uri=` +
50+
encodeURIComponent(SSO_LOGOUT_REDIRECT_URI) +
51+
`&client_id=${SSO_CLIENT_ID}`;
4952

5053
export const SITEMINDER_BASE_URL = isBundled ? '{{env "SITEMINDER_BASE_URL"}}' : DEV_ENV.SITEMINDER_BASE_URL;
5154

5255
export const SITEMINDER_LOGOUT_REDIRECT_URI = `${window.location.origin}/return-page?type=${RETURN_PAGE_TYPE.SITEMINDER_LOGOUT}`;
53-
export const SITEMINDER_LOGOUT_ENDPOINT = `${SITEMINDER_BASE_URL}/clp-cgi/logoff.cgi?returl=${SITEMINDER_LOGOUT_REDIRECT_URI}&retnow=1`;
56+
export const SITEMINDER_LOGOUT_ENDPOINT =
57+
`${SITEMINDER_BASE_URL}/clp-cgi/logoff.cgi?returl=` +
58+
encodeURIComponent(SITEMINDER_LOGOUT_REDIRECT_URI) +
59+
`&retnow=1`;
5460

5561
export const GET_TOKEN_FROM_SSO = `/auth/realms/${SSO_REALM_NAME}/protocol/openid-connect/token`;
5662
export const REFRESH_TOKEN_FROM_SSO = `/auth/realms/${SSO_REALM_NAME}/protocol/openid-connect/token`;

0 commit comments

Comments
 (0)