@hmcts/opal-frontend-common-node 0.0.2 → 0.0.3
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/app-insights/app-insights-configuration.d.ts +5 -0
- package/app-insights/app-insights-configuration.d.ts.map +1 -0
- package/app-insights/app-insights-configuration.js +15 -0
- package/app-insights/app-insights-configuration.js.map +1 -0
- package/app-insights/index.d.ts +5 -0
- package/app-insights/index.d.ts.map +1 -0
- package/app-insights/index.js +34 -0
- package/app-insights/index.js.map +1 -0
- package/csrf-token/index.d.ts +5 -0
- package/csrf-token/index.d.ts.map +1 -0
- package/csrf-token/index.js +33 -0
- package/csrf-token/index.js.map +1 -0
- package/health/index.d.ts +8 -0
- package/health/index.d.ts.map +1 -0
- package/health/index.js +30 -0
- package/health/index.js.map +1 -0
- package/helmet/index.d.ts +10 -0
- package/helmet/index.d.ts.map +1 -0
- package/helmet/index.js +54 -0
- package/helmet/index.js.map +1 -0
- package/index.d.ts +9 -0
- package/index.d.ts.map +1 -0
- package/{src/index.ts → index.js} +1 -1
- package/index.js.map +1 -0
- package/interfaces/app-insights-config.d.ts +7 -0
- package/interfaces/app-insights-config.d.ts.map +1 -0
- package/interfaces/app-insights-config.js +7 -0
- package/interfaces/app-insights-config.js.map +1 -0
- package/interfaces/index.d.ts +12 -0
- package/interfaces/index.d.ts.map +1 -0
- package/{src/interfaces/index.ts → interfaces/index.js} +2 -13
- package/interfaces/index.js.map +1 -0
- package/interfaces/launch-darkly-config.d.ts +7 -0
- package/interfaces/launch-darkly-config.d.ts.map +1 -0
- package/interfaces/launch-darkly-config.js +7 -0
- package/interfaces/launch-darkly-config.js.map +1 -0
- package/interfaces/routes-config.d.ts +8 -0
- package/interfaces/routes-config.d.ts.map +1 -0
- package/interfaces/routes-config.js +8 -0
- package/interfaces/routes-config.js.map +1 -0
- package/interfaces/securityToken.d.ts +7 -0
- package/interfaces/securityToken.d.ts.map +1 -0
- package/interfaces/securityToken.js +6 -0
- package/interfaces/securityToken.js.map +1 -0
- package/interfaces/session-config.d.ts +6 -0
- package/interfaces/session-config.d.ts.map +1 -0
- package/interfaces/session-config.js +6 -0
- package/interfaces/session-config.js.map +1 -0
- package/interfaces/session-expiry-config.d.ts +7 -0
- package/interfaces/session-expiry-config.d.ts.map +1 -0
- package/interfaces/session-expiry-config.js +7 -0
- package/interfaces/session-expiry-config.js.map +1 -0
- package/interfaces/session-storage-config.d.ts +12 -0
- package/interfaces/session-storage-config.d.ts.map +1 -0
- package/interfaces/session-storage-config.js +12 -0
- package/interfaces/session-storage-config.js.map +1 -0
- package/interfaces/sso-config.d.ts +9 -0
- package/interfaces/sso-config.d.ts.map +1 -0
- package/interfaces/sso-config.js +9 -0
- package/interfaces/sso-config.js.map +1 -0
- package/interfaces/transfer-server-state.d.ts +9 -0
- package/interfaces/transfer-server-state.d.ts.map +1 -0
- package/interfaces/transfer-server-state.js +7 -0
- package/interfaces/transfer-server-state.js.map +1 -0
- package/interfaces/userState.d.ts +16 -0
- package/interfaces/userState.d.ts.map +1 -0
- package/interfaces/userState.js +16 -0
- package/interfaces/userState.js.map +1 -0
- package/launch-darkly/index.d.ts +5 -0
- package/launch-darkly/index.d.ts.map +1 -0
- package/launch-darkly/index.js +14 -0
- package/launch-darkly/index.js.map +1 -0
- package/package.json +1 -1
- package/properties-volume/index.d.ts +6 -0
- package/properties-volume/index.d.ts.map +1 -0
- package/properties-volume/index.js +10 -0
- package/properties-volume/index.js.map +1 -0
- package/proxy/index.d.ts +2 -0
- package/proxy/index.d.ts.map +1 -0
- package/{src/proxy/index.ts → proxy/index.js} +1 -0
- package/proxy/index.js.map +1 -0
- package/proxy/opal-api-proxy/index.d.ts +3 -0
- package/proxy/opal-api-proxy/index.d.ts.map +1 -0
- package/proxy/opal-api-proxy/index.js +18 -0
- package/proxy/opal-api-proxy/index.js.map +1 -0
- package/routes/index.d.ts +10 -0
- package/routes/index.d.ts.map +1 -0
- package/routes/index.js +36 -0
- package/routes/index.js.map +1 -0
- package/session/index.d.ts +5 -0
- package/session/index.d.ts.map +1 -0
- package/{src/session/index.ts → session/index.js} +1 -1
- package/session/index.js.map +1 -0
- package/session/session-expiry/index.d.ts +4 -0
- package/session/session-expiry/index.d.ts.map +1 -0
- package/session/session-expiry/index.js +23 -0
- package/session/session-expiry/index.js.map +1 -0
- package/session/session-storage/index.d.ts +7 -0
- package/session/session-storage/index.d.ts.map +1 -0
- package/session/session-storage/index.js +58 -0
- package/session/session-storage/index.js.map +1 -0
- package/session/session-user-state/index.d.ts +4 -0
- package/session/session-user-state/index.d.ts.map +1 -0
- package/session/session-user-state/index.js +20 -0
- package/session/session-user-state/index.js.map +1 -0
- package/sso/index.d.ts +7 -0
- package/sso/index.d.ts.map +1 -0
- package/{src/sso/index.ts → sso/index.js} +1 -1
- package/sso/index.js.map +1 -0
- package/sso/sso-authenticated.d.ts +4 -0
- package/sso/sso-authenticated.d.ts.map +1 -0
- package/sso/sso-authenticated.js +14 -0
- package/sso/sso-authenticated.js.map +1 -0
- package/sso/sso-login-callback.d.ts +4 -0
- package/sso/sso-login-callback.d.ts.map +1 -0
- package/sso/sso-login-callback.js +26 -0
- package/sso/sso-login-callback.js.map +1 -0
- package/sso/sso-login.d.ts +4 -0
- package/sso/sso-login.d.ts.map +1 -0
- package/sso/sso-login.js +24 -0
- package/sso/sso-login.js.map +1 -0
- package/sso/sso-logout-callback.d.ts +4 -0
- package/sso/sso-logout-callback.d.ts.map +1 -0
- package/sso/sso-logout-callback.js +13 -0
- package/sso/sso-logout-callback.js.map +1 -0
- package/sso/sso-logout.d.ts +4 -0
- package/sso/sso-logout.d.ts.map +1 -0
- package/sso/sso-logout.js +31 -0
- package/sso/sso-logout.js.map +1 -0
- package/stubs/sso/index.d.ts +7 -0
- package/stubs/sso/index.d.ts.map +1 -0
- package/{src/stubs/sso/index.ts → stubs/sso/index.js} +1 -1
- package/stubs/sso/index.js.map +1 -0
- package/stubs/sso/sso-authenticated.stub.d.ts +4 -0
- package/stubs/sso/sso-authenticated.stub.d.ts.map +1 -0
- package/stubs/sso/sso-authenticated.stub.js +14 -0
- package/stubs/sso/sso-authenticated.stub.js.map +1 -0
- package/stubs/sso/sso-login-callback.stub.d.ts +4 -0
- package/stubs/sso/sso-login-callback.stub.d.ts.map +1 -0
- package/stubs/sso/sso-login-callback.stub.js +26 -0
- package/stubs/sso/sso-login-callback.stub.js.map +1 -0
- package/stubs/sso/sso-login.stub.d.ts +4 -0
- package/stubs/sso/sso-login.stub.d.ts.map +1 -0
- package/stubs/sso/sso-login.stub.js +14 -0
- package/stubs/sso/sso-login.stub.js.map +1 -0
- package/stubs/sso/sso-logout-callback.stub.d.ts +4 -0
- package/stubs/sso/sso-logout-callback.stub.d.ts.map +1 -0
- package/stubs/sso/sso-logout-callback.stub.js +13 -0
- package/stubs/sso/sso-logout-callback.stub.js.map +1 -0
- package/stubs/sso/sso-logout.stub.d.ts +4 -0
- package/stubs/sso/sso-logout.stub.d.ts.map +1 -0
- package/stubs/sso/sso-logout.stub.js +5 -0
- package/stubs/sso/sso-logout.stub.js.map +1 -0
- package/utils/base64.d.ts +3 -0
- package/utils/base64.d.ts.map +1 -0
- package/utils/base64.js +7 -0
- package/utils/base64.js.map +1 -0
- package/utils/index.d.ts +3 -0
- package/utils/index.d.ts.map +1 -0
- package/{src/utils/index.ts → utils/index.js} +1 -1
- package/utils/index.js.map +1 -0
- package/utils/jwt.d.ts +5 -0
- package/utils/jwt.d.ts.map +1 -0
- package/utils/jwt.js +32 -0
- package/utils/jwt.js.map +1 -0
- package/.editorconfig +0 -16
- package/.github/renovate.json +0 -11
- package/.github/workflows/npm_build.yml +0 -67
- package/.prettierignore +0 -12
- package/.prettierrc +0 -7
- package/.vscode/settings.json +0 -6
- package/LICENSE +0 -21
- package/README.md +0 -109
- package/eslint.config.js +0 -22
- package/sonar-project.properties +0 -9
- package/src/app-insights/app-insights-configuration.ts +0 -18
- package/src/app-insights/index.ts +0 -39
- package/src/csrf-token/index.ts +0 -36
- package/src/health/index.ts +0 -32
- package/src/helmet/index.ts +0 -60
- package/src/interfaces/app-insights-config.ts +0 -7
- package/src/interfaces/launch-darkly-config.ts +0 -7
- package/src/interfaces/routes-config.ts +0 -8
- package/src/interfaces/securityToken.ts +0 -8
- package/src/interfaces/session-config.ts +0 -5
- package/src/interfaces/session-expiry-config.ts +0 -7
- package/src/interfaces/session-storage-config.ts +0 -12
- package/src/interfaces/sso-config.ts +0 -9
- package/src/interfaces/transfer-server-state.ts +0 -10
- package/src/interfaces/userState.ts +0 -18
- package/src/launch-darkly/index.ts +0 -17
- package/src/properties-volume/index.ts +0 -12
- package/src/proxy/opal-api-proxy/index.ts +0 -19
- package/src/routes/index.ts +0 -91
- package/src/session/session-expiry/index.ts +0 -31
- package/src/session/session-storage/index.ts +0 -68
- package/src/session/session-user-state/index.ts +0 -24
- package/src/sso/sso-authenticated.ts +0 -15
- package/src/sso/sso-login-callback.ts +0 -30
- package/src/sso/sso-login.ts +0 -31
- package/src/sso/sso-logout-callback.ts +0 -17
- package/src/sso/sso-logout.ts +0 -41
- package/src/stubs/sso/sso-authenticated.stub.ts +0 -16
- package/src/stubs/sso/sso-login-callback.stub.ts +0 -29
- package/src/stubs/sso/sso-login.stub.ts +0 -16
- package/src/stubs/sso/sso-logout-callback.stub.ts +0 -16
- package/src/stubs/sso/sso-logout.stub.ts +0 -6
- package/src/utils/base64.ts +0 -7
- package/src/utils/jwt.ts +0 -35
- package/tsconfig.json +0 -72
- /package/{src/global.d.ts → global.d.ts} +0 -0
- /package/{src/session.d.ts → session.d.ts} +0 -0
- /package/{src/type.d.ts → type.d.ts} +0 -0
package/src/helmet/index.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import * as express from 'express';
|
|
2
|
-
import helmet from 'helmet';
|
|
3
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
4
|
-
|
|
5
|
-
const logger = Logger.getLogger('helmet');
|
|
6
|
-
const googleAnalyticsDomain = '*.google-analytics.com';
|
|
7
|
-
const self = "'self'";
|
|
8
|
-
const dynatraceDomain = '*.dynatrace.com';
|
|
9
|
-
const LaunchDarklyDomain = '*.launchdarkly.com';
|
|
10
|
-
const azureDomain = '*.azure.com';
|
|
11
|
-
const applicationInsightsDomain = '*.applicationinsights.azure.com';
|
|
12
|
-
/**
|
|
13
|
-
* Module that enables helmet in the application
|
|
14
|
-
*/
|
|
15
|
-
export class Helmet {
|
|
16
|
-
private readonly developmentMode: boolean;
|
|
17
|
-
constructor(developmentMode: boolean) {
|
|
18
|
-
this.developmentMode = developmentMode;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public enableFor(app: express.Express, enabled: boolean): void {
|
|
22
|
-
if (enabled) {
|
|
23
|
-
logger.info('Helmet enabled');
|
|
24
|
-
// include default helmet functions
|
|
25
|
-
const scriptSrc = [
|
|
26
|
-
self,
|
|
27
|
-
googleAnalyticsDomain,
|
|
28
|
-
dynatraceDomain,
|
|
29
|
-
"'sha256-+6WnXIl4mbFTCARd8N3COQmT3bJJmo32N8q8ZSQAIcU='",
|
|
30
|
-
"'unsafe-inline'",
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
if (this.developmentMode) {
|
|
34
|
-
// Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval'
|
|
35
|
-
// is not an allowed source of script in the following Content Security Policy directive:
|
|
36
|
-
// "script-src 'self' *.google-analytics.com 'sha256-+6WnXIl4mbFTCARd8N3COQmT3bJJmo32N8q8ZSQAIcU='".
|
|
37
|
-
// seems to be related to webpack
|
|
38
|
-
scriptSrc.push("'unsafe-eval'");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
app.use(
|
|
42
|
-
helmet({
|
|
43
|
-
contentSecurityPolicy: {
|
|
44
|
-
directives: {
|
|
45
|
-
connectSrc: [self, dynatraceDomain, LaunchDarklyDomain, azureDomain, applicationInsightsDomain],
|
|
46
|
-
defaultSrc: ["'none'"],
|
|
47
|
-
fontSrc: [self, 'data:', 'https://fonts.gstatic.com'],
|
|
48
|
-
imgSrc: [self, googleAnalyticsDomain],
|
|
49
|
-
objectSrc: [self],
|
|
50
|
-
scriptSrc,
|
|
51
|
-
styleSrc: [self, "'unsafe-inline'", 'https://fonts.googleapis.com'],
|
|
52
|
-
scriptSrcAttr: ["'unsafe-inline'"],
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
referrerPolicy: { policy: 'origin' },
|
|
56
|
-
}),
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
class SessionStorageConfiguration {
|
|
2
|
-
secret!: string;
|
|
3
|
-
prefix!: string;
|
|
4
|
-
maxAge!: number;
|
|
5
|
-
sameSite!: boolean;
|
|
6
|
-
secure!: boolean;
|
|
7
|
-
domain!: string;
|
|
8
|
-
redisEnabled!: boolean;
|
|
9
|
-
redisConnectionString!: string | null;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default SessionStorageConfiguration;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import AppInsightsConfig from './app-insights-config';
|
|
2
|
-
import LaunchDarklyConfig from './launch-darkly-config';
|
|
3
|
-
|
|
4
|
-
class TransferServerState {
|
|
5
|
-
launchDarklyConfig!: LaunchDarklyConfig;
|
|
6
|
-
ssoEnabled!: boolean;
|
|
7
|
-
appInsightsConfig!: AppInsightsConfig;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default TransferServerState;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
class UserState {
|
|
2
|
-
user_id!: string;
|
|
3
|
-
user_name!: string;
|
|
4
|
-
business_unit_user?: BusinessUnitUser[];
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
class BusinessUnitUser {
|
|
8
|
-
business_user_id!: string;
|
|
9
|
-
business_unit!: string;
|
|
10
|
-
permissions?: Permissions[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class Permissions {
|
|
14
|
-
permission_id!: number;
|
|
15
|
-
permission_name!: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default UserState;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import LaunchDarklyConfig from '../interfaces/launch-darkly-config';
|
|
2
|
-
|
|
3
|
-
export class LaunchDarkly {
|
|
4
|
-
public enableFor(enabled: boolean, stream: boolean, clientId: string | null): LaunchDarklyConfig {
|
|
5
|
-
const launchDarklyConfig: LaunchDarklyConfig = {
|
|
6
|
-
enabled: enabled,
|
|
7
|
-
clientId: null,
|
|
8
|
-
stream: stream,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
if (launchDarklyConfig.enabled && clientId) {
|
|
12
|
-
launchDarklyConfig.clientId = clientId;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return launchDarklyConfig;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as propertiesVolume from '@hmcts/properties-volume';
|
|
2
|
-
import { IConfig } from 'config';
|
|
3
|
-
import { Application } from 'express';
|
|
4
|
-
|
|
5
|
-
export class PropertiesVolume {
|
|
6
|
-
enableFor(server: Application, config: IConfig): IConfig {
|
|
7
|
-
if (server.locals['ENV'] !== 'development') {
|
|
8
|
-
propertiesVolume.addTo(config);
|
|
9
|
-
}
|
|
10
|
-
return config;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
2
|
-
|
|
3
|
-
const opalApiProxy = (opalApiTarget: string) => {
|
|
4
|
-
return createProxyMiddleware({
|
|
5
|
-
target: opalApiTarget,
|
|
6
|
-
changeOrigin: true,
|
|
7
|
-
logger: console,
|
|
8
|
-
on: {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
proxyReq: (proxyReq, req: any) => {
|
|
11
|
-
if (req.session.securityToken?.access_token) {
|
|
12
|
-
proxyReq.setHeader('Authorization', `Bearer ${req.session.securityToken.access_token}`);
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default opalApiProxy;
|
package/src/routes/index.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { Application } from 'express';
|
|
2
|
-
import bodyParser from 'body-parser';
|
|
3
|
-
import type { NextFunction, Request, Response } from 'express';
|
|
4
|
-
import { ssoAuthenticated, ssoLoginCallback, ssoLogin, ssoLogout, ssoLogoutCallback } from '../sso';
|
|
5
|
-
import {
|
|
6
|
-
ssoLoginStub,
|
|
7
|
-
ssoLoginCallbackStub,
|
|
8
|
-
ssoAuthenticatedStub,
|
|
9
|
-
ssoLogoutStub,
|
|
10
|
-
ssoLogoutCallbackStub,
|
|
11
|
-
} from '../stubs/sso';
|
|
12
|
-
import sessionExpiry from '@hmcts/opal-frontend-common-node/session/session-expiry';
|
|
13
|
-
import sessionUserState from '@hmcts/opal-frontend-common-node/session/session-user-state';
|
|
14
|
-
import ExpiryConfiguration from '@hmcts/opal-frontend-common-node/interfaces/session-expiry-config';
|
|
15
|
-
import RoutesConfiguration from '@hmcts/opal-frontend-common-node/interfaces/routes-config';
|
|
16
|
-
import SsoConfiguration from '@hmcts/opal-frontend-common-node/interfaces/sso-config';
|
|
17
|
-
import SessionConfiguration from '@hmcts/opal-frontend-common-node/interfaces/session-config';
|
|
18
|
-
|
|
19
|
-
export class Routes {
|
|
20
|
-
public enableFor(
|
|
21
|
-
app: Application,
|
|
22
|
-
ssoEnabled: boolean,
|
|
23
|
-
expiryConfiguration: ExpiryConfiguration,
|
|
24
|
-
routesConfiguration: RoutesConfiguration,
|
|
25
|
-
sessionConfiguration: SessionConfiguration,
|
|
26
|
-
ssoConfiguration: SsoConfiguration,
|
|
27
|
-
): void {
|
|
28
|
-
// Declare use of body-parser AFTER the use of proxy https://github.com/villadora/express-http-proxy
|
|
29
|
-
app.use(bodyParser.json());
|
|
30
|
-
app.use(bodyParser.urlencoded({ extended: false }));
|
|
31
|
-
|
|
32
|
-
this.setupSSORoutes(
|
|
33
|
-
app,
|
|
34
|
-
ssoEnabled,
|
|
35
|
-
routesConfiguration.opalApiTarget,
|
|
36
|
-
routesConfiguration.frontendHostname,
|
|
37
|
-
routesConfiguration.prefix,
|
|
38
|
-
ssoConfiguration,
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
app.get(sessionConfiguration.userStateUrl, (req: Request, res: Response) => sessionUserState(req, res));
|
|
42
|
-
app.get(sessionConfiguration.sessionExpiryUrl, (req: Request, res: Response) =>
|
|
43
|
-
sessionExpiry(
|
|
44
|
-
req,
|
|
45
|
-
res,
|
|
46
|
-
expiryConfiguration.testMode,
|
|
47
|
-
expiryConfiguration.expiryTimeInMilliseconds,
|
|
48
|
-
expiryConfiguration.warningThresholdInMilliseconds,
|
|
49
|
-
),
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
private setupSSORoutes(
|
|
54
|
-
app: Application,
|
|
55
|
-
ssoEnabled: boolean,
|
|
56
|
-
opalApiUrl: string,
|
|
57
|
-
frontendHostname: string,
|
|
58
|
-
prefix: string,
|
|
59
|
-
ssoConfiguration: SsoConfiguration,
|
|
60
|
-
): void {
|
|
61
|
-
const login = ssoEnabled ? ssoLogin : ssoLoginStub;
|
|
62
|
-
const loginCallback = ssoEnabled ? ssoLoginCallback : ssoLoginCallbackStub;
|
|
63
|
-
const logout = ssoEnabled ? ssoLogout : ssoLogoutStub;
|
|
64
|
-
const logoutCallback = ssoEnabled ? ssoLogoutCallback : ssoLogoutCallbackStub;
|
|
65
|
-
const authenticated = ssoEnabled ? ssoAuthenticated : ssoAuthenticatedStub;
|
|
66
|
-
|
|
67
|
-
const loginCallbackType = ssoEnabled ? 'post' : 'get';
|
|
68
|
-
|
|
69
|
-
app.get(ssoConfiguration.login, (req: Request, res: Response, next: NextFunction) =>
|
|
70
|
-
login(req, res, next, opalApiUrl, frontendHostname),
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const routePath = ssoConfiguration.loginCallback;
|
|
74
|
-
const callbackHandler = (req: Request, res: Response, next: NextFunction) =>
|
|
75
|
-
loginCallback(req, res, next, opalApiUrl);
|
|
76
|
-
|
|
77
|
-
if (loginCallbackType === 'post') {
|
|
78
|
-
app.post(routePath, callbackHandler);
|
|
79
|
-
} else {
|
|
80
|
-
app.get(routePath, callbackHandler);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
app.get(ssoConfiguration.logout, (req: Request, res: Response, next: NextFunction) =>
|
|
84
|
-
logout(req, res, next, opalApiUrl, frontendHostname),
|
|
85
|
-
);
|
|
86
|
-
app.get(ssoConfiguration.logoutCallback, (req: Request, res: Response, next: NextFunction) =>
|
|
87
|
-
logoutCallback(req, res, next, prefix),
|
|
88
|
-
);
|
|
89
|
-
app.get(ssoConfiguration.authenticated, (req: Request, res: Response) => authenticated(req, res));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Request, Response } from 'express';
|
|
2
|
-
import { DateTime } from 'luxon';
|
|
3
|
-
import { Jwt } from '../../utils';
|
|
4
|
-
|
|
5
|
-
const sessionExpiry = (
|
|
6
|
-
req: Request,
|
|
7
|
-
res: Response,
|
|
8
|
-
testMode: boolean,
|
|
9
|
-
expiryTimeInMilliseconds: number,
|
|
10
|
-
warningThresholdInMilliseconds: number,
|
|
11
|
-
) => {
|
|
12
|
-
const accessToken = req.session.securityToken?.access_token;
|
|
13
|
-
if (accessToken) {
|
|
14
|
-
const payload = Jwt.parseJwt(accessToken);
|
|
15
|
-
const jwtExpiry = testMode
|
|
16
|
-
? DateTime.now().plus({ milliseconds: expiryTimeInMilliseconds }).toISO()
|
|
17
|
-
: DateTime.fromMillis(payload.exp * 1000).toISO();
|
|
18
|
-
|
|
19
|
-
res.status(200).send({
|
|
20
|
-
expiry: jwtExpiry,
|
|
21
|
-
warningThresholdInMilliseconds: warningThresholdInMilliseconds,
|
|
22
|
-
});
|
|
23
|
-
} else {
|
|
24
|
-
res.status(200).send({
|
|
25
|
-
expiry: null,
|
|
26
|
-
warningThresholdInMilliseconds: null,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export default sessionExpiry;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
2
|
-
import SessionStorageConfiguration from '@hmcts/opal-frontend-common-node/interfaces/session-storage-config';
|
|
3
|
-
import { RedisStore } from 'connect-redis';
|
|
4
|
-
import cookieParser from 'cookie-parser';
|
|
5
|
-
import { Application } from 'express';
|
|
6
|
-
import session from 'express-session';
|
|
7
|
-
import { createClient } from 'redis';
|
|
8
|
-
import FileStoreFactory from 'session-file-store';
|
|
9
|
-
|
|
10
|
-
const FileStore = FileStoreFactory(session);
|
|
11
|
-
const logger = Logger.getLogger('session-storage');
|
|
12
|
-
|
|
13
|
-
export default class SessionStorage {
|
|
14
|
-
public enableFor(app: Application, sessionStorage: SessionStorageConfiguration): void {
|
|
15
|
-
app.use(cookieParser(sessionStorage.secret));
|
|
16
|
-
app.set('trust proxy', 1);
|
|
17
|
-
|
|
18
|
-
app.use(
|
|
19
|
-
session({
|
|
20
|
-
name: sessionStorage.prefix,
|
|
21
|
-
resave: false,
|
|
22
|
-
saveUninitialized: false,
|
|
23
|
-
secret: sessionStorage.secret,
|
|
24
|
-
cookie: {
|
|
25
|
-
httpOnly: true,
|
|
26
|
-
maxAge: sessionStorage.maxAge,
|
|
27
|
-
sameSite: sessionStorage.sameSite,
|
|
28
|
-
secure: sessionStorage.secure,
|
|
29
|
-
domain: sessionStorage.domain,
|
|
30
|
-
},
|
|
31
|
-
rolling: true,
|
|
32
|
-
store: this.getStore(app, sessionStorage.redisEnabled, sessionStorage.redisConnectionString),
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
private getStore(app: Application, enabled: boolean, connectionString: string | null) {
|
|
38
|
-
if (enabled && connectionString) {
|
|
39
|
-
logger.info('Using Redis session store', connectionString);
|
|
40
|
-
const client = createClient({
|
|
41
|
-
url: connectionString,
|
|
42
|
-
socket: {
|
|
43
|
-
reconnectStrategy: function (retries) {
|
|
44
|
-
if (retries > 20) {
|
|
45
|
-
logger.log('Too many attempts to reconnect. Redis connection was terminated');
|
|
46
|
-
return new Error('Too many retries.');
|
|
47
|
-
} else {
|
|
48
|
-
return retries * 500;
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
client.on('error', (err) => {
|
|
55
|
-
logger.error('Redis Client Error', err);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
client.connect().catch(() => {
|
|
59
|
-
process.exit();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
app.locals['redisClient'] = client;
|
|
63
|
-
return new RedisStore({ client });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return new FileStore({ path: '/tmp' });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Request, Response } from 'express';
|
|
2
|
-
import { UserState } from '../../interfaces';
|
|
3
|
-
import { Jwt } from '../../utils';
|
|
4
|
-
|
|
5
|
-
const sessionUserState = (req: Request, res: Response) => {
|
|
6
|
-
const userState: UserState | undefined = req.session.securityToken?.user_state;
|
|
7
|
-
const accessToken = req.session.securityToken?.access_token;
|
|
8
|
-
const name = accessToken && userState ? Jwt.parseJwt(accessToken).name : '';
|
|
9
|
-
|
|
10
|
-
// Don't allow caching of this endpoint
|
|
11
|
-
res.set({
|
|
12
|
-
'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0',
|
|
13
|
-
Pragma: 'no-cache',
|
|
14
|
-
Expires: '0',
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
if (!userState) {
|
|
18
|
-
res.send({});
|
|
19
|
-
} else {
|
|
20
|
-
res.send({ ...userState, name });
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default sessionUserState;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Request, Response } from 'express';
|
|
2
|
-
import { Jwt } from '../utils';
|
|
3
|
-
|
|
4
|
-
export default (req: Request, res: Response) => {
|
|
5
|
-
const isJwtExpired = Jwt.isJwtExpired(req.session.securityToken?.access_token);
|
|
6
|
-
const userId = req.session.securityToken?.user_state?.user_id;
|
|
7
|
-
// Don't allow caching of this endpoint
|
|
8
|
-
res.header('Cache-Control', 'no-store, must-revalidate');
|
|
9
|
-
|
|
10
|
-
if (isJwtExpired || !userId) {
|
|
11
|
-
res.status(401).send(false);
|
|
12
|
-
} else {
|
|
13
|
-
res.status(200).send(true);
|
|
14
|
-
}
|
|
15
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
3
|
-
import axios from 'axios';
|
|
4
|
-
|
|
5
|
-
export default async (req: Request, res: Response, next: NextFunction, opalApiUrl: string) => {
|
|
6
|
-
const INTERNAL_USER_CALLBACK = `${opalApiUrl}/internal-user/handle-oauth-code`;
|
|
7
|
-
const logger = Logger.getLogger('login-callback');
|
|
8
|
-
|
|
9
|
-
try {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
-
const result = await axios.post<any>(INTERNAL_USER_CALLBACK, req.body, {
|
|
12
|
-
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const securityToken = result.data;
|
|
16
|
-
req.session.securityToken = securityToken;
|
|
17
|
-
|
|
18
|
-
req.session.save((err) => {
|
|
19
|
-
if (err) {
|
|
20
|
-
logger.error('Error saving session', err);
|
|
21
|
-
return next(err);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
res.redirect('/');
|
|
25
|
-
});
|
|
26
|
-
} catch (error) {
|
|
27
|
-
logger.error('Error on login-callback', error);
|
|
28
|
-
return next(error);
|
|
29
|
-
}
|
|
30
|
-
};
|
package/src/sso/sso-login.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
3
|
-
import axios from 'axios';
|
|
4
|
-
|
|
5
|
-
export default async (
|
|
6
|
-
req: Request,
|
|
7
|
-
res: Response,
|
|
8
|
-
next: NextFunction,
|
|
9
|
-
opalApiUrl: string,
|
|
10
|
-
frontendHostname: string,
|
|
11
|
-
) => {
|
|
12
|
-
const INTERNAL_USER_LOGIN = `${opalApiUrl}/internal-user/login-or-refresh`;
|
|
13
|
-
const logger = Logger.getLogger('login');
|
|
14
|
-
const url = `${INTERNAL_USER_LOGIN}?redirect_uri=${frontendHostname}/sso/login-callback`;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const response = await axios.get(url);
|
|
18
|
-
const redirectUrl = response.request.res.responseUrl;
|
|
19
|
-
|
|
20
|
-
if (redirectUrl) {
|
|
21
|
-
res.redirect(redirectUrl);
|
|
22
|
-
} else {
|
|
23
|
-
const error = new Error('Error trying to fetch login page');
|
|
24
|
-
logger.error('Error on login', error);
|
|
25
|
-
return next(error);
|
|
26
|
-
}
|
|
27
|
-
} catch (error) {
|
|
28
|
-
logger.error('Error on login', error);
|
|
29
|
-
return next(error);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
3
|
-
|
|
4
|
-
const logger = Logger.getLogger('logout');
|
|
5
|
-
|
|
6
|
-
export default (req: Request, res: Response, next: NextFunction, prefix: string) => {
|
|
7
|
-
req.session.destroy((err) => {
|
|
8
|
-
if (err) {
|
|
9
|
-
logger.error('Error destroying session', err);
|
|
10
|
-
return next(err);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
res.clearCookie(prefix);
|
|
14
|
-
|
|
15
|
-
res.redirect('/');
|
|
16
|
-
});
|
|
17
|
-
};
|
package/src/sso/sso-logout.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import { NextFunction, Request, Response } from 'express';
|
|
3
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
4
|
-
|
|
5
|
-
export default async (
|
|
6
|
-
req: Request,
|
|
7
|
-
res: Response,
|
|
8
|
-
next: NextFunction,
|
|
9
|
-
opalApiUrl: string,
|
|
10
|
-
frontendHostname: string,
|
|
11
|
-
) => {
|
|
12
|
-
const INTERNAL_USER_LOGOUT = `${opalApiUrl}/internal-user/logout`;
|
|
13
|
-
const logger = Logger.getLogger('login');
|
|
14
|
-
const url = `${INTERNAL_USER_LOGOUT}?redirect_uri=${frontendHostname}/sso/logout-callback`;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
let accessToken;
|
|
18
|
-
|
|
19
|
-
if (req.session.securityToken) {
|
|
20
|
-
accessToken = req.session.securityToken.access_token;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (!accessToken) {
|
|
24
|
-
return next(new Error('No access token found in session'));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const response = await axios.get(url, {
|
|
28
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const logoutRedirect = response.request.res.responseUrl;
|
|
32
|
-
if (logoutRedirect) {
|
|
33
|
-
res.redirect(logoutRedirect);
|
|
34
|
-
} else {
|
|
35
|
-
next(new Error('Error trying to fetch logout page'));
|
|
36
|
-
}
|
|
37
|
-
} catch (error) {
|
|
38
|
-
logger.error('Error logging out', error);
|
|
39
|
-
return next(error);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Request, Response } from 'express';
|
|
2
|
-
import { Jwt } from '../../utils';
|
|
3
|
-
|
|
4
|
-
export default (req: Request, res: Response) => {
|
|
5
|
-
const isJwtExpired = Jwt.isJwtExpired(req.session.securityToken?.access_token);
|
|
6
|
-
const userId = req.session.securityToken?.user_state?.user_id;
|
|
7
|
-
|
|
8
|
-
// Don't allow caching of this endpoint
|
|
9
|
-
res.header('Cache-Control', 'no-store, must-revalidate');
|
|
10
|
-
|
|
11
|
-
if (isJwtExpired || !userId) {
|
|
12
|
-
res.status(401).send(false);
|
|
13
|
-
} else {
|
|
14
|
-
res.status(200).send(true);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
3
|
-
import axios from 'axios';
|
|
4
|
-
|
|
5
|
-
export default async (req: Request, res: Response, next: NextFunction, opalApiUrl: string) => {
|
|
6
|
-
const INTERNAL_JWT = `${opalApiUrl}/testing-support/token/user`;
|
|
7
|
-
const logger = Logger.getLogger('login-callback-stub');
|
|
8
|
-
|
|
9
|
-
try {
|
|
10
|
-
const email = req.query['email'] as string;
|
|
11
|
-
const result = await axios.get(INTERNAL_JWT, {
|
|
12
|
-
headers: { 'X-User-Email': email },
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
req.session.securityToken = result.data;
|
|
16
|
-
|
|
17
|
-
req.session.save((err) => {
|
|
18
|
-
if (err) {
|
|
19
|
-
logger.error('Error saving session', err);
|
|
20
|
-
return next(err);
|
|
21
|
-
}
|
|
22
|
-
logger.info('Session saved');
|
|
23
|
-
res.redirect('/');
|
|
24
|
-
});
|
|
25
|
-
} catch (error) {
|
|
26
|
-
logger.error('Error on login-stub callback', error);
|
|
27
|
-
return next(error);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
3
|
-
|
|
4
|
-
const logger = Logger.getLogger('login-stub');
|
|
5
|
-
|
|
6
|
-
export default async (req: Request, res: Response, next: NextFunction) => {
|
|
7
|
-
const email = req.query['email'] as string;
|
|
8
|
-
|
|
9
|
-
if (email !== 'null') {
|
|
10
|
-
res.redirect(`/sso/login-callback?email=${email}`);
|
|
11
|
-
} else {
|
|
12
|
-
const error = new Error('No email provided.');
|
|
13
|
-
logger.error('Error on login-stub', error);
|
|
14
|
-
return next(error);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { Logger } from '@hmcts/nodejs-logging';
|
|
3
|
-
|
|
4
|
-
export default (req: Request, res: Response, next: NextFunction, prefix: string) => {
|
|
5
|
-
const logger = Logger.getLogger('logout-callback-stub');
|
|
6
|
-
|
|
7
|
-
req.session.destroy((err) => {
|
|
8
|
-
if (err) {
|
|
9
|
-
logger.error(`Error destroying session: ${err}`);
|
|
10
|
-
return next(err);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
res.clearCookie(prefix);
|
|
14
|
-
res.redirect('/');
|
|
15
|
-
});
|
|
16
|
-
};
|