Whenever the window location changes API calls called are canceled by the browser.
I am firing analytics events on-click of a button which also takes to a subdomain and refreshes the page, so there is a race condition now. Sometimes the event is resolved and sometimes it is canceled by the browser.
Tried to resolve it using service worker. Not getting callbacks in sync for canceled events
the possible workaround I found are as follows
wait for the event to be resolved before redirecting
store in local storage and fire on returning back
pass the event to be fired as query param to the subdomain and fire it there
Is there a better solution for this ?
Define a new Analytics component at global level that is not impacted with route changes.
Add a generic logic in Analytics component to receive data and hit
API.
Now location change of any component / destroy event will not impact cancelling of API call.
just the event need to be hit rest Analytics component will take care.
<Provider> -- redux store -->
**<Analytics >** - analytics logic , use redux to notify about event or other logic
<App></App> - has route and all other logic
</provider>
I'm building a system where a user is scored on the percentage of a video they have watched. If they leave/refresh / close the page I need to post their scoring data to an API endpoint.
I use the beforeunload event to fire the action when the user changes their location.
The action is handled using redux-saga.
I can see the action is being dispatched but it seems that the window closes before the call is made to the endpoint (chrome dev tools shows the call but with a status of canceled).
Is there any way to reliably ensure that the call is made to the endpoint? Surely there are a lot of sites (most notably e-learning ones) that handle this kind of behavior consistently, so there must be a solution.
Component:
componentDidMount() {
window.addEventListener('beforeunload', this.onUnload);
}
componentWillUnmount() {
window.removeEventListener('beforeunload', this.onUnload);
}
onUnload() {
this.props.postScore(params);
}
Any help is greatly appreciated.
If redux store is your app state, which is about to be go kaput, this is a rare time you have to bypass the store.
Just synchronously read the store and directly post to the api.
But even this is only saving the progress when the browser fires "unload".
If the page becomes unresponsive, or the browser simply crashes, the handler and api call will never execute.
A simple tactic would be to continually update progress every x seconds
i've tried with the conn.status() but as soon as the call starts "ringing" the status change to "open"
i've tried with the conn.accept(function(conn){ // do something }) but doesn't appear to work.
I want to put a timer for the call duration, but now i'm only available to start it when the call starts rining.
Twilio developer evangelist here.
The JS SDK doesn't show you the call progress events I'm afraid.
However, you can subscribe to call progress events via webhooks. In your TwiML that sets up the call, you can supply a URL as the statusCallback attribute on the <Number> element. You will then get webhook callbacks to that URL when the call moves through the various events, including initiated, ringing, answered and completed.
If you set up a real time connection to your front end using server sent events or a websocket, you can then display your timer when the correct webhook arrives.
Let me know if that helps at all.
I am using Thinktecture AuthorizationServer (AS) and it is working great.
I would like to write a native javascript single page app which can call a WebAPI directly, however implicit flow does not provide a refresh token.
If an AJAX call is made, if the token has expired the API will send a redirect to the login page, since the data is using dynamic popups it will this will interrupt the user.
How does Facebook or Stackoverflow do this and still allow the javascript running on the page to call the APIs?
Proposed Solution
Does the below scenario sound sensible (assuming this can be done with iframes):
My SPA directs me to the AS and I obtain a token by Implicit Flow. Within AS I click allow Read data scope, and click Remember decision, then Allow button.
Since I have clicked Remember decision button, whenever I hit AS for a token, a new token is passed back automatically without me needing to sign in ( I can see FedAuth cookie which is remembering my decision and believe this is enabling this to just work).
With my SPA (untrusted app), I don't have a refresh-token only an access token. So instead I:
Ensure user has logged in and clicked remember decision (otherwise iframe wont work)
Call WebAPI, if 401 response try and get a new token by the below steps...
Have a hidden iframe on the page, which I will set the URL to get a new access-token from the Authorisation Server.
Get the new token from the iframe's hash-fragment, then store this in the SPA and use for all future WebAPI requests.
I guess I would still be in trouble if the FedAuth cookie is stolen.
Any standard or recommended way for the above scenario?
I understand that your problem is that the user will experience an interruption when the access token has expired, by a redirection to the login page of the authorization server. But I don't think you can and should get around this, at least, when using the implicit grant.
As I'm sure you already know, the implicit grant should be used by consumers that can NOT keep their credentials secret. Because of this, the access token that is issued by an authorization server should have a limited ttl. For instance google invalidates their access token in 3600 sec. Of course you can increase the ttl, but it should never become a long lived token.
Also something to note is that in my opinion the user interruption is very minimal, i.e if implemented correctly, the user will only have to authenticate once with the authorization server. After doing that (for example the first time when also authorizing the application access to whatever resources the user controls) a session will be established (either cookie- or token based) and when the access token of the consumer (web app using implicit grant) expires, the user will be notified that the token has expired and re authentication with the authorization server is required. But because a session already has been established, the user will be immediately redirected back to the web app.
If however this is not what you want, you should, in my opinion, consider using the authorization code grant, instead of doing complicated stuff with iframes.
In that case you need a server side web application because then you can keep your credentials secret and use refresh tokens.
Sounds like you need to queue requests in the event that an access token expires. This is more or less how Facebook and Google do it. A simple way using Angular would be to add a HTTP Interceptor and check for HTTP401 responses. If one is returned, you re-authenticate and queue any requests that come in after until the authentication request has completed (i.e. a promise). Once that's done, you can then process the outstanding queue with the newly returned access token from your authentication request using your refresh token.
Happy Coding.
Not sure if I understand your question but,
I would like to write a native javascript single page app which can call a WebAPI directly, however implicit flow does not provide a refresh token.
Summarize facts,
refresh token is sometimes used to be a part of A: Authorization Grant
https://www.rfc-editor.org/rfc/rfc6749#section-1.5
and as you said in implicit flow you dont get back refresh token, but only in Authorization Grant part
https://www.rfc-editor.org/rfc/rfc6749#section-4.2.2
so you can get back refresh token when issuing access token (refresh tokens are always optional)
https://www.rfc-editor.org/rfc/rfc6749#section-5.1
With my SPA (untrusted app), I don't have a refresh-token only an
access token. So instead I:
Ensure user has logged in and clicked remember decision (otherwise
iframe wont work)
Call WebAPI, if 401 response try and get a new
token by the below steps...
Have a hidden iframe on the page, which
I will set the URL to get a new access-token from the Authorisation
Server.
Get the new token from the iframe's hash-fragment, then
store this in the SPA and use for all future WebAPI requests.
SPA(you) have no idea if user selected remember decision. Its in AS direction and should be complete blackbox. Skip this step.
You can try to use access token and wait for result, always.
If access token has expired and you dont have refresh token, you still can create hidden iframe and and try to get new access token.
Lets assume your AS provide option to remember decision and wont change it in future, then: your iframe will get new access token without user interaction, then you will get result back in some unknown time limit.
Result can be checked by setInterval for read specific cookie or iframe postmessage.
If you dont get back data in time limit, then one from following scenarios occured:
lag, AS is slow, connection is slow or time limit is too tight
user didnt select remember decision
In this case:
show iframe with login
I consider scenario above as good practise if AS doesnt provide refresh tokens, but I also guess every AS like that wont provide remember option as well.
StackOverflow <---> Google scenario (I can only guess)
User login, authorization request occured
User logs in, SO gets access token
SO tries to use access token
SO gets back result + refresh token
SO saves refresh token
SO has permanent access to users Google account
In Google o-Auth , the access token will only be valid for 1 hour, so you need to programmatically update your access token in each one hour, simple you can create web api to do so,you need to have a refresh token, and also that refresh token will not be expired , using c# code, I have done this.
if (dateTimeDiff > 55)
{
var request = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v3/token");
var postData = "refresh_token=your refresh token";
postData += "&client_id=your client id";
postData += "&client_secret=your client secrent";
postData += "&grant_type=refresh_token";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
request.UseDefaultCredentials = true;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
you need to save the last updated date time of the access token somewhere(say in database), so that , whenever you have to make a request , so you can subtract that with current date time , if it is more than 60 minutes , you need to call the webapi to get new token .
I'm doing a javascript single-page app which allows people to log in, either via twitter or (for some use cases) anonymously.
A very important thing to figure out was how to let them reload the page -- this shouldn't force them to log back in!
I figured this out pretty quickly for the twitter login, and so it uses cookie-stored information to log back in (specifically, the user_id, oauth_token and oauth_token_secret).
However, I can't seem to make this work with the anonymous login facility.
I tried:
auth.login("anonymous", {
user_id: #get("userId"),
firebase_auth_token: #get("firebaseAuthToken")
});
but it doesn't work... I get a new anonymous user ID. I want to keep the same one for the duration of the user's browser session.
And yeah, I tried both user_id and id, firebaseAuthToken and firebase_auth_token.
Thanks!
By default, sessions are created any time you successfully log in a user, and last up until the session expiration time configured under the 'Auth' tab in Forge. This built-in sessioning applies to all Simple Login authentication types, and is automatic as long as local storage and cookies are available.
To resume a session, simply instantiate the FirebaseSimpleLogin object with a Firebase reference and callback. If a local session exists, the callback will be invoked with the same payload you would see if you had just logged the user in for the first time. Invoking the login method will always generate a brand new auth. flow regardless of current user authentication state or session.
Note that in anonymous auth, once a user session expires it cannot be recovered. This may change in the future or some additional functionality may be added to enable it, but it is currently only logged-in to once per user id.