queueit-knownuser
Advanced tools
Comparing version 3.6.4 to 3.7.0
@@ -10,3 +10,3 @@ export interface IHttpRequest { | ||
export interface IHttpResponse { | ||
setCookie(cookieName: string, cookieValue: string, domain: string, expiration: any): any; | ||
setCookie(cookieName: string, cookieValue: string, domain: string, expiration: number, httpOnly: boolean, isSecure: boolean, sameSiteValue: string): any; | ||
} | ||
@@ -13,0 +13,0 @@ export interface IHttpContextProvider { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//# sourceMappingURL=HttpContextProvider.js.map |
@@ -10,5 +10,6 @@ "use strict"; | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.QueueUrlParams = exports.QueueParameterHelper = exports.Utils = exports.KnownUser = void 0; | ||
var KnownUser_1 = require("./KnownUser"); | ||
@@ -21,1 +22,2 @@ Object.defineProperty(exports, "KnownUser", { enumerable: true, get: function () { return KnownUser_1.KnownUser; } }); | ||
Object.defineProperty(exports, "QueueUrlParams", { enumerable: true, get: function () { return QueueITHelpers_1.QueueUrlParams; } }); | ||
//# sourceMappingURL=index.js.map |
@@ -17,3 +17,3 @@ "use strict"; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
@@ -223,1 +223,2 @@ return result; | ||
exports.ComparisonOperatorHelper = ComparisonOperatorHelper; | ||
//# sourceMappingURL=IntegrationConfigHelpers.js.map |
@@ -5,2 +5,5 @@ export declare class IntegrationConfigModel { | ||
CookieDomain: string; | ||
IsCookieHttpOnly: boolean; | ||
IsCookieSecure: boolean; | ||
CookieSameSiteValue: string | null; | ||
LayoutName: string; | ||
@@ -7,0 +10,0 @@ Culture: string; |
@@ -78,1 +78,2 @@ "use strict"; | ||
exports.ActionType = ActionType; | ||
//# sourceMappingURL=IntegrationConfigModel.js.map |
@@ -17,3 +17,3 @@ "use strict"; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
@@ -65,3 +65,4 @@ return result; | ||
return; | ||
httpContextProvider.getHttpResponse().setCookie(this.QueueITDebugKey, cookieValue, null, QueueITHelpers_1.Utils.getCurrentTime() + 20 * 60); // now + 20 mins | ||
httpContextProvider.getHttpResponse().setCookie(this.QueueITDebugKey, cookieValue, null, QueueITHelpers_1.Utils.getCurrentTime() + 20 * 60, // now + 20 mins | ||
false, false, null); | ||
}; | ||
@@ -122,3 +123,3 @@ KnownUser._resolveQueueRequestByLocalConfig = function (targetUrl, queueitToken, queueConfig, customerId, secretKey, httpContextProvider, debugEntries, isDebug) { | ||
KnownUser.handleQueueAction = function (currentUrlWithoutQueueITToken, queueitToken, customerIntegrationInfo, customerId, secretKey, matchedConfig, httpContextProvider, debugEntries, isDebug) { | ||
var targetUrl = ""; | ||
var targetUrl; | ||
switch (matchedConfig.RedirectLogic) { | ||
@@ -135,7 +136,7 @@ case "ForcedTargetUrl": | ||
} | ||
var queueEventConfig = new Models_1.QueueEventConfig(matchedConfig.EventId, matchedConfig.LayoutName, matchedConfig.Culture, matchedConfig.QueueDomain, matchedConfig.ExtendCookieValidity, matchedConfig.CookieValidityMinute, matchedConfig.CookieDomain, customerIntegrationInfo.Version, matchedConfig.Name); | ||
var queueEventConfig = new Models_1.QueueEventConfig(matchedConfig.EventId, matchedConfig.LayoutName, matchedConfig.Culture, matchedConfig.QueueDomain, matchedConfig.ExtendCookieValidity, matchedConfig.CookieValidityMinute, matchedConfig.CookieDomain, matchedConfig.IsCookieHttpOnly, matchedConfig.IsCookieSecure, matchedConfig.CookieSameSiteValue, customerIntegrationInfo.Version, matchedConfig.Name); | ||
return this._resolveQueueRequestByLocalConfig(targetUrl, queueitToken, queueEventConfig, customerId, secretKey, httpContextProvider, debugEntries, isDebug); | ||
}; | ||
KnownUser.handleCancelAction = function (currentUrlWithoutQueueITToken, queueitToken, customerIntegrationInfo, customerId, secretKey, matchedConfig, httpContextProvider, debugEntries, isDebug) { | ||
var cancelEventConfig = new Models_1.CancelEventConfig(matchedConfig.EventId, matchedConfig.QueueDomain, matchedConfig.CookieDomain, customerIntegrationInfo.Version, matchedConfig.Name); | ||
var cancelEventConfig = new Models_1.CancelEventConfig(matchedConfig.EventId, matchedConfig.QueueDomain, matchedConfig.CookieDomain, matchedConfig.IsCookieHttpOnly, matchedConfig.IsCookieSecure, matchedConfig.CookieSameSiteValue, customerIntegrationInfo.Version, matchedConfig.Name); | ||
var targetUrl = this.generateTargetUrl(currentUrlWithoutQueueITToken, httpContextProvider); | ||
@@ -252,1 +253,2 @@ return this._cancelRequestByLocalConfig(targetUrl, queueitToken, cancelEventConfig, customerId, secretKey, httpContextProvider, debugEntries, isDebug); | ||
exports.KnownUser = KnownUser; | ||
//# sourceMappingURL=KnownUser.js.map |
@@ -9,5 +9,8 @@ export declare class QueueEventConfig { | ||
cookieDomain: string; | ||
isCookieHttpOnly: boolean; | ||
isCookieSecure: boolean; | ||
cookieSameSiteValue: string; | ||
version: number; | ||
actionName: string; | ||
constructor(eventId: string, layoutName: string, culture: string, queueDomain: string, extendCookieValidity: boolean, cookieValidityMinute: number, cookieDomain: string, version: number, actionName?: string); | ||
constructor(eventId: string, layoutName: string, culture: string, queueDomain: string, extendCookieValidity: boolean, cookieValidityMinute: number, cookieDomain: string, isCookieHttpOnly: boolean, isCookieSecure: boolean, cookieSameSiteValue: string, version: number, actionName?: string); | ||
getString(): string; | ||
@@ -19,5 +22,8 @@ } | ||
cookieDomain: string; | ||
isCookieHttpOnly: boolean; | ||
isCookieSecure: boolean; | ||
cookieSameSiteValue: string; | ||
version: number; | ||
actionName: string; | ||
constructor(eventId: string, queueDomain: string, cookieDomain: string, version: number, actionName?: string); | ||
constructor(eventId: string, queueDomain: string, cookieDomain: string, isCookieHttpOnly: boolean, isCookieSecure: boolean, cookieSameSiteValue: string, version: number, actionName?: string); | ||
getString(): string; | ||
@@ -24,0 +30,0 @@ } |
@@ -6,3 +6,3 @@ "use strict"; | ||
var QueueEventConfig = /** @class */ (function () { | ||
function QueueEventConfig(eventId, layoutName, culture, queueDomain, extendCookieValidity, cookieValidityMinute, cookieDomain, version, actionName) { | ||
function QueueEventConfig(eventId, layoutName, culture, queueDomain, extendCookieValidity, cookieValidityMinute, cookieDomain, isCookieHttpOnly, isCookieSecure, cookieSameSiteValue, version, actionName) { | ||
if (actionName === void 0) { actionName = 'unspecified'; } | ||
@@ -16,2 +16,5 @@ this.eventId = eventId; | ||
this.cookieDomain = cookieDomain; | ||
this.isCookieHttpOnly = isCookieHttpOnly; | ||
this.isCookieSecure = isCookieSecure; | ||
this.cookieSameSiteValue = cookieSameSiteValue; | ||
this.version = version; | ||
@@ -22,3 +25,5 @@ this.actionName = actionName; | ||
return "EventId:" + this.eventId + "&Version:" + this.version + "&ActionName:" + this.actionName + "&QueueDomain:" + this.queueDomain + | ||
("&CookieDomain:" + this.cookieDomain + "&ExtendCookieValidity:" + this.extendCookieValidity) + | ||
("&CookieDomain:" + this.cookieDomain + "&IsCookieHttpOnly:" + this.isCookieHttpOnly + "&IsCookieSecure:" + this.isCookieSecure) + | ||
("&CookieSameSiteValue:" + this.cookieSameSiteValue) + | ||
("&ExtendCookieValidity:" + this.extendCookieValidity) + | ||
("&CookieValidityMinute:" + this.cookieValidityMinute + "&LayoutName:" + this.layoutName + "&Culture:" + this.culture); | ||
@@ -30,3 +35,3 @@ }; | ||
var CancelEventConfig = /** @class */ (function () { | ||
function CancelEventConfig(eventId, queueDomain, cookieDomain, version, actionName) { | ||
function CancelEventConfig(eventId, queueDomain, cookieDomain, isCookieHttpOnly, isCookieSecure, cookieSameSiteValue, version, actionName) { | ||
if (actionName === void 0) { actionName = 'unspecified'; } | ||
@@ -36,2 +41,5 @@ this.eventId = eventId; | ||
this.cookieDomain = cookieDomain; | ||
this.isCookieHttpOnly = isCookieHttpOnly; | ||
this.isCookieSecure = isCookieSecure; | ||
this.cookieSameSiteValue = cookieSameSiteValue; | ||
this.version = version; | ||
@@ -42,3 +50,6 @@ this.actionName = actionName; | ||
return "EventId:" + this.eventId + "&Version:" + this.version + | ||
("&QueueDomain:" + this.queueDomain + "&CookieDomain:" + this.cookieDomain + "&ActionName:" + this.actionName); | ||
("&QueueDomain:" + this.queueDomain) + | ||
("&CookieDomain:" + this.cookieDomain + "&IsCookieHttpOnly:" + this.isCookieHttpOnly + "&IsCookieSecure:" + this.isCookieSecure) + | ||
("&CookieSameSiteValue:" + this.cookieSameSiteValue) + | ||
("&ActionName:" + this.actionName); | ||
}; | ||
@@ -88,1 +99,2 @@ return CancelEventConfig; | ||
exports.ActionTypes = ActionTypes; | ||
//# sourceMappingURL=Models.js.map |
@@ -33,3 +33,3 @@ import { RequestValidationResult } from './Models'; | ||
export declare class CookieHelper { | ||
static toMapFromValue(cookieValue: string): {}; | ||
static toMapFromValue(cookieValue: string): object; | ||
static toValueFromKeyValueCollection(cookieValues: Array<{ | ||
@@ -36,0 +36,0 @@ key: string; |
@@ -135,4 +135,3 @@ "use strict"; | ||
} | ||
var result = values.join("&"); | ||
return result; | ||
return values.join("&"); | ||
}; | ||
@@ -183,1 +182,2 @@ return CookieHelper; | ||
exports.ConnectorDiagnostics = ConnectorDiagnostics; | ||
//# sourceMappingURL=QueueITHelpers.js.map |
@@ -11,3 +11,3 @@ "use strict"; | ||
UserInQueueService.prototype.getValidTokenResult = function (config, queueParams, secretKey) { | ||
this.userInQueueStateRepository.store(config.eventId, queueParams.queueId, queueParams.cookieValidityMinutes, config.cookieDomain, queueParams.redirectType, secretKey); | ||
this.userInQueueStateRepository.store(config.eventId, queueParams.queueId, queueParams.cookieValidityMinutes, config.cookieDomain, config.isCookieHttpOnly, config.isCookieSecure, config.cookieSameSiteValue, queueParams.redirectType, secretKey); | ||
return new Models_1.RequestValidationResult(Models_1.ActionTypes.QueueAction, config.eventId, queueParams.queueId, null, queueParams.redirectType, config.actionName); | ||
@@ -46,4 +46,3 @@ }; | ||
queueDomain = queueDomain + "/"; | ||
var redirectUrl = "https://" + queueDomain + uriPath + "?" + query; | ||
return redirectUrl; | ||
return "https://" + queueDomain + uriPath + "?" + query; | ||
}; | ||
@@ -54,3 +53,3 @@ UserInQueueService.prototype.validateQueueRequest = function (targetUrl, queueitToken, config, customerId, secretKey) { | ||
if (state.isStateExtendable() && config.extendCookieValidity) { | ||
this.userInQueueStateRepository.store(config.eventId, state.queueId, null, config.cookieDomain, state.redirectType, secretKey); | ||
this.userInQueueStateRepository.store(config.eventId, state.queueId, null, config.cookieDomain, config.isCookieHttpOnly, config.isCookieSecure, config.cookieSameSiteValue, state.redirectType, secretKey); | ||
} | ||
@@ -60,3 +59,3 @@ return new Models_1.RequestValidationResult(Models_1.ActionTypes.QueueAction, config.eventId, state.queueId, null, state.redirectType, config.actionName); | ||
var queueParams = QueueITHelpers_1.QueueParameterHelper.extractQueueParams(queueitToken); | ||
var requestValidationResult = null; | ||
var requestValidationResult; | ||
var isTokenValid = false; | ||
@@ -77,3 +76,3 @@ if (queueParams != null) { | ||
if (state.isFound && !isTokenValid) { | ||
this.userInQueueStateRepository.cancelQueueCookie(config.eventId, config.cookieDomain); | ||
this.userInQueueStateRepository.cancelQueueCookie(config.eventId, config.cookieDomain, config.isCookieHttpOnly, config.isCookieSecure, config.cookieSameSiteValue); | ||
} | ||
@@ -86,6 +85,9 @@ return requestValidationResult; | ||
if (state.isValid) { | ||
this.userInQueueStateRepository.cancelQueueCookie(config.eventId, config.cookieDomain); | ||
this.userInQueueStateRepository.cancelQueueCookie(config.eventId, config.cookieDomain, config.isCookieHttpOnly, config.isCookieSecure, config.cookieSameSiteValue); | ||
var query = this.getQueryString(customerId, config.eventId, config.version, null, null, config.actionName) + | ||
(targetUrl ? "&r=" + QueueITHelpers_1.Utils.encodeUrl(targetUrl) : ""); | ||
var uriPath = "cancel/" + customerId + "/" + config.eventId + "/"; | ||
var uriPath = "cancel/" + customerId + "/" + config.eventId; | ||
if (state.queueId) { | ||
uriPath += "/" + state.queueId; | ||
} | ||
var redirectUrl = this.generateRedirectUrl(config.queueDomain, uriPath, query); | ||
@@ -114,3 +116,3 @@ return new Models_1.RequestValidationResult(Models_1.ActionTypes.CancelAction, config.eventId, state.queueId, redirectUrl, state.redirectType, config.actionName); | ||
}; | ||
UserInQueueService.SDK_VERSION = "v3-javascript-" + "3.6.3"; | ||
UserInQueueService.SDK_VERSION = "v3-javascript-" + "3.7.0"; | ||
return UserInQueueService; | ||
@@ -126,1 +128,2 @@ }()); | ||
}()); | ||
//# sourceMappingURL=UserInQueueService.js.map |
@@ -11,9 +11,12 @@ import { IHttpContextProvider } from './HttpContextProvider'; | ||
private static readonly _FixedCookieValidityMinutesKey; | ||
private static readonly _IsCookieHttpOnly; | ||
private static readonly _IsCookieSecure; | ||
private static readonly _CookieSameSiteValue; | ||
constructor(httpContextProvider: IHttpContextProvider); | ||
static getCookieKey(eventId: string): string; | ||
store(eventId: string, queueId: string, fixedCookieValidityMinutes: number | null, cookieDomain: string, redirectType: string, secretKey: string): void; | ||
store(eventId: string, queueId: string, fixedCookieValidityMinutes: number | null, cookieDomain: string, isHttpOnly: boolean, isSecure: boolean, sameSiteValue: string, redirectType: string, secretKey: string): void; | ||
private createCookie; | ||
getState(eventId: string, cookieValidityMinutes: number, secretKey: string, validateTime: boolean): StateInfo; | ||
private isCookieValid; | ||
cancelQueueCookie(eventId: string, cookieDomain: string): void; | ||
cancelQueueCookie(eventId: string, cookieDomain: string, isCookieHttpOnly: boolean, isSecure: boolean, sameSiteValue: string): void; | ||
reissueQueueCookie(eventId: string, cookieValidityMinutes: number, cookieDomain: string, secretKey: string): void; | ||
@@ -20,0 +23,0 @@ private generateHash; |
@@ -12,6 +12,8 @@ "use strict"; | ||
}; | ||
UserInQueueStateCookieRepository.prototype.store = function (eventId, queueId, fixedCookieValidityMinutes, cookieDomain, redirectType, secretKey) { | ||
this.createCookie(eventId, queueId, fixedCookieValidityMinutes ? fixedCookieValidityMinutes.toString() : "", redirectType, cookieDomain, secretKey); | ||
UserInQueueStateCookieRepository.prototype.store = function (eventId, queueId, fixedCookieValidityMinutes, cookieDomain, isHttpOnly, isSecure, sameSiteValue, redirectType, secretKey) { | ||
isHttpOnly = isHttpOnly == null ? false : isHttpOnly; | ||
isSecure = isSecure == null ? false : isSecure; | ||
this.createCookie(eventId, queueId, fixedCookieValidityMinutes ? fixedCookieValidityMinutes.toString() : "", redirectType, cookieDomain, isHttpOnly, isSecure, sameSiteValue, secretKey); | ||
}; | ||
UserInQueueStateCookieRepository.prototype.createCookie = function (eventId, queueId, fixedCookieValidityMinutes, redirectType, cookieDomain, secretKey) { | ||
UserInQueueStateCookieRepository.prototype.createCookie = function (eventId, queueId, fixedCookieValidityMinutes, redirectType, cookieDomain, isHttpOnly, isSecure, sameSiteValue, secretKey) { | ||
var cookieKey = UserInQueueStateCookieRepository.getCookieKey(eventId); | ||
@@ -23,3 +25,6 @@ var issueTime = QueueITHelpers_1.Utils.getCurrentTime().toString(); | ||
if (fixedCookieValidityMinutes) { | ||
cookieValues.push({ key: UserInQueueStateCookieRepository._FixedCookieValidityMinutesKey, value: fixedCookieValidityMinutes }); | ||
cookieValues.push({ | ||
key: UserInQueueStateCookieRepository._FixedCookieValidityMinutesKey, | ||
value: fixedCookieValidityMinutes | ||
}); | ||
} | ||
@@ -32,6 +37,6 @@ cookieValues.push({ key: UserInQueueStateCookieRepository._RedirectTypeKey, value: redirectType.toLowerCase() }); | ||
}); | ||
var tommorrow = new Date(); | ||
tommorrow.setDate(tommorrow.getDate() + 1); | ||
var expire = Math.floor(tommorrow.getTime() / 1000); | ||
this.httpContextProvider.getHttpResponse().setCookie(cookieKey, QueueITHelpers_1.CookieHelper.toValueFromKeyValueCollection(cookieValues), cookieDomain, expire); | ||
var tomorrow = new Date(); | ||
tomorrow.setDate(tomorrow.getDate() + 1); | ||
var expire = Math.floor(tomorrow.getTime() / 1000); | ||
this.httpContextProvider.getHttpResponse().setCookie(cookieKey, QueueITHelpers_1.CookieHelper.toValueFromKeyValueCollection(cookieValues), cookieDomain, expire, isHttpOnly, isSecure, sameSiteValue); | ||
}; | ||
@@ -80,5 +85,6 @@ UserInQueueStateCookieRepository.prototype.getState = function (eventId, cookieValidityMinutes, secretKey, validateTime) { | ||
}; | ||
UserInQueueStateCookieRepository.prototype.cancelQueueCookie = function (eventId, cookieDomain) { | ||
UserInQueueStateCookieRepository.prototype.cancelQueueCookie = function (eventId, cookieDomain, isCookieHttpOnly, isSecure, sameSiteValue) { | ||
var cookieKey = UserInQueueStateCookieRepository.getCookieKey(eventId); | ||
this.httpContextProvider.getHttpResponse().setCookie(cookieKey, "", cookieDomain, 0); | ||
this.httpContextProvider.getHttpResponse() | ||
.setCookie(cookieKey, "", cookieDomain, 0, isCookieHttpOnly, isSecure, sameSiteValue); | ||
}; | ||
@@ -96,3 +102,3 @@ UserInQueueStateCookieRepository.prototype.reissueQueueCookie = function (eventId, cookieValidityMinutes, cookieDomain, secretKey) { | ||
fixedCookieValidityMinutes = cookieValues[UserInQueueStateCookieRepository._FixedCookieValidityMinutesKey].toString(); | ||
this.createCookie(eventId, cookieValues[UserInQueueStateCookieRepository._QueueIdKey], fixedCookieValidityMinutes, cookieValues[UserInQueueStateCookieRepository._RedirectTypeKey], cookieDomain, secretKey); | ||
this.createCookie(eventId, cookieValues[UserInQueueStateCookieRepository._QueueIdKey], fixedCookieValidityMinutes, cookieValues[UserInQueueStateCookieRepository._RedirectTypeKey], cookieDomain, cookieValues[UserInQueueStateCookieRepository._IsCookieHttpOnly], cookieValues[UserInQueueStateCookieRepository._IsCookieSecure], cookieValues[UserInQueueStateCookieRepository._CookieSameSiteValue], secretKey); | ||
}; | ||
@@ -110,2 +116,5 @@ UserInQueueStateCookieRepository.prototype.generateHash = function (eventId, queueId, fixedCookieValidityMinutes, redirectType, issueTime, secretKey) { | ||
UserInQueueStateCookieRepository._FixedCookieValidityMinutesKey = "FixedValidityMins"; | ||
UserInQueueStateCookieRepository._IsCookieHttpOnly = "IsCookieHttpOnly"; | ||
UserInQueueStateCookieRepository._IsCookieSecure = "IsCookieSecure"; | ||
UserInQueueStateCookieRepository._CookieSameSiteValue = "CookieSameSiteValue"; | ||
return UserInQueueStateCookieRepository; | ||
@@ -128,1 +137,2 @@ }()); | ||
exports.StateInfo = StateInfo; | ||
//# sourceMappingURL=UserInQueueStateCookieRepository.js.map |
{ | ||
"name": "queueit-knownuser", | ||
"version": "3.6.4", | ||
"version": "3.7.0", | ||
"description": "SDK to integrate Queue-it into a javascript based server side application.", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"repository": "https://github.com/queueit/KnownUser.V3.Javascript", | ||
"scripts": { | ||
"prepare": "npm run build", | ||
"build": "tsc" | ||
"build": "tsc && npm run browserify", | ||
"browserify": "browserify . -s QueueIT.KnownUserV3.SDK -o dist/browserified.js", | ||
"test": "mocha --recursive" | ||
}, | ||
"keywords": [], | ||
"author": "QueueIT", | ||
"license": "GNU Lesser General Public License v3.0" | ||
"license": "MIT", | ||
"devDependencies": { | ||
"browserify": "^17.0.0", | ||
"chai": "^4.3.4", | ||
"chai-string": "^1.5.0", | ||
"mocha": "^9.1.2", | ||
"ts-node": "^10.2.1", | ||
"typescript": "^4.4.3" | ||
} | ||
} |
@@ -1,49 +0,8 @@ | ||
>You can find the latest released version [here](https://github.com/queueit/KnownUser.V3.Javascript/releases/latest) | ||
# KnownUser.V3.Javascript | ||
The [Queue-it](https://queue-it.com) Security Framework is used to ensure that end users cannot bypass the queue by adding a server-side integration to your server. It was developed with TypeScript and verified using Nodejs v.8.12 and Express v.4.16. | ||
Before getting started please read the [documentation](https://github.com/queueit/Documentation/tree/main/serverside-connectors) to get acquainted with server-side connectors. | ||
## Introduction | ||
When a user is redirected back from the queue to your website, the queue engine can attache a query string parameter (`queueittoken`) containing some information about the user. | ||
The most important fields of the `queueittoken` are: | ||
Connector was developed with TypeScript and verified using Nodejs v.8.12 and Express v.4.16. | ||
- q - the users unique queue identifier | ||
- ts - a timestamp of how long this redirect is valid | ||
- h - a hash of the token | ||
You can find the latest released version [here](https://github.com/queueit/KnownUser.V3.Javascript/releases/latest). or download latest npm package from [here](https://www.npmjs.com/package/queueit-knownuser). | ||
The high level logic is as follows: | ||
![The KnownUser validation flow](https://github.com/queueit/KnownUser.V3.Javascript/blob/master/Documentation/KnownUserFlow.png?raw=true) | ||
1. User requests a page on your server | ||
2. The validation method sees that the has no Queue-it session cookie and no `queueittoken` and sends him to the correct queue based on the configuration | ||
3. User waits in the queue | ||
4. User is redirected back to your website, now with a `queueittoken` | ||
5. The validation method validates the `queueittoken` and creates a Queue-it session cookie | ||
6. The user browses to a new page and the Queue-it session cookie will let him go there without queuing again | ||
## How to validate a user | ||
To validate that the current user is allowed to enter your website (has been through the queue) these steps are needed: | ||
1. Providing the queue configuration to the KnownUser validation | ||
2. Validate the `queueittoken` and store a session cookie | ||
### 1. Providing the queue configuration | ||
The recommended way is to use the Go Queue-it self-service portal to setup the configuration. | ||
The configuration specifies a set of Triggers and Actions. A Trigger is an expression matching one, more or all URLs on your website. | ||
When a user enter your website and the URL matches a Trigger-expression the corresponding Action will be triggered. | ||
The Action specifies which queue the users should be send to. | ||
In this way you can specify which queue(s) should protect which page(s) on the fly without changing the server-side integration. | ||
This configuration can then be downloaded to your application server. | ||
Read more about how *[here](https://github.com/queueit/KnownUser.V3.Javascript/tree/master/Documentation)*. | ||
### 2. Validate the `queueittoken` and store a session cookie | ||
To validate that the user has been through the queue, use the `knownUser.validateRequestByIntegrationConfig()` method. | ||
This call will validate the timestamp and hash and if valid create a "QueueITAccepted-SDFrts345E-V3_[EventId]" cookie with a TTL as specified in the configuration. | ||
If the timestamp or hash is invalid, the user is send back to the queue. | ||
## Implementation | ||
@@ -54,3 +13,3 @@ The KnownUser validation must be done on *all requests except requests for static and cached pages, resources like images, css files and ...*. | ||
The following is an example route in express/nodejs which shows how to validate that a user has been through the queue. | ||
It asumes that your integrationconfiguration file is located in root of the web application and the known user sdk file is in a folder called 'sdk'. Please note it uses the node module 'node-import' to import the SDK code. | ||
It assumes that your integrationconfiguration file is located in root of the web application. | ||
@@ -62,3 +21,3 @@ ```javascript | ||
var QueueITConnector = require('./src/index'); | ||
var QueueITConnector = require('queueit-knownuser'); | ||
@@ -114,3 +73,3 @@ configureKnownUserHashing(); | ||
// Request can continue - we remove queueittoken form querystring parameter to avoid sharing of user specific token | ||
if (requestUrl !== requestUrlWithoutToken && validationResult.actionType) { | ||
if (requestUrl !== requestUrlWithoutToken && validationResult.actionType === "Queue") { | ||
res.redirect(requestUrlWithoutToken); | ||
@@ -139,3 +98,4 @@ } | ||
Code to initialize a httpContextProvider in Express (requires node module 'cookie-parser'): | ||
``` | ||
```javascript | ||
function initializeExpressHttpContextProvider(req, res) { | ||
@@ -171,3 +131,3 @@ return { | ||
var httpResponse = { | ||
setCookie: function (cookieName, cookieValue, domain, expiration) { | ||
setCookie: function (cookieName, cookieValue, domain, expiration, httpOnly, isSecure, sameSiteValue) { | ||
if (domain === "") | ||
@@ -187,4 +147,5 @@ domain = null; | ||
domain: domain, | ||
secure: false, | ||
httpOnly: false | ||
secure: isSecure, | ||
httpOnly: httpOnly, | ||
sameSite: sameSiteValue | ||
}); | ||
@@ -200,3 +161,4 @@ } | ||
Code to configure hashing in KnownUser SDK (requires node module 'crypto'): | ||
``` | ||
```javascript | ||
function configureKnownUserHashing() { | ||
@@ -213,26 +175,6 @@ var utils = QueueITConnector.Utils; | ||
``` | ||
### Protecting ajax calls | ||
If you need to protect AJAX calls beside page loads you need to add the below JavaScript tags to your pages: | ||
``` | ||
<script type="text/javascript" src="//static.queue-it.net/script/queueclient.min.js"></script> | ||
<script | ||
data-queueit-intercept-domain="{YOUR_CURRENT_DOMAIN}" | ||
data-queueit-intercept="true" | ||
data-queueit-c="{YOUR_CUSTOMER_ID}" | ||
type="text/javascript" | ||
src="//static.queue-it.net/script/queueconfigloader.min.js"> | ||
</script> | ||
``` | ||
## Alternative Implementation | ||
## Implementation using inline queue configuration | ||
Specify the configuration in code without using the Trigger/Action paradigm. In this case it is important *only to queue-up page requests* and not requests for resources or AJAX calls. This can be done by adding custom filtering logic before caling the `knownUser.resolveQueueRequestByLocalConfig()` method. | ||
### Queue configuration | ||
If your application server (maybe due to security reasons) is not allowed to do external GET requests, then you have three options: | ||
1. Manually download the configuration file from Queue-it Go self-service portal, save it on your application server and load it from local disk | ||
2. Use an internal gateway server to download the configuration file and save to application server | ||
3. Specify the configuration in code without using the Trigger/Action paradigm. In this case it is important *only to queue-up page requests* and not requests for resources or AJAX calls. | ||
This can be done by adding custom filtering logic before caling the `knownUser.resolveQueueRequestByLocalConfig()` method. | ||
The following is an example (using Express/Nodejs) of how to specify the configuration in code: | ||
@@ -245,3 +187,3 @@ | ||
var QueueITConnector = require('./src/index'); | ||
var QueueITConnector = require('queueit-knownuser'); | ||
@@ -306,3 +248,3 @@ configureKnownUserHashing(); | ||
// Request can continue - we remove queueittoken form querystring parameter to avoid sharing of user specific token | ||
if (requestUrl !== requestUrlWithoutToken && validationResult.actionType) { | ||
if (requestUrl !== requestUrlWithoutToken && validationResult.actionType === "Queue") { | ||
res.redirect(requestUrlWithoutToken); | ||
@@ -309,0 +251,0 @@ } |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
Copyleft License
License(Experimental) Copyleft license information was found.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
Non-permissive License
License(Experimental) A license not known to be considered permissive was found.
Found 1 instance in 1 package
191661
38
0
0
100
2489
6
261
3