I am working on the logout part of my website and I am using JWT for authentication and using cookies to send the JWT for client side.
For logging out I am passing some dummy token value with the same token name so that it over rides the previous token. But when I log out of the portal, I am still able to access my dashboard. There is some glitch in the logout functionality. I guess it is due to the browser cache.
I have few questions regarding Express.
Are there any ways to reload the current page using Express and delete the browser cache while doing so?
I need to disable the browser forward option of chrome once the user is logged out, how can I achieve this using express?
How to redirect the user to his dashboard when he tries to hit '/login' or '/signup' route when he is already logged in? I am using the JWT authentication for login
Thanks in advance
Are there any ways to reload the current page using Express and delete the browser cache while doing so?
The server can't, on its own, tell the browser what to do. The browser has to initiate communications and then act on that communications.
You could have the web page in the browser reload its own page using Javascript with window.location.reload(true) at any time. If you want the web page Javascript to be told when to do this by the server, it could either send regular Ajax calls to the server and, based on the response, decide when to reload the page. Or, it could have a webSocket connection to the server and the server could send the web page some data that, when the web page received that data, it would see that it should reload its page.
We could help you better if you told us what the real problem was here. Web pages can use Javascript and/or webSocket connections to dynamically update themselves rather than just reload all the time. That's a more modern design.
I need to disable the browser forward option of chrome once the user is logged out, how can I achieve this using express?
There's a discussion of disabling the forward button here: HTML5 history disabling forward button. You will probably find this is a brute force approach (it involves getting rid of browser history) and there is likely a much better way to solve whatever real problem you're trying to solve. It also sounds like you may also want to manage browser cache expiration too.
How to redirect the user to his dashboard when he tries to hit '/login' or '/signup' route when he is already logged in? I am using the JWT authentication for login
When you detect a request to '/login' or '/signup' in Express from a user who is already logged in, you just respond with a res.redirect("/dashboard") from your server. FYI, there are lots of questions about whether this is the proper user experience. A user going to '/login' or '/signup' when they are already signed in could have any one of these use cases:
They don't realize they are already signed in or they don't know if they are signed in as the desired user.
They want to sign in as a different user.
They want to create a new account (different from what is currently logged in).
They are trying to figure out how to log out.
You should make sure that blind redirecting (and not taking the user to the page they asked to go to) still makes all these use cases entirely clear. If not, you will just frustrate the user by not taking them where they asked to go.
Related
We have two separate websites which essentially share the same UserAuth data store. We want to provide the user with a link from one to the other without requiring them to login again.
At the moment we currently make a call to the target website's API: /auth/credentials which sets up the session and allows us to then redirect the user, bypassing the need go through the login screen. Great.
As far as I can tell /auth/basic should do exactly the same thing. However, the response from the API call is the same but when redirected the user ends up at the login page.
Have I missed something?
Version: 4.5.8
They are not the same, the BasicAuthProvider enables HTTP’s Basic Access Authentication and is a per Request Auth Provider.
I have a front end HTML website that posts requests to a WebApp hosting online. These html pages run locally on any machine. Thus, they are making cross site requests.
I am thinking of saving cookies and validating these cookies in each request that is sent to my WebApp. Is that the best way to go?
Also, when the user goes back and forth from 1 page to another, (and it is required that he is logged in), do i send a request with cookie from the HTML at the start of the page and redirect him to login page accordingly if his cookie is not valid?
Thanks in advance,
The way you are planning to go about seems alright. Ofcourse you will have to think well about how you are going to save your access tokens. I would use an access token with the IP, username and session expiration date encoded in it.
However just checking on page load would not be the best idea since the result of the check could be spoofed. You should sent this acces token with every request for information so your webapp can decide wether or not to reply with information.
So far I have mainly been using a single asp.net app metaphor where the razor pages are served together with the data from the same app, so I can protect certain controller actions for the ui and data controller actions using the same security.
My new app has a completely independent api web site (using servicestack) and a different asp.net UI app that consumes the api. Right now the two apps sit on the same server, but I want to support the ability for anybody to write a UI app that consumes my data, so the app could sit anywhere and could be a php app all I care.
The new UI uses razor and MVC but it is really a fully client side app, which requests data from the api site.
So, the problem is right there. I am used to automatically redirecting a page from the server side to the login when someone hasn't logged in yet. My UI's server side has no concept of the login situation of the api web site.
The best I can do right now is, at the begging of ANY UI page's load, to do a lightweight ajax call to the api web site, to get the current user info. If it's null, I do a client side document.location.href = .
This works, but has issues, primarily it causes a lot of client side busy ui stuff. An initial version of the UI loads empty (no data), then an awkward redirect to the login page happens. The client side app becomes chatty - every page that loads does an additional call to the api site. The server side redirect is clean because the first page you see is either the UI page that you already have access to or the login page.
My first question is, what is the best practice to do this kind of stuff? My second question is, is there a client side cookie on my UI page that deterministically tells me I am logged in to the api site? I inspected the cookies on a UI page before and after the login that sets the security to the api site and the cookies seem to be the same. My third question is - is there some kind of security actionfilter I can write for my UI mvc site, which somehow magically determines from the cookies of the request, whether the UI is currently logged in to the api site and if it is, it lets the request serve the page, if not, it does the sever side redirect to the login page.
Thanks
Edit:
Scott - thanks so much for the detailed explanation. One clarification - i use mvc only to really serve my client side html. I use all knockoutjs and Ajax calls to servicestack to render the data. My question is really about how to react to Ajax calls that return security exceptions and how to avoid presenting an empty html ui because the user is not logged in. My login page authenticates directly from html to ss bypassing the mvc part. It's not an spa where I can keep a single client side login state that applies to all views of the spa. There are multiple cshtml pages that all need to probe for login in order to not load empty and redirect to the login page...
So the MVC just serves the blank template, that includes the knockout js that will call the API to populate it? I believe this flow shows how your current pages are testing for a session using a lightweight ajax call to the api.
The problem with that approach as you have noted is that it has overhead, and a noticeable delay if there isn't a session.
Solution:
You can't test for the ss-id cookie in your JavaScript client application because of the origin difference. Knowing this cookie exists would give you an indication of whether a user might have a valid session. But seeing you can't access it, you have to work around this. When your login page successfully creates a session by calling the API, you should have the success method create a cookie that denotes that you have a session. Such as a hasSession cookie.
You can check for this existence of this cookie on each page load. It doesn't involve a server trip to verify it. If that cookie has the same expiration policy as the ServiceStack API cookie, then it should stay in sync.
The initial cshtml page state should hide the unpopulated page form contact using CSS, and show a loading indicator until the data is loaded from the API.
When the page first loads it should check if the hasSession cookie exists? If it doesn't then it shouldn't make any API calls, and should redirect immediately login.
How would I know that I can invoke ajax calls and succeed without making a test call?
You should just assume you have a session ss-id cookie if you have the hasSession cookie as you must have logged in successfully to get it. So make you call for the page data. If you get data back from the call and not a 401 exception then populate the form, and display it by altering the CSS.
If you got a 401 redirect to the login screen, and delete the hasSession cookie. The user won't have seen a blank unpopulated form because the CSS prevented this. They get a loading indicator while waiting, a perfectly reasonable state.
The 401 Authorization error should only occur once, and redirect to login, and that shouldn't even happen if your hasSession and the ss-id cookie expiration remain in sync.
I am just confused why you are trying to change the ServiceStack attributes now, subclassing [Authorize]. You shouldn't need to change the behaviour of the API.
Suppose I have the following URL route:
app.post('upvote', function(req, res) {
// make a database a call to increase vote count
});
What can I do to prevent others from opening up a console and sending AJAX POST request on www.mysite.com/upvote? I'd like it so that only www.mysite.com is allowed to make that POST request and no one else.
What can I do to prevent others from opening up a console and sending AJAX POST request
Who is "others"?
If others==users of the site... there is nothing you can do to stop them sending whatever requests they like, using the JavaScript console or any other means. You can't trust the client, so you have to have server-side authorisation: requiring that the user be logged into an account, and registering that the account has upvoted so can't vote again.
If others==admins of other sites (by serving script to their users that causes submissions to your site)... it isn't possible for JavaScript on another site to cause an AJAX POST request, or at least not unless you deliberately opt into that using CORS. But it's quite possible for them to cause a POST by simply creating a <form> pointing to your address and submitting it.
This is a classic Cross Site Request Forgery problem. The widely-accepted solution to XSRF issues is to include a secret token as a parameter in each POST (form or AJAX) submission. That secret token is associated with the logged-in state of the user, either by being stored in the server-side session, or replicated in a client-side cookie. Either way an attacker from another site isn't capable of getting hold of a token that is valid for the logged-in user, so they can't fake the request.
You need XSRF protection on all actions that have a direct effect, whether AJAX or form-based POSTs.
I agree with bobince. others is a very general term.
If others belong to other sites (malicious sites on net).
express has csrf middleware to protect from Cross Site Request
Forgery. You can use it to prevent such a scenario. See the API docs
here.
If others are users of your own site
then that is an authentication issue. Every request must be
checked before serving / executing it. You should implement a user
authentication to prevent this situation. I use passport, and
ensure that user is authenticated before I actually run app.post
handler.
I want to use basic auth to authenticate users. The problem is when a user needs authentication, the browser loads an ugly form where the user should enter their credentials (such is the default on all browsers when they get a basic auth request).
I would like to know how I can bypass this ugly browser default form and instead serve an alternative good looking custom made form.
Thanks in advance
What you're seeing is the HTTP authentication page put out by your web server. Browsers just pass it as is, and it's not customizable. This is why no one really uses them for much other than locking a site down during development or hiding a particular part of a site.
If you want to do something that fits the look and feel of your site, you're going to need to design a page or include your login somewhere on your existing pages.