AngularJs logout action - javascript

I have implemented authentication, based on jwt tokens in my app. But I have some trouble with logout action. When I press logout, I simply clear my local storage from access_token value.
Let's imagine, that user opened three browser tabs with my app. One of them is unprotected and there is some unsaved user input (tab1). Other tabs (tab2,tab3) have protected resources. When user press logout button on tab3, I want to redirect him on login page (because he is on protected tab). Also I want to redirect him on login page when he makes tab2 active, because it also has unprotected resources. But I do not want to redirect him from tab1 (because it is unprotected), and I do not want to renew it, because user will loose his input. How can I implement this?

TL;DR: In order to achieve this, you'll need to implement WebSockets.
A standard single page application written in angular works over HTTP, which, according to wikipedia:
HTTP functions as a request–response protocol in the client–server computing model. A web browser, for example, may be the client and an application running on a computer hosting a web site may be the server. The client submits an HTTP request message to the server. The server, which provides resources such as HTML files and other content, or performs other functions on behalf of the client, returns a response message to the client. The response contains completion status information about the request and may also contain requested content in its message body.
Request-response is one of the basic methods of communication between computers. One computer sends a request, the other one sends back a response - it's just so simple (on the surface. The underlying technology handles a lot of stuff, but it's out of the scope in this answer).
But, as with any (simple) technology, it has its constraints. A request contains information about its sender. Upon receiving a request, the server handles it and sends back a response to the entity that issued the request.
Now let's consider your scenario
You have 3 opened tabs with your app and 2 problems here:
Suppose you log out on tab 3. Because you use JWT token authentication (actually any token authentication behaves similarly), the proper log out action consists of just removing the token from your local storage in the SPA project instance on the tab 3. The application state of the project in tab 1 and 2 does not change in this case. Also, logging out doesn't require any request to the server, thus no response is send that would somehow notify of the changed authentication status of the user.
Even if you'll send a request to the server to notify it about the log out action on the tab 3, the server does not know about other 2 opened tabs, because the request holds information only about the entity that issued the request, thus it will just send a response to the third tab.
Entering WebSockets
Note: Before reading on, I want to mention that I don't have practical experience with websockets, so you can take everything I write with a grain of salt.
Again, according to wikipedia (highlights are mine):
The WebSocket protocol makes more interaction between a browser and a website possible, facilitating the real-time data transfer from and to the server. This is made possible by providing a standardized way for the server to send content to the browser without being solicited by the client, and allowing for messages to be passed back and forth while keeping the connection open. In this way a two-way (bi-directional) ongoing conversation can take place between a browser and the server.
WebSockets provides a full-duplex communication channel, meaning that the server doesn't only provide responses to client's request, but also initiate data transmission. This solves the second problem mentioned above leaving you the task to solve the first problem - notifying the server about the logging out of the user. Once the server knows that the user has logged out, it communicates this fact to all other clients, thus synchronizing the state of your single page application among all tabs.
Angular doesn't provide websockets support out of the box, but there are modules that give you the possibility to use them in your project. Just google it.
Hope this helps you.

Related

Best way to make a request to external web service

So, I have this web application that shows network products for a specific network. The web server is not inside the network, so in order to show the visitor what network services he or she can order, I need to identify their computer inside the network.
So, I've been doing this with an iframe, which loads a specific in-network URL provided by my clients. This in-network URL will identify the visiting browser and then redirect it (inside the iframe) to a resource on my web service, with attached identification details.
For identification to occur, the in-network web server needs to receive a HTTP request from the visitor, but is this really the best way to handle this? Ajax cross domain is a bit of a mess as far as I'm aware, but I think iframe cross domain is equally shaky, or?
How would you solve this? The chain of events needs to be:
visitor visits my.web.com/services
visitor is sent to client.network.com/identify
Which redirects to my.web.com/identifier?id=XXYY
Now I can set a cookie for my.web.com on the user browser that their id is "XXYY" (or update member profile if logged in). Obviously this request needs to be asynchronous since the in-network web server may be slow to respond, so just a normal redirect is off the table.

