added time drift slider
This commit is contained in:
@@ -177,20 +177,20 @@ def main():
|
|||||||
prog='session-security-poc',
|
prog='session-security-poc',
|
||||||
description='Program to demostrate improved user session security')
|
description='Program to demostrate improved user session security')
|
||||||
parser.add_argument('--host', default='127.0.0.1')
|
parser.add_argument('--host', default='127.0.0.1')
|
||||||
parser.add_argument('--port', default='8080')
|
parser.add_argument('--port', default='1443')
|
||||||
parser.add_argument('--key-file')
|
parser.add_argument('--key-file')
|
||||||
parser.add_argument('--cert-file')
|
parser.add_argument('--cert-file')
|
||||||
parser.add_argument('--tls-self-signed', action='store_true')
|
parser.add_argument('--disable-tls', action='store_true')
|
||||||
|
|
||||||
args = parser.parse_args(sys.argv[1:])
|
args = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
if args.tls_self_signed:
|
if args.key_file and args.cert_file:
|
||||||
ssl_context = 'adhoc'
|
|
||||||
elif args.key_file and args.cert_file:
|
|
||||||
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
ssl_context.load_cert_chain(certfile=args.cert_file, keyfile=args.key_file)
|
ssl_context.load_cert_chain(certfile=args.cert_file, keyfile=args.key_file)
|
||||||
|
elif args.disable_tls:
|
||||||
|
ssl_context = None
|
||||||
else:
|
else:
|
||||||
ssl_context = None
|
ssl_context = 'adhoc'
|
||||||
app.run(host=args.host, port=args.port, ssl_context=ssl_context)
|
app.run(host=args.host, port=args.port, ssl_context=ssl_context)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,12 +4,47 @@
|
|||||||
<script src="js/sspoc.js" defer></script>
|
<script src="js/sspoc.js" defer></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Username</td>
|
||||||
|
<td>Password</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>user1</td>
|
||||||
|
<td>password</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>user2</td>
|
||||||
|
<td>password</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>user3</td>
|
||||||
|
<td>password</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>user4</td>
|
||||||
|
<td>password</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<form id="login-form">
|
<form id="login-form">
|
||||||
<label for="username">Username</label>
|
<label for="username">Username</label>
|
||||||
<input id="username" type="text">
|
<input id="username" type="text"/>
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input id="password" type="password">
|
<input id="password" type="password"/>
|
||||||
<button id="login-button" type="button">Login</button>
|
<button id="login-button" type="button">Login</button>
|
||||||
</form>
|
</form>
|
||||||
|
<div>
|
||||||
|
<form id="whoami-form">
|
||||||
|
<input id="time-drift-slider" type="range" min="-9000" max="+9000" step="100" value="0"/>
|
||||||
|
<label for="time-drift-slider">Time drift: <em>0 s</em></label>
|
||||||
|
<input id="whoami-button" type="button" value="whoami"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@@ -71,6 +71,7 @@ loginButton.addEventListener('click', async evt => {
|
|||||||
let paragraph = document.createElement('p');
|
let paragraph = document.createElement('p');
|
||||||
paragraph.textContent = await response.text();
|
paragraph.textContent = await response.text();
|
||||||
document.body.appendChild(paragraph);
|
document.body.appendChild(paragraph);
|
||||||
|
setTimeout(() => document.body.removeChild(paragraph), 10000);
|
||||||
}
|
}
|
||||||
const nonceHeader = response.headers.get('nonce');
|
const nonceHeader = response.headers.get('nonce');
|
||||||
const encryptedNonce = atob(nonceHeader);
|
const encryptedNonce = atob(nonceHeader);
|
||||||
@@ -82,10 +83,10 @@ loginButton.addEventListener('click', async evt => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function computeToken() {
|
async function computeToken(instant) {
|
||||||
if(nonce != null) {
|
if(nonce != null) {
|
||||||
const crypto = window.crypto.subtle;
|
const crypto = window.crypto.subtle;
|
||||||
const epochTick = Math.floor(new Date().getTime() / 3000);
|
const epochTick = Math.floor(instant / 3000);
|
||||||
const data = concatenateUInt8Arrays(nonce, integerToBytes(epochTick, 8));
|
const data = concatenateUInt8Arrays(nonce, integerToBytes(epochTick, 8));
|
||||||
const hash = new Uint8Array(await crypto.digest("SHA-256", data));
|
const hash = new Uint8Array(await crypto.digest("SHA-256", data));
|
||||||
const token = btoa(Array.from(hash, byte => String.fromCharCode(byte)).join(''));
|
const token = btoa(Array.from(hash, byte => String.fromCharCode(byte)).join(''));
|
||||||
@@ -95,15 +96,19 @@ async function computeToken() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let div = document.createElement('div');
|
|
||||||
document.body.appendChild(div);
|
|
||||||
|
|
||||||
let whoamiButton = document.createElement('button');
|
const whoamiButton = document.getElementById('whoami-button');
|
||||||
whoamiButton.textContent = 'whoami'
|
const whoamiForm = document.getElementById('whoami-form');
|
||||||
div.appendChild(whoamiButton);
|
const timeDriftLabel = whoamiForm.querySelector("label em");
|
||||||
|
const timeDriftSlider = whoamiForm['time-drift-slider'];
|
||||||
|
timeDriftSlider.addEventListener('input', evt => {
|
||||||
|
timeDriftLabel.textContent = parseInt(evt.target.value) / 1000 + ' s';
|
||||||
|
});
|
||||||
|
|
||||||
whoamiButton.addEventListener('click', async evt => {
|
whoamiButton.addEventListener('click', async evt => {
|
||||||
const token = await computeToken();
|
const drift = parseInt(timeDriftSlider.value);
|
||||||
|
const instant = new Date().getTime() + drift;
|
||||||
|
const token = await computeToken(instant);
|
||||||
let headers = {};
|
let headers = {};
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
headers = {
|
headers = {
|
||||||
@@ -117,27 +122,27 @@ whoamiButton.addEventListener('click', async evt => {
|
|||||||
let paragraph = document.createElement('p');
|
let paragraph = document.createElement('p');
|
||||||
paragraph.textContent = text;
|
paragraph.textContent = text;
|
||||||
document.body.appendChild(paragraph);
|
document.body.appendChild(paragraph);
|
||||||
|
setTimeout(() => document.body.removeChild(paragraph), 10000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let helloButton = document.createElement('button');
|
// const helloButton = document.createElement('button');
|
||||||
helloButton.textContent = 'hello'
|
// helloButton.textContent = 'hello'
|
||||||
div.appendChild(helloButton);
|
|
||||||
|
|
||||||
helloButton.addEventListener('click', async evt => {
|
// helloButton.addEventListener('click', async evt => {
|
||||||
const token = await computeToken();
|
// const token = await computeToken();
|
||||||
let headers = {};
|
// let headers = {};
|
||||||
if (token != null) {
|
// if (token != null) {
|
||||||
headers = {
|
// headers = {
|
||||||
'x-token': token
|
// 'x-token': token
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
fetch('api/hello', {
|
// fetch('api/hello', {
|
||||||
method: 'GET',
|
// method: 'GET',
|
||||||
headers
|
// headers
|
||||||
}).then(response => response.text()).then(text => {
|
// }).then(response => response.text()).then(text => {
|
||||||
let paragraph = document.createElement('p');
|
// let paragraph = document.createElement('p');
|
||||||
paragraph.textContent = text;
|
// paragraph.textContent = text;
|
||||||
document.body.appendChild(paragraph);
|
// document.body.appendChild(paragraph);
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
Reference in New Issue
Block a user