@carisls/sso-standard 1.0.6 → 1.1.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/cjs/shared/cookies/refreshToken.cjs +1 -1
- package/cjs/shared/logout.cjs +4 -3
- package/cjs/standard/codeRequest.cjs +3 -7
- package/cjs/standard/index.cjs +9 -8
- package/cjs/standard/login.cjs +8 -4
- package/cjs/standard/refreshRequest.cjs +3 -7
- package/cjs/standard/sso.cjs +2 -2
- package/esm/shared/cookies/refreshToken.js +1 -1
- package/esm/shared/logout.js +4 -3
- package/esm/standard/codeRequest.js +3 -7
- package/esm/standard/index.js +9 -8
- package/esm/standard/login.js +8 -4
- package/esm/standard/refreshRequest.js +3 -7
- package/esm/standard/sso.js +2 -2
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { tokenDecoderModule: decodeToken } = require('@carisls/sso-core');
|
|
2
2
|
|
|
3
|
-
function refreshTokenModule (
|
|
3
|
+
function refreshTokenModule (encryptor) {
|
|
4
4
|
return async function (res, refreshToken, cookiesSecure) {
|
|
5
5
|
// Process access token if returned
|
|
6
6
|
const token = refreshToken.includes('.') ? decodeToken.data(refreshToken) : refreshToken;
|
package/cjs/shared/logout.cjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { stringify } = require('node:querystring');
|
|
2
|
+
|
|
1
3
|
function logout (router, client, encryptor, logoutPath, afterLogoutPath) {
|
|
2
4
|
router.get(logoutPath, async (req, res) => {
|
|
3
5
|
let idToken = '';
|
|
@@ -9,16 +11,15 @@ function logout (router, client, encryptor, logoutPath, afterLogoutPath) {
|
|
|
9
11
|
idToken = await encryptor.decrypt(req.cookies['x-session-id']);
|
|
10
12
|
res.cookie('x-session-id', 'Removing...', { maxAge: 0 });
|
|
11
13
|
}
|
|
12
|
-
res.redirect(client.endSessionUrl({
|
|
13
14
|
|
|
15
|
+
res.redirect(`${client.issuer.end_session_endpoint}?${stringify({
|
|
14
16
|
// redirect_uri for keycloak
|
|
15
17
|
redirect_uri: `${req.protocol}://${req.headers.host}${afterLogoutPath}`,
|
|
16
18
|
|
|
17
19
|
// id_token_hint and post_logout_redirect_uri for okta
|
|
18
20
|
id_token_hint: idToken,
|
|
19
21
|
post_logout_redirect_uri: `${req.protocol}://${req.headers.host}${afterLogoutPath}`
|
|
20
|
-
|
|
21
|
-
}));
|
|
22
|
+
})}`);
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
const { postForm } = require('@carisls/sso-core');
|
|
2
2
|
|
|
3
3
|
function codeRequest (client) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return (code, redirectUri) => postForm(url, {
|
|
9
|
-
client_id: clientId,
|
|
10
|
-
client_secret: clientSecret,
|
|
4
|
+
return (code, redirectUri) => postForm(client.issuer.token_endpoint, {
|
|
5
|
+
client_id: client.metadata.client_id,
|
|
6
|
+
client_secret: client.metadata.client_secret,
|
|
11
7
|
grant_type: 'authorization_code',
|
|
12
8
|
code,
|
|
13
9
|
redirect_uri: redirectUri
|
package/cjs/standard/index.cjs
CHANGED
|
@@ -18,19 +18,20 @@ function index (router, clientId, clientSecret, issuerSelector, encryptor, userM
|
|
|
18
18
|
cookieParserModule(router);
|
|
19
19
|
|
|
20
20
|
// Issuer Selector
|
|
21
|
-
const keycloakIssuer = issuerSelector.providers[Object.keys(issuerSelector.providers)[0]].issuer;
|
|
22
21
|
const tokenValidator = issuerSelector.providers[Object.keys(issuerSelector.providers)[0]].validator;
|
|
23
22
|
|
|
24
23
|
// Instantiate client
|
|
25
|
-
const client =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
const client = {
|
|
25
|
+
metadata: {
|
|
26
|
+
client_id: clientId,
|
|
27
|
+
client_secret: clientSecret
|
|
28
|
+
},
|
|
29
|
+
issuer: issuerSelector.providers[Object.keys(issuerSelector.providers)[0]].issuer
|
|
30
|
+
};
|
|
30
31
|
|
|
31
32
|
// Instantiate token modules
|
|
32
33
|
const accessTokenModule = accessTokenModule2(tokenValidator, encryptor, expOffset);
|
|
33
|
-
const refreshTokenModule = refreshTokenModule2(
|
|
34
|
+
const refreshTokenModule = refreshTokenModule2(encryptor);
|
|
34
35
|
const idTokenModule = idTokenModule2(encryptor); // id_token must be saved for Okta logout
|
|
35
36
|
|
|
36
37
|
const codeRequestModule = codeRequestModule2(client);
|
|
@@ -45,7 +46,7 @@ function index (router, clientId, clientSecret, issuerSelector, encryptor, userM
|
|
|
45
46
|
);
|
|
46
47
|
|
|
47
48
|
// Handle return from standard SSO
|
|
48
|
-
ssoModule(router,
|
|
49
|
+
ssoModule(router,
|
|
49
50
|
paths?.sso || '/sso',
|
|
50
51
|
codeRequestModule,
|
|
51
52
|
accessTokenModule,
|
package/cjs/standard/login.cjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { stringify } = require('node:querystring');
|
|
2
|
+
|
|
1
3
|
function login (router, client, loginPath, ssoPath, afterLoginPath, groups = true) {
|
|
2
4
|
router.get(loginPath, (req, res) => {
|
|
3
5
|
// Set redirectTo
|
|
@@ -10,11 +12,13 @@ function login (router, client, loginPath, ssoPath, afterLoginPath, groups = tru
|
|
|
10
12
|
scopes.push('groups');
|
|
11
13
|
|
|
12
14
|
// Standard flow initiates directly
|
|
13
|
-
res.redirect(client.
|
|
15
|
+
res.redirect(`${client.issuer.authorization_url}?${stringify({
|
|
16
|
+
client_id: client.metadata.client_id,
|
|
17
|
+
response_type: 'code',
|
|
18
|
+
scope: scopes.join(' '),
|
|
14
19
|
redirect_uri: `${req.protocol}://${req.headers.host}${ssoPath}`,
|
|
15
|
-
state: redirectTo ? Buffer.from(redirectTo).toString('
|
|
16
|
-
|
|
17
|
-
}));
|
|
20
|
+
state: redirectTo ? Buffer.from(redirectTo).toString('base64url') : undefined
|
|
21
|
+
})}`);
|
|
18
22
|
});
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
const { postForm } = require('@carisls/sso-core');
|
|
2
2
|
|
|
3
3
|
function refreshRequest (router, client, encryptor, accessTokenModule, refreshTokenModule, idTokenModule) {
|
|
4
|
-
const clientId = client.metadata.client_id;
|
|
5
|
-
const clientSecret = client.metadata.client_secret || undefined;
|
|
6
|
-
const url = client.issuer.token_endpoint;
|
|
7
|
-
|
|
8
4
|
router.all('*', (req, res, next) => {
|
|
9
5
|
// Check if SSO cookie is there
|
|
10
6
|
if (req.cookies['x-session']?.length > 36 || req.token || !req.cookies['x-session-sso']) {
|
|
@@ -14,9 +10,9 @@ function refreshRequest (router, client, encryptor, accessTokenModule, refreshTo
|
|
|
14
10
|
|
|
15
11
|
encryptor
|
|
16
12
|
.decrypt(req.cookies['x-session-sso'])
|
|
17
|
-
.then(token => postForm(
|
|
18
|
-
client_id:
|
|
19
|
-
client_secret:
|
|
13
|
+
.then(token => postForm(client.issuer.token_endpoint, {
|
|
14
|
+
client_id: client.metadata.client_id,
|
|
15
|
+
client_secret: client.metadata.client_secret,
|
|
20
16
|
grant_type: 'refresh_token',
|
|
21
17
|
refresh_token: token
|
|
22
18
|
}))
|
package/cjs/standard/sso.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { HttpError } = require('@carisls/sso-core');
|
|
2
2
|
|
|
3
|
-
function sso (router,
|
|
3
|
+
function sso (router, ssoPath, codeRequestModule, accessTokenModule, refreshTokenModule, idTokenModule) {
|
|
4
4
|
router.get(ssoPath, (req, res, next) => {
|
|
5
5
|
if (!req.query.code) {
|
|
6
6
|
next(new HttpError(500, req.query.error));
|
|
@@ -14,7 +14,7 @@ function sso (router, client, ssoPath, codeRequestModule, accessTokenModule, ref
|
|
|
14
14
|
idTokenModule(res, tokens.id_token, req.protocol === 'https')
|
|
15
15
|
]))
|
|
16
16
|
.then(() => {
|
|
17
|
-
res.redirect(req.query.state ? Buffer.from(req.query.state, '
|
|
17
|
+
res.redirect(req.query.state ? Buffer.from(req.query.state, 'base64url').toString('utf8') : '/');
|
|
18
18
|
})
|
|
19
19
|
.catch((err) => {
|
|
20
20
|
next(err);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tokenDecoderModule as decodeToken } from '@carisls/sso-core';
|
|
2
2
|
|
|
3
|
-
function refreshTokenModule (
|
|
3
|
+
function refreshTokenModule (encryptor) {
|
|
4
4
|
return async function (res, refreshToken, cookiesSecure) {
|
|
5
5
|
// Process access token if returned
|
|
6
6
|
const token = refreshToken.includes('.') ? decodeToken.data(refreshToken) : refreshToken;
|
package/esm/shared/logout.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stringify } from 'node:querystring';
|
|
2
|
+
|
|
1
3
|
function logout (router, client, encryptor, logoutPath, afterLogoutPath) {
|
|
2
4
|
router.get(logoutPath, async (req, res) => {
|
|
3
5
|
let idToken = '';
|
|
@@ -9,16 +11,15 @@ function logout (router, client, encryptor, logoutPath, afterLogoutPath) {
|
|
|
9
11
|
idToken = await encryptor.decrypt(req.cookies['x-session-id']);
|
|
10
12
|
res.cookie('x-session-id', 'Removing...', { maxAge: 0 });
|
|
11
13
|
}
|
|
12
|
-
res.redirect(client.endSessionUrl({
|
|
13
14
|
|
|
15
|
+
res.redirect(`${client.issuer.end_session_endpoint}?${stringify({
|
|
14
16
|
// redirect_uri for keycloak
|
|
15
17
|
redirect_uri: `${req.protocol}://${req.headers.host}${afterLogoutPath}`,
|
|
16
18
|
|
|
17
19
|
// id_token_hint and post_logout_redirect_uri for okta
|
|
18
20
|
id_token_hint: idToken,
|
|
19
21
|
post_logout_redirect_uri: `${req.protocol}://${req.headers.host}${afterLogoutPath}`
|
|
20
|
-
|
|
21
|
-
}));
|
|
22
|
+
})}`);
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { postForm } from '@carisls/sso-core';
|
|
2
2
|
|
|
3
3
|
function codeRequest (client) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return (code, redirectUri) => postForm(url, {
|
|
9
|
-
client_id: clientId,
|
|
10
|
-
client_secret: clientSecret,
|
|
4
|
+
return (code, redirectUri) => postForm(client.issuer.token_endpoint, {
|
|
5
|
+
client_id: client.metadata.client_id,
|
|
6
|
+
client_secret: client.metadata.client_secret,
|
|
11
7
|
grant_type: 'authorization_code',
|
|
12
8
|
code,
|
|
13
9
|
redirect_uri: redirectUri
|
package/esm/standard/index.js
CHANGED
|
@@ -18,19 +18,20 @@ function index (router, clientId, clientSecret, issuerSelector, encryptor, userM
|
|
|
18
18
|
cookieParserModule(router);
|
|
19
19
|
|
|
20
20
|
// Issuer Selector
|
|
21
|
-
const keycloakIssuer = issuerSelector.providers[Object.keys(issuerSelector.providers)[0]].issuer;
|
|
22
21
|
const tokenValidator = issuerSelector.providers[Object.keys(issuerSelector.providers)[0]].validator;
|
|
23
22
|
|
|
24
23
|
// Instantiate client
|
|
25
|
-
const client =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
const client = {
|
|
25
|
+
metadata: {
|
|
26
|
+
client_id: clientId,
|
|
27
|
+
client_secret: clientSecret
|
|
28
|
+
},
|
|
29
|
+
issuer: issuerSelector.providers[Object.keys(issuerSelector.providers)[0]].issuer
|
|
30
|
+
};
|
|
30
31
|
|
|
31
32
|
// Instantiate token modules
|
|
32
33
|
const accessTokenModule = accessTokenModule2(tokenValidator, encryptor, expOffset);
|
|
33
|
-
const refreshTokenModule = refreshTokenModule2(
|
|
34
|
+
const refreshTokenModule = refreshTokenModule2(encryptor);
|
|
34
35
|
const idTokenModule = idTokenModule2(encryptor); // id_token must be saved for Okta logout
|
|
35
36
|
|
|
36
37
|
const codeRequestModule = codeRequestModule2(client);
|
|
@@ -45,7 +46,7 @@ function index (router, clientId, clientSecret, issuerSelector, encryptor, userM
|
|
|
45
46
|
);
|
|
46
47
|
|
|
47
48
|
// Handle return from standard SSO
|
|
48
|
-
ssoModule(router,
|
|
49
|
+
ssoModule(router,
|
|
49
50
|
paths?.sso || '/sso',
|
|
50
51
|
codeRequestModule,
|
|
51
52
|
accessTokenModule,
|
package/esm/standard/login.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stringify } from 'node:querystring';
|
|
2
|
+
|
|
1
3
|
function login (router, client, loginPath, ssoPath, afterLoginPath, groups = true) {
|
|
2
4
|
router.get(loginPath, (req, res) => {
|
|
3
5
|
// Set redirectTo
|
|
@@ -10,11 +12,13 @@ function login (router, client, loginPath, ssoPath, afterLoginPath, groups = tru
|
|
|
10
12
|
scopes.push('groups');
|
|
11
13
|
|
|
12
14
|
// Standard flow initiates directly
|
|
13
|
-
res.redirect(client.
|
|
15
|
+
res.redirect(`${client.issuer.authorization_endpoint}?${stringify({
|
|
16
|
+
client_id: client.metadata.client_id,
|
|
17
|
+
response_type: 'code',
|
|
18
|
+
scope: scopes.join(' '),
|
|
14
19
|
redirect_uri: `${req.protocol}://${req.headers.host}${ssoPath}`,
|
|
15
|
-
state: redirectTo ? Buffer.from(redirectTo).toString('
|
|
16
|
-
|
|
17
|
-
}));
|
|
20
|
+
state: redirectTo ? Buffer.from(redirectTo).toString('base64url') : undefined
|
|
21
|
+
})}`);
|
|
18
22
|
});
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { postForm } from '@carisls/sso-core';
|
|
2
2
|
|
|
3
3
|
function refreshRequest (router, client, encryptor, accessTokenModule, refreshTokenModule, idTokenModule) {
|
|
4
|
-
const clientId = client.metadata.client_id;
|
|
5
|
-
const clientSecret = client.metadata.client_secret || undefined;
|
|
6
|
-
const url = client.issuer.token_endpoint;
|
|
7
|
-
|
|
8
4
|
router.all('*', (req, res, next) => {
|
|
9
5
|
// Check if SSO cookie is there
|
|
10
6
|
if (req.cookies['x-session']?.length > 36 || req.token || !req.cookies['x-session-sso']) {
|
|
@@ -14,9 +10,9 @@ function refreshRequest (router, client, encryptor, accessTokenModule, refreshTo
|
|
|
14
10
|
|
|
15
11
|
encryptor
|
|
16
12
|
.decrypt(req.cookies['x-session-sso'])
|
|
17
|
-
.then(token => postForm(
|
|
18
|
-
client_id:
|
|
19
|
-
client_secret:
|
|
13
|
+
.then(token => postForm(client.issuer.token_endpoint, {
|
|
14
|
+
client_id: client.metadata.client_id,
|
|
15
|
+
client_secret: client.metadata.client_secret,
|
|
20
16
|
grant_type: 'refresh_token',
|
|
21
17
|
refresh_token: token
|
|
22
18
|
}))
|
package/esm/standard/sso.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpError } from '@carisls/sso-core';
|
|
2
2
|
|
|
3
|
-
function sso (router,
|
|
3
|
+
function sso (router, ssoPath, codeRequestModule, accessTokenModule, refreshTokenModule, idTokenModule) {
|
|
4
4
|
router.get(ssoPath, (req, res, next) => {
|
|
5
5
|
if (!req.query.code) {
|
|
6
6
|
next(new HttpError(500, req.query.error));
|
|
@@ -14,7 +14,7 @@ function sso (router, client, ssoPath, codeRequestModule, accessTokenModule, ref
|
|
|
14
14
|
idTokenModule(res, tokens.id_token, req.protocol === 'https')
|
|
15
15
|
]))
|
|
16
16
|
.then(() => {
|
|
17
|
-
res.redirect(req.query.state ? Buffer.from(req.query.state, '
|
|
17
|
+
res.redirect(req.query.state ? Buffer.from(req.query.state, 'base64url').toString('utf8') : '/');
|
|
18
18
|
})
|
|
19
19
|
.catch((err) => {
|
|
20
20
|
next(err);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carisls/sso-standard",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A middleware implementing standard flow SSO",
|
|
5
5
|
"main": "cjs/index.cjs",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"author": "Mihovil Strujic <mstrujic@carisls.com>",
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@carisls/sso-core": "1.
|
|
28
|
+
"@carisls/sso-core": "1.1.1",
|
|
29
29
|
"cookie-parser": "^1.4.7",
|
|
30
30
|
"debug": "^4.4.0",
|
|
31
31
|
"express": "^4.21.2"
|