How does websockets deal with for two tabs of the same browser

I have
1 PHP server (serving http request) and
1 node.js publishing updated data messages (with websockets to each connection).
The php server setup its cookie. In one browser, this cookie is available across all tabs.
When a browser has 2 tabs opened to the domain, there is only one cookie identifying the browser, but 1 message of updated data must be sent to each tabs.
What is the traditional way to distinguish between tabs ?
Should I use another cookie (managed by node.js) to distinguish between each browser tabs ?
Turning my comment into an answer...
There's a separate websocket for each tab. That's how you distinguish different tabs from each other. If you're keeping separate state per tab in your server and you want to allow multiple connections by the same user, then you have to keep the state per websocket connection (you can use the websocket id), not per user.
You don't need to create a separate cookie per tab because the websocket itself already serves as the unique id for each tab.
You haven't said if your app wants identical state in all tabs or if each tab has different state and you would handle things a bit differently on the server side based on the desire. If you want all tabs to receive the same data, then whenever you want to send data to a client, you have to find all websockets that are associated with a given user and send the same data to them.
If you want each tab to behave independently, then you just keep server-side state per websocket and send a response only to the websocket that the response belongs to, not all websockets associated with that user.
As with nearly all questions here on SO, it's a lot easier to answer more specifically if you tell us more about what you're actually doing rather than having a theoretical conversation. For example, if we knew how your app was supposed to work with different tabs, then we'd know which behavior path to follow.

AngularJS SPA and RestfulAPI Server Security

