Download a file that needs authentication token - ajax

I am implementing an AngularJS app with a REST backend (using Spring Boot).
I can currently download a file like this:
<td><a href="/api/datasheets/{{datasheet.id}}/documents/{{document.id}}/download" download>Download</a></td>
Now, I am adding security (using Spring Security) to my application and this now no longer works. The authentication of the AJAX calls works by adding x-auth-token in the HTTP header for each request.
But a simple href does not have the x-auth-token in the header ofcourse. I tried using $http.get() on an ng-click, but that cannot not work.
Is there a simple alternative?

I had similar problem while implementing file downloads in angular. In my case, I was not able to handle blob in safari. What I did was: create a handler which returns a download token valid for say 5 second. Only authenticated user can get this token. Once you have the token, call a different handler which returns the file after validating the token and this handler is publicly accessible. So you don't need to send authentication header while downloading file.
I used itsdangerous library to implement timstamped token.

Related

How to attach jwt token on every page after successful authentication?

I followed this code and implemented the jwt authentication successfully. I am using this authentication in my web application. I am able to get the token on the login page. After that how to attach that token to the header of all the subsequent requests. I stored the token in local storage, but when I navigate to next page after successful login before js loads, the page getting loaded with 401 error.
How should I achieve this?
The problem is you're trying to use token based security with the Web MVC architecture. I did a quick search for any tutorials on how to do it that way and all I was able to find is examples of REST APIs that use token based security.
The reason is that with Spring MVC, each link you click is going to redirect you to a controller endpoint that is going to render the HTML and send it back to the browser. Unless you somehow made every link on your site include the token in a header or perhaps used a cookie to store the token, you'll get a 401 error because the token isn't present in the request.
If you were to use Angular JS (or your favorite front end framework) with a REST backend, you'll be able to use the JS to put whatever you need in the header to make sure the user is authenticated and has access to the resource. There a lot of example projects out there that demonstrate how to do this.
Disclaimer I haven't been able to find a reliable source that definitively says that token based security is for REST only. I'm basing this on experience and readily what I see out there in terms of tutorials and how to articles.
Ich totally agree to the answer from blur0224, you have to set the token in the request header of every link on your pages. I don't know how to achieve this. Furthermore I think that JWT token based authentication is not the right way for MVC based app. I would use it in SPAs build with frameworks like Angularjs.
Why don't you use the 'standard' Spring authentication?

Spring Security - REST API - token vs. cookie

I have written a REST- API in Java and I have secured this API with Spring Security. The procedure is like this:
Frontend invokes /login RestService in Backend
Backend gives back token to frontend
at each REST- API Backend invokation the token has to be placed in header
This works fine, but I have read that it is also possible (with Node.JS/Passport.js/Express.js) that the session object with the cookie inside can be transfered out of the box without any custom code.
My question now would be if there is a better approach so that the frontend/client do not need to set the token into the header all the time for any request.
Usually token based authentication has advantages over cookie based.
You can achieve this using middle-ware layer
Here is a good Post - https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
Server side, I usually first check in the headers if there is an auth token. If not, I then check in the cookies as a fallback.
If you want to use cookies, then at your step 2, you need to add a Set-Cookie header to the response, so that browsers know they must store a cookie. Once done, no need to add a header client-side, since browsers will send cookies each request. You'll need to add a CSRF protection though (here is a good example).

Angular CSRF token + ruby api

I'm currently running into a lot of issues with the CSRF token.
Our current setup is a Ruby API and an Angular front-end, both live on a different domain.
The Ruby back-end solely serves as an API for the front-end.
I've spend a lot of time researching this problem, but I can't find a proper solution.
So far the solutions I've found are:
Generate the token and insert it into the DOM (Different domains, so can't do that)
Let the API return the CSRF token on a GET request (Doesn't seem to work, and it's not a good solution since I don't want to make an extra request just to get the token)
So I'm rather stuck here and not sure how to continue.
Is the current implementation just not working? How do other people create an API with oauth without running into this issue?
Not sure if this will help but here is a sample of a simple todo api in ruby with angular as frontend, and i am using token for authentication generated after the user fills username and password.
https://github.com/sirfilip/todoapi/blob/master/app.rb (the api written in sinatra and sequel)
https://github.com/sirfilip/todoapiclient/blob/master/public/js/angular-todoapi-plugin.js (angular client api service that is used for communication with the api)
TL;DR: Secure your rails API with the doorkeeper gem.
This SO post seems to be the accepted answer when your api and client exist on the same domain.
In the post they outline the angularJS docs http://docs.angularjs.org/api/ng.$http :
Since only JavaScript that runs on your domain could read the cookie,
your server can be assured that the XHR came from JavaScript running
on your domain.
To take advantage of this (CSRF Protection), your server needs to set
a token in a JavaScript readable session cookie called XSRF-TOKEN on
first HTTP GET request. On subsequent non-GET requests the server can
verify that the cookie matches X-XSRF-TOKEN HTTP header
It seems that the security of storing and transferring the XSRF-TOKEN session cookie in this way hinges on having your api and your front-end be in the same domain. Since this is not the case, you may have to implement another form of authorization for any given client session, like OAUTH. I'd recommend taking a look at the doorkeeper gem. The gem will give you the ability to interact with your api as if you were any other client.

Spring template connect to OpenSSO/JAAS secure endpoint

I'm trying to access a REST service via a server-to-server GET request that is secured by OpenSSO/Spring Security and am unable to. It's like my Spring Rest Template client is not stateful to hold the cookies it should as I get redirected through the authentication workflow.
When doing this with a browser, the initial request is redirected to OpenSSO, I'm challenged for my cert (PKI), I present it, get a response with my authentication cookie header. Then I am redirected back to my original destination, I present my auth cookie in the request header and I'm on my way.
This isn't happening in my server-to-server invocations.
I've searched for quite a while now and can't seem to find any solutions that hold onto this state across redirects!
Following the link in zagyi's comment may have worked, but I spent some more time and found the following solution, which does not involve overriding anything:
To handle the authentication cookie in the REST controller, you have to explicitly tell it to accept cookies. Before handling the call, add the following line of code:
CookieHandler.setDefault(new cookieManager(null, CookiePolicy.ACCEPT_ALL));

Securing jQuery calls to Spring MVC REST API using Spring Security

I'm developing a REST JSON API with the Spring MVC Framework. I want to serve a single HTML application to the user and the whole communication between server and client is done with JSON format. So the client single HTML application uses jQuery to send AJAX calls to the server.
My big problem is to find the right way to do integrate a proper security technique. I read a lot about basic, digest or form based authentication via Spring Security, but I don't think this is the right way. I want to get JSON responses if the user isn't logged in and I don't want to send a jsessionid with each request.
Could you please tell me the right way or the best-practice how to authenticate user by performing AJAX requests? Maybe it's OAuth 2-legged? (don't have much clue of OAuth)
If you don't want to store auth information in server-side session (and use JSESSIONID in cookies/urls) you may send auth info with every ajax request using BASIC auth header (created in JS).
I've never used 2-legged oauth, so I won't comment about it.
edit: typo

Resources