How to properly decouple Django from an AJAX application? - javascript

I'm using TastyPie and Django to build out my backend for an application that will have browser and mobile (native iOS) clients.
I have been through the TastyPie and Django docs, can authenticate successfully either using the TastyPie resources I set up, or using Djangos built in views. I see a lot of examples on including the CSRF token on the page and grabbing it with your JavaScript, and that works, but I don't understand now to actually determine whether a user is logged in on initial page load (from JavaScript).
Example:
If I want to serve static HTML from a separate, fast web server, and cache my application JavaScript, and only interact with Django through TastyPie views, how do I determine if the user is logged in (and know to render a login form or the app views using JavaScript), and after logout, is there any session information I need to remove from the client browser?
If I were to serve up HTML through Django's template engine, I could render the login form through there appropriately, but that seems not ideal if I want to truly decouple my JavaScript app from Django (and behave like a mobile client).
Edit: I am using Backbone.js, but I don't think that should matter.
UPDATE:
I think I figured it out reading through Django's CSRF documentation again.
If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie().
If I do not want to render Django templates, this reads like I can still use the cookie and pull that into my Backbone or jQuery AJAX methods. I'm not sure if TastyPie ensures the cookie will be sent or how to tie into it.
If I use AJAX to logout, will the cookie automatically be removed or does it become invalid? Are these CSRF tokens unique to each user session? I'll have to test some things tomorrow with it. Is it possible to use Django decorators on TastyPie views?

A mobile client doesn't care if the Javascript comes from Django or any other web server. So go ahead and put all your JavaScript and static HTML on another server.
If you want your mobile app to see if the user is logged in, it should make an AJAX call to your Django backend (where the request is authenticated). The data returned should indicate if the session is active (user is logged in).
Another AJAX call can perform the Django logout function.

Related

Using IdentityServer with ASP.NET + embedded SPA JS framework

I'm sorry if the title is not very clear.
What I have: ASP.NET application with "embedded" Vue.js 2 from this repo: https://github.com/MarkPieszak/aspnetcore-Vue-starter
I already studied Identity Server 4 manuals so I tried hybrid flow with pure ASP.NET and implicit flow using oidc-client with pure JS. Both flows work for me.
But what I want is using JS page that hosted in ASP.NET to get access token and refresh token and store them in ASP.NET. ASP.NET in this case acts as a backend (but not the Resource API!).
Maybe (optional) there is a way to create custom login form. User fill this form, JS sends login and password to ASP.NET backend and than in turn transmits them to Identity Server and retrieves tokens.
I wonder if it is possible to use such a scenario at all and whether it is viable and sufficiently safe.
Any assumptions are welcome!
EDIT:
What I really want is to use Vue just for display my data while using ASP.NET as a backend-client which gathers information from resource API.
Regarding the Login page - no, you can't. Reason - when using OIDC authentication, you are delegating the login functionality to the provider (in your case Identity Server), and it takes care for the login page and etc.
Now regarding your Vue app. Vue is a SPA. SPA's can only use Implicit grant type and by this - they are not being issued a refresh token.
Your solution here is to use the oidc-client-js library with your Vue app. We have this scenario implemented (Vue on top of aspnet core) and it works perfectly fine.

Django: Page Refresh

Here's the view that updates the timestamp of a model in database whenever it's called,
def data(request):
new = Data.objects.filter(user=request.user)
new.update(timestamp=timezone.now())
return HttpResponse('')
This view is related to this URL,
url(r'^go/$', views.data, name='data')
Everything is fine, but how can I call this view & update the database without refreshing the page?
This is a great question as its something that may not seem as logical in django as say node or js based server and client interactions. Let me give a generic response then go more detailed.
Django is a web server. It has some newer functionality that allows it to more easily interact with javascript than it could in the past, but it is normally used in conjunction with a javascript framework. I'll normally build a django app w/ django-rest-framework and reactjs. So my workflow is normally to build the datamodel, serve up the page with compiled js as a static asset, and have those two communicate via a rest-api stood up with DRF.
Specifically to your question, you can simply have your django model communicate with the server via ajax posting to endpoint in your app. An example of a jquery/ajax post is available at this link. The only other thing you will want to look into is supporting csrf which Django discusses in the docs.
Let me know if this helps. If it does but requires specific snippets, let me know.

How to secure web pages with token based authentication?