Quick background:
Full Javascript SPA AngularJS client that talks to a REstful API server. I am trying to work out the best authentication for the API Server. The client will have roles and I am not concerned if the user can see areas of the client they aren't allowed because the server should be air tight.
Authentication flow:
User Posts Username and Password to let's say /api/authenticate
If a user the server generates api token ( sha hash of fields or md5) and some other meta data determining roles to pass back in 1) post reply.
The token is stored in a session cookie (no exp, http only, ssl)
Each request after authentication takes the token in the cookie and verifies this is the user.
SSL user on server.
Questions:
Is this the best way to secure the server?
Do I need to worry about replay attacks w/ SSL? If so best way to manage this?
I tried to think of a way to do HMAC security with AngularJS but I can't store a private key on a javascript client.
I initially went the http authentication method but sending the username and password each request seems odd.
Any suggestions or examples would be appreciated.
I'm currently working on a similar situation using angularjs+node as a REST API, authenticating with HMAC.
I'm in the middle of working on this though, so my tune may change at any point. Here's what I have though. Anyone willing to poke holes in this, i welcome that as well:
User authenticates, username and password over https
Server (in my case node.js+express) sends back a temporary universal private key to authenticated users. This key is what the user will use to sign HMACs client side and is stored in LocalStorage on the browser, not a cookie (since we don't want it going back and forth on each request).
The key is stored in nodejs memory and regenerates every six hours, keeping record of the last key generated. For 10 seconds after the key changes, the server actually generates two HMACs; one with the new key, one with the old key. That way requests that are made while the key changed are still valid. If the key changed, the server sends the new one back to the client so its can flash it in LocalStorage. The key is a SHA256 of a UUID generated with node-uuid, hashed with crypto. And after typing this out, i realize this may not scale well, but anyway ...
The key is then stored in LocalStorage on the browser (the app actually spits out a your-browser-is-too-old page if LocalStorage is not supported before you can even try to login).
Then all requests beyond the initial authentication send three custom headers:
Auth-Signature: HMAC of username+time+request.body (in my case request.body is a JSON.stringify()'d representation of the request vars) signed with the locally stored key
Auth-Username: the username
X-Microtime: A unix timestamp of when the client generated its HMAC
The server then checks the X-Microtime header, and if the gap between X-Microtime and now is greater than 10 seconds, drop the request as a potential replay attack and throw back a 401.
Then the server generates is own HMAC using the same sequence as the client, Auth-Username+X-Microtime+req.body using the 6-hour private key in node memory.
If HMACs are identical, trust the request, if not, 401. And we have the Auth-Username header if we need to deal with anything user specific on the API.
All of this communication is intended to happen over HTTPS obviously.
Edit:
The key would have to be returned to the client after each successful request to keep the client up to date with the dynamic key. This is problematic since it does the same thing that a cookie does basically.
You could make the key static and never changing, but that seems less secure because the key would never expire. You could also assign a key per user, that gets returned to the client on login, but then you still have to do user lookups on each request anyway, might as well just use basic auth at that point.
Edit #2
So, after doing some testing of my own, i've decided to go with a backend proxy to my REST API still using HMAC.
Angular connects to same-domain backend, the backend runs the HMAC procedure from above, private key stored on this proxy. Having this on same domain allows us to block cors.
On successful auth, angular just gets a flag, and we store logged in state in LocalStorage. No keys, but something that identifies the user and is ok to be made public. For me, the presence of this stored value is what determines if the user is logged in. We remove the localStorage when they logout or we decide to invalidate their "session".
Subsequent calls from angular to same domain proxy contain user header. The proxy checks for user header (which can only be set by us because we've blocked cross-site access), returns 401 if not set, otherwise just forwards the request through to the API, but HMAC'd like above. API passes response back to proxy and thus back to angular.
This allows us to keep private bits out of the front end, while still allowing us to build an API that can authenticate quickly without DB calls on every request, and remain state-less. It also allows our API to serve other interfaces like a native mobile app. Mobile apps would just be bundled with the private key and run the HMAC sequence for each of their requests.

What's the best way to resume an HTTP POST?

I am trying to handle following case, I am new to web-app world so please pardon my ignorance (if any):
Assumptions/Constraints:
I don't have any control over the web-app code base whatsoever.
Authentication is being handled at http proxy level.
Scenario:
User has authenticated with a web-app using SAML and has been accessing the web-app for quite some time.
His authentication token (or cookie) expires.
He submits a form (HTTP POST).
Server needs to perform the authentication workflow again, which requires a HTTP redirect.
Now, the requirement is to somehow resubmit the original HTTP POST, after completing the authentication workflow, automatically for the user. A couple of options I could think of are:
Use javascript injection to store the POST state in browser's sessionStorage and rePOST things after completing the auth workflow. But I couldn't figure how would this work if the original POST was done using XMLHttpRequest ???
Store POST state on server (or proxy) side and do an internal rePOST and return the result to the browser.
Are there any other options ??? It'd be great if we could avoid saving state on server side. How do people usually handle such scenarios?
TIA,
praddy
Generally the second approach is implemented.
You send the request to the server running the application, it preserves the POST data (actually the again doing the authentication does this), sends you to authenticate, redirects you back and POSTs the data again. This feature may already be present in your authentication infrastructure and just needs to be enabled, but that of course depends what you are running.
This feature is sometimes also referred to 'POST data preservation'.

Authenticated JavaScript AJAX Requests

I'm developing a mobile application that requires users to login, and then they can use the application. The application will submit data to the server upon submission. Here's my question: if I want the application to be available to users even when there is no internet connection, I will allow them to bypass the login screen and use the application without logging in. However, once an internet connection is available, and the application knows that, and tries to submit the information to the server (through jQuery AJAX), how do I validate the request? It seems like if someone really wanted to, they could set up their own web page and submit their own [fictitious] data to my server using the same AJAX URL and data format that my application is using. What would stop them? How do I ensure on my server side (receiving end of the AJAX request) that the only data coming in belongs to my application, and not someone who is simply mimicking my AJAX requests?
The only thing I can think of is when the application detects that the internet connection is back, immediately show the user the login screen, and then use an expiring cookie/ticket to validate the AJAX requests.
Any advice? Thanks!

Categories

Resources