I read many examples of the method in Keycloak-js without a clear explanation of the following method.
updateToken(minValidity: number): KeycloakPromise<boolean, boolean>;
Note : I am using "keycloak-js": "^15.0.2"
Here is its documentation
/**
* If the token expires within `minValidity` seconds, the token is refreshed.
* If the session status iframe is enabled, the session status is also
* checked.
* #returns A promise to set functions that can be invoked if the token is
* still valid, or if the token is no longer valid.
* #example
* ```js
* keycloak.updateToken(5).then(function(refreshed) {
* if (refreshed) {
* alert('Token was successfully refreshed');
* } else {
* alert('Token is still valid');
* }
* }).catch(function() {
* alert('Failed to refresh the token, or the session has expired');
* });
*/
I am not a native english speaker. The term "expires within" is imprecise here.
An illustration is better understood. This method updateToken periodically checks if the token is expired or not during a window of time minValidity
When the token will be refreshed ?
When the keycloak token expiration is approaching, the token refreshment is either :
right prior its expiration date within the window of time minValidity ( blue)
OR after the next period update check. (orange)
In the blue case, it makes sense to have a large enough value of minValidity.
In the orange case, a small value is better.
I understand it is the blue case.
Bonus question : What will happen if the token duration < minValidity ?
Overall you want to avoid a situation where you send the AccessToken to a server/service and it gets rejected because it's not valid anymore.
So it's a good idea to check validity everytime before using the token. As the documentation mentions: calls to a service/backend should only be made within the callback of the updateToken method. But beside that, there is no (automatic) periodic check for refreshing the token.
The minValidity comes into place if you imagine a situation where the remaining AccessToken Lifetime is only 1 second.
If you check the token on client side (isTokenExpired() => false) it will still be valid, but there is a probability, that when the request reaches a service, the token will not be valid anymore and gets rejected. => we want to avoid that
The default value for minValidity is 5 seconds. So when calling the updateToken method and the token is still valid, but will expire within the next 5 seconds the token gets refreshed and any service/backend call inside the callback will use the new token. But a call itself does not necessarily mean a new token. If the remaining lifetime is long enough, nothing happens.
So in your example the blue situation is correct. The second "update" call (if you mean a updateToken method call) will already trigger a token refresh. But again: The update calls are not done automatically. You need to either implement a periodic check or call updateToken before a backend call.
To your bonus question: I looked into the code and in a fictional situation where e.g. minValidity is 60s but a new fresh token is always only valid for 30s, a call to updateToken will trigger a refresh everytime. But imho there will be no recurring "refresh-loop"
Related
I have a simple component to verify user's email. It consists of "Send Email" (that sends email with code) button, text input to enter sent code and "Verify" button that sends code to back for verification. Berification code expires in 5 minutes. And if I resend email new code expires in 5 minutes after resend.
I'm using OnPush change detection strategy so everything is handled with async pipes. The observable wrapping "Send Email" request is passed to template as async pipe. I want to have an other observable that will emit something (e.g. true) when 5 minutes passed. Yes, I can use delay operator in the way like the following
expired$ = sendObservable$.pipe(delay(5 * 60 * 1000), mapTo(true))
But. What if user decide to resend email? How can I restart these 5 minutes from the beginging?
And yes, I understand that all of that is somewhat strange. Maybe there's totaly different way to handle expiration of code using observables and async pipes?
debounceTime delays values emitted by the source Observable, but drops
previous pending delayed emissions if a new value arrives on the
source Observable. This operator keeps track of the most recent value
from the source Observable, and emits that only when dueTime enough
time has passed without any other value appearing on the source
Observable. If a new value appears before dueTime silence occurs, the
previous value will be dropped and will not be emitted on the output
So, simply:
expired$ = sendObservable$.pipe(debounceTime(5 * 60 * 1000))
I am developing a chatbot using Dialogflow, I would like to throw a message to user when the chatbot doesn't understand the user input for three times in a row and for the forth time respond with a custom message (not the one of the options declared on the dialogflow interface)
One idea that I have is to make a counter within the input unknown action like this:
var counter = 1;
// The default fallback intent has been matched, try to recover (https://dialogflow.com/docs/intents#fallback_intents)
'input.unknown': () => {
// Use the Actions on Google lib to respond to Google requests; for other requests use JSON
if (requestSource === googleAssistantRequest) {
sendGoogleResponse('I\'m having trouble, can you try that again?'); // Send simple response to user
} else {
if (counter == 3) {
counter = 1;
sendResponse('Custom message');
} else {
counter++;
sendResponse('I\'m having trouble, can you try that again?'); // Send simple response to user
}
}
},
This would work, but idk if this will work for multiple user at the same time, I was thinking to create a storage for storing requests attached by a unique id and have a different counter for each request!
Do you have any better idea of achieving such thing in Dialogflow?
This will not work the way you've designed it. Not quite for the reason you think, but close.
You don't show the rest of your code (that's ok), but the counter variable is probably in a function that gets called each time it processes a message. When that function is finished, the counter variable goes out of scope - it is lost. Having multiple calls at the same time won't really be an issue since each call gets a different scope (I'm glossing over some technical details, but this should be good enough).
One solution is that you could store the variable in a global context - but then you do have the issue of multiple users ending up with the same counter. That is very very bad.
Your solution about keeping a counter in a database, keyed against the user, does make sense. But for this need, it is overkill. It is useful for saving data between conversations, but there are better ways to save information during the same conversation.
The easiest solution would be to use a Dialogflow Context. Contexts let you save state in between calls to your webhook fulfillment during the same conversation and for a specific number of messages received from the user (the lifespan).
In this case, it would be best if you created a context named something like unknown_counter with a lifespan of 1. In the parameters, you might set val to 1.
The lifespan of 1 would mean that you'll only see this context the next time your webhook is called. If they handle it through some other Intent (ie - you understood them), then the context would just vanish after your fulfillment runs.
But if your input.unknown handler is called again, then you would see the context was there and what the value is. If it doesn't meet the threshold, send the context again (with a lifespan of 1 again), but with the value being incremented by 1. If it did meet the threshold - you'd reply with some other answer and close the connection.
By "send the context", I mean that the context would be included as part of the reply. So instead of sending just a string to sendGoogleResponse() or sendResponse() you would send an object that included a speech property and an outputContexts property. Something like this:
var outputContexts = [
{
name: 'unknown_counter',
lifespan: 1,
parameters: {
'val': counterValue,
}
}
];
sendResponse({
speech: "I'm confused. What did you say?",
outputContexts: outputContexts
});
What I'm trying to do
I'm building a node.js logging tool logminer to learn and expirement about logging/monitoring services. I found an interesting problem that I couldn't solve yet:
The problem
Let's say we want to log the URL and the IP and Location of the Client when an HTTP Request is emitted to see what users are entering into the omnibar (or for whatever reason).
Let's say the URL is logged right away, but for the IP we do an Async Request (maybe we want to get the location based on the IP)
// hypothetical http request handler
function httpRequestHandler(req, res){
// first log (after 0 seconds)
var log = new Log('Request')
if(req.url = 'home'){
// second log (after 0.1 seconds)
log.message('welcome home')
// ... do something
} else {
// second log (after 0.1 seconds);
log.message('the url is', req.url)
asyncFunction(req, function(value){
// third log (after 5 seconds)
log.message('the ip is ', value.ip)
log.message('the location is ', value.location)
// ... do something
})
}
}
The output can very quickly become from this:
(at +0 seconds) User Requests: http://example.com/other
Request
in Request: welcome home
(at +5 seconds) User Requests: http://example.com/
Request
in Request: the url is http://example.com/other
in Request: the ip is 127.0.0.1
in Request: the location is 'San Francisco'
Into this:
4 requests after another with 1 second between page request
(+0 second) User Requests: http://example.com/
(+1 second) User Requests: http://example.com/other <-- this needs 5 -seconds to finish
(+2 second) User Requests: http://example.com/
(+3 second) User Requests: http://example.com/
.
// at +0 second
Request
in Request: welcome home
// at +1 second
Request
in Request: the url is http://example.com/other
// at +2 second
Request
in Request: welcome home
// at +3 second
Request
in Request: welcome home
// at +5 second
in Request: the ip is 127.0.0.1
in Request: the location is 'San Francisco'
As you can see the one with +5 seconds creates confusion especially because it actually looks like this:
Request
in Request: welcome home
in Request: the ip is 127.0.0.1
in Request: the location is 'San Francisco'
And this doesn't make any sense! The 2nd and the 3rd rows are within a different Scope from the 1st one and this makes it seem like they are the same. With many concurent users this is completely unreadable. That's why I think there has to be a way to identify to the origins's of each line, that's why I have an ID in logminer. Including a Scope ID in every row works but it's still very hard to connect the dots and it takes a lots of screen-space as well.
The Question
Now my question is it possible to group things in an asynchronous environment based on their Scope without an ID or using Paging/Filters without a GUI?
Is this a design problem that cannot be solved because of the linear nature of terminals so a GUI is required at this point or am I missing something?
What are the best ways to handle this?
The usual solution to this is to not output your message in pieces that are separated in time because of async results.
Instead, accumulate all the data for your entire message into a string or various variables and then output the whole message at once. This will avoid some part of the message being output and then sometime later (after an async operation) so other part of the message being output.
If you want to make sure you know "when" the event occurred, then record a timestamp from the beginning of the event and include that in the message too.
For example:
// hypothetical http request handler
function httpRequestHandler(req, res){
// first log (after 0 seconds)
var log = new Log('Request');
if(req.url = 'home'){
// second log (after 0.1 seconds)
log.message('welcome home');
// ... do something
} else {
asyncFunction(req, function(value){
log.message('the url is', req.url);
log.message('the ip is ', value.ip);
log.message('the location is ', value.location);
// ... do something
})
}
}
The usual way is to gather all the information and print in stages. The problem becomes when you're impatiently waiting for things to finish and your async program has lots to do and you want some status update.
In that case you can use you can use the nodejs builtin readline to hack the terminal lines and overwrite the old information effectively dividing it into sections. However there is a few libraries out there that already do that, take logger master that does exactly that (find code # github). Depends on how slow your program is.
I'm using a token for my API, the problem is that when the token is invalid (time to live < 0) there's no way to know it, so you go on and fill out a form and only when you submit it you get the message "invalid token" which is really annoyin. My idea is to write a script that checks the token's time to live every 10sec for example and then if it's invalid I can disable the forms for example or display a box to force the user to reload the page. Maybe you guys have better ideas , so please don't hesitate to share.
You can do this in a very simple way, I would guess you have an "expiration time" set on your server side for your token. You can just return this time and have a JS function check that value every x seconds or on every required action (open a pop/form/etc).
Probably when you return the token your json can look something like
{
token:"1234567890",
expire: "1427484624" //timestamp in seconds, easier to compare
}
Then your JS function can be something as simple as:
function isValidToken(token){
cTs=Math.floor(Date.now() / 1000);
return (token>=cTs);
}
and that way you can know very easily.
QUESTION
Using ASP.NET VB and/or JavaScript how can a user be prevented from losing form data when a session expires?
The Problem
Currently when a user is filling out form data for a period longer than the session timeout period all form data is lost on post due to session expiry.
Client side actions such as typing DO NOT reset the session timeout period.
Ideas
I would like to know ways to prevent this problem occurring.
My initial idea is a notification message warning of pending expiry
and an option to reset session timer.
An alternate idea is a way to pass a key press or mouse movement to the server to cause an auto refresh of session timer.
SOLUTION 1 : KEEP SESSION ALIVE
On way of to solve your problem is to keep session alive while the form is opened. I'm sure there many ways to 'keep alive' user's session. For me, I use generic handler and this work fine at least in my requirement.
First, create a generic handler and enter code as below:
Public Class KeepSessionAlive
Implements IHttpHandler, IRequiresSessionState
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Session("KeepSessionAlive") = DateTime.Now
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Make sure your generic handler class implements IRequiresSessionState as above.
Then in you form page, use jQuery.post to post request the above handler at time interval of you choice. For example:
<script type="text/javascript">
$(function () {
setInterval(function () { $.post('<%= ResolveClientUrl("~/KeepSessionAlive.ashx")%>'); }, 10000); ' 10 secs interval
});
</script>
While user is on the form, the POST requests will keep refreshing user's session just like normal page requests and therefore, IIS will keep on reseting the session timeout.
SOLUTION 2 : ALERT USER BEFORE TIMEOUT
Another way is to alert user when session is about to end. This can be achieved simply by using plain javascript alone. I used this method few years back so pardon my scripting.
Create a javascript method :
function sessionTimeout(n) {
setTimeout("alertSessionTimeout()", (n - 1) * 60 * 1000);
}
function alertSessionTimeout() {
var answer = confirm("Your session is about to expire in 1 minute.\n\n
Click 'OK' to extend your session.\n
Click 'Cancel' to terminate you session immediately.");
if (answer == true)
window.location = location.href;
else {
window.top.location = 'logout.aspx';
}
}
On your form page, just enter onload script on your body tag:
<body onload="sessionTimeout(<%=session.Timeout %>)">
So, if your timeout setting is 10 minutes, user will be alerted on the 9th minute. Of course, you might want to change the code when user click OK button. My code above will refresh the page and that definitely not what you want to do, or else, user's data will be lost. You can use the generic handler as in SOLUTION 1 above to reset the session and call sessionTimeout again to reset client side timeout countdown.
In the age of single page apps if you need to work with old school approach, my advise would be to create Ajax request that constantly updates data in your website or just checks for session expiration (probably request itself would prevent that). But if it happens and you receive session expired message you could just show some login popup for user to login without leaving actual page.