I'm building a website using ruby on rails which is hosted separately which makes requests to another backend api rails app which is again hosted separately. Obviously i've setup the backend api with token based oauth authentication.
Now since im not dealing with sessions, and it being stateless n all, How can I stop users from accessing certain view pages in my front end web app? For example, I have a consumer/booking page. I don't want the user to access this page without being logged in. But anyone can just enter the url and open any page they want right now.
On user login (ajax call from .js.erb files), im getting the token and storing it in localStorage variable for every future request to the api. I know I should use this token somehow to stop users from access restricted pages. But I just dont know how.
Now as you have stored the token in the localStorage, you will need to pass this token with the request to the page where you want to restrict access and check if the user is authorized to access the page or not.
TL;DR: there is no standard method or library for this; you must implement such functionality as you see fit.
I'm assuming you're using some sort of front end framework like react; if so, then any request to change the current view should be terminated if there is no valid token in localStorage. Check out this post regarding conditional rendering in React; if you're using something else, the methodology is still pretty much the same.
Otherwise, I would build a small script to include in the beginning of every page that checks whether or not there is a valid token and if there isn't, calls window.history.back() to return the user to the previous page.
(Another way of doing it is to intercept every call to a static HTML file on the server, check if there's a token, and send the file if there is. Otherwise, you can send a custom error page or whatever).

laravel: Login form on non Laravel page

I'm building a web application which is accompanied by a small website that uses Jekyll. Reason for this being that the website will almost never change and this way it is able to run fast (pure HTML+CSS and some JavaScript) and semi-independent of the application.
The Jekyll site is placed inside the Laravel public folder and runs fine. As it stands a user that wants to use our application needs to visit the default Laravel auth route to login (/login).
I would like to add a login form on one of my site pages that enables the user to login without visiting the application first.
Of course I tried adding a simple form and posting it to /login (the default Laravel route) but this won't work because Laravel expects a csrf token to be set.
I know Laravel sets a cookie containing the encrypted token but I'm not sure if (and how) I'm able to use this.
Is there any (simple) way of adding a login form to a NON-Laravel page? And is it possible to do so using only HTML & JavaScript (maybe using Ajax)?
You have a couple of options.
1- Cheapest option: disable csrf_token on the login route only. Some will recommend this, others will say you shouldn't. You can research online if you want to go this way or not.
2- Make an ajax GET request to a route that will return you the csrf_token so you can use it in your form. In your Laravel controller you simply return the session token
public function getToken() {
return session()->token();
}
3 - Go the passport road for API requests the same as SPAs. https://laravel.com/docs/5.4/passport

How to manage server user session within client side single page app

I've been fumbling around with different client side technologies, like AngularJS, EmberJS, even trying to use straight JQuery and figure out how to use ReactJS with it. That aside, my goal is to build a single page app using json in between the client and a Java Jersey 2 jax-rs back end api.
I have two stumbling blocks right now. Some info though..I am deploying my app as a WAR file in Jetty. My back end is java based. I am using only jquery in the client side as of now.
My main stumbling block is how to handle login, logout and session management. With an rest API and using ajax, I have login working, including it setting a cookie. My concern however is with a single page app, there is just the one index page, and if the user closes the browser, then reopens it to the index page while the cookie/session is still good, the user should be logged in, not see the outside (not logged in) page. I am unsure how to handle this, whether it be a jsp page, index.html with some templating library, etc. With JSP I can insert some scriplet code (against my better judgment). In the old days I'd include a header that would check for request.getSession().getAttribute("user") and if it was there..the user was logged in and using scriplet if() code I'd display a logged in header, instead of the non-logged in header. But I am in the belief there has got to be a better way to do this with todays client side JS frameworks.
The other stumbling block is the navigation and dynamic aspects. For example, when I was messing around with angular js, it was easy enough to use Welcome {{name}} and within the scope replace name with a json response value for the logged in user. In my current situation, I am not exactly sure how to best go about displaying dynamic bits like this with pure jquery other than using some sort of $("#elem-id").innerHtml="..." code within the response success method of an ajax call. As well, I am not quite sure how to handle navigation to different pages. My logged in site will have some drop down menus or links that will replace the content area with different varying amounts of content.
So first, what are some ways in a SPA to handle user sessions, in the case of a page reload, or close/crash browser restart.. to ensure the user is still logged in and direct them to the right page? Second, what sort of templating and routing/navigation options exist that don't require me to put a huge ton of code in my one index.jsp page?
Thank you.
If you're having a REST API as the back end, then you must have implemented oAuth as an authentication mechanism. That is, when your user logs in, using a username and a password, you exchange that data with an authentication token. This authentication token is sent your server with each and every API call and your backend validates this token before servicing the request. Clear so far?
What you could do is, when you obtain the access token, you can also obtain the access token expiration time from the server and store that data in your client side app. In localStorage maybe? And when your user closes the browser and reopens again, you can first check whether such access token is available (and not expired) before asking the user to log in. This should solve your first problem.
Secondly, if you're looking for a lightweight routing option, I recommend director.
I am building a similar application. OAuth is not mandatory. You can have normal sessions etc by hitting the jersey login endpoint and setting a session and a cookie "keepme" with the session if user wants to be persistently logged in. You can then have a jersey AuthFilter for example check if either there is a cookie with a valid session or an active session and keep the user logged in.
Your frontend application should have no say over this, just communicate with the server and if it doesn't get unauthorized access (from the AuthFilter) then continues otherwise it displays the login page.

Categories

Resources