How to pass the session cookie to Play via Uploadify? - java

I'm trying to use Uploadify, an Ajax file uploader, with Play Framework.
Uploadify uses a Flash object to talk to the server ... so by default it will not use the Play cookies. I want to authenticate my user correctly, so I need to get uploadify to send some cookies over itself.
Does anyone has a working example of the two working together, or, failing that, some pointers?

uploadify has an option called scriptData which you could used to send your authentityToken:
#{authenticityToken /}
<script>
var token = $('#input[name=authenticityToken]').val();
$('#file_upload').uploadify({
'uploader' : '/uploadify/uploadify.swf',
'script' : '/uploadify/uploadify.php',
'cancelImg' : '/uploadify/cancel.png',
'folder' : '/uploads',
'scriptData' : {'authenticyToken': token}
});
</script>

Well, if you're using httpOnly configuration (and you should!), then it's impossible to pass Play's native auth cookie to uploadify.
What I did was:
1. Not secure the Images controller with #With(Secure.class), but instead use a before method:
#Before(unless = "uploadPost")
public static void before() throws Throwable {
Secure.checkAccess();
}
2. Pass along two parameters from the controller that renders the page hosting the uploadify plugin: userId, and signedUserId
String userIdSignature = Crypto.sign(Long.toString(user.id));
render(..., user.id, userIdSignature);
3. Pass these two parameters to uploadify, and to the uploadPost method
public static void uploadPost(Upload upload, long userId, String userIdSignature) {
assertEquals(userIdSignature, Crypto.sign(Long.toString(userId)),
"Failed to authenticate user ID " + userId);
If for some reason you don't want the client to know its user ID, an alternative to signing is encrypting the user id.
Note that you are still exposed to replay attacks using this method, but I believe this is a general problem with Play (I could be mistaken about this). You can add an expiration date to the signature to limit the damage.

Related

Facebook - How to Pragmatically post to facebook page? | Refreshing Access Token

So I have been stuck on this for a while, I'm trying to post from my web application (Spring boot) AUTOMATICALLY without any user interaction, NO POPUP LOGIN VIA FB OR AUTHORIZE FB ACTION nothing.
My application itself should do this. I achieved this by using :
public String postStatusOnPage(String message) {
if (socialFacebookConfiguration.isEnableWorkaroundAutoPost()) {
String id = facebook.pageOperations().post(new PagePostData(socialFacebookConfiguration.getPageId()).message(message));
log.log(Level.INFO, "Created New post id: " + id);
return id;
} else {
return null;
}
}
This works all ok. Bud , there is an issue and i dont know if my solution is really a right way to do it.
Im getting facebook The authentication has expired.
My access token that i have defined in application.properties
workaround.social.facebook.accessToken=...
Will expire. I dont know about how to refresh it. I have cheated a bit by using
https://developers.facebook.com/tools/explorer/
Question :
So How do I automatically get new access token? Is this a correct way of doing this OR is there better way? Is there a possibility to have access token that never expires?
Side note : MY application has OAuth2 login via google, bud I want application itself to do this, without any user being logged in(administrator as a human).
There is another token that i have , its app token
Bud this one does not work for posting to my page. On invocation throws :
faceboook An active access token must be used to query information
about the current user.
An App Token does not have any relation to a User or Page. You MUST use a Page Token to post to your Page, and you can use an Extended Page Token for that.
More information about Tokens: https://developers.facebook.com/docs/facebook-login/access-tokens/

Best practices for managing auth token

I am writing a REST client in Java using the HttpCLient , the REST API that I access needs an auth token for every REST action. This token is valid for 24 hours.
The way I am handling this now is calling a "getAuth()" method everytime I need to make a REST call which seems like an overhead on the auth server.
How can I conveniently store this auth token and manage its life cycle?
Are there any documented best practices?
I thought of the following solution
public class MySession {
String user;
String pass;
public MySession(String user, String pass) {
this.user = user;
this.pass = pass;
}
public getAuth() {
//user user, pass to get auth token
}
}
and then pass the sessions object to any class that nees the token. If the token is expired, just call this method again
For brevity I'll assuming you're calling an endpoint that you can't change. How you should implement will heavily depend on whether the token is app or user based (one token for all users on a shared app instance or one token per user).
If it's one auth token for the entire app:
Store it in memory along with a time-to-live timestamp (or alternatively catch the token expired error, request a new token and retry the original request), refresh it if it doesn't exist/is expired
If you're concerned about re-requesting API tokens after an application restart also store it in the database and load it at startup if it exists
If it's one token per user:
Store it in your user session, it's exactly what sessions are used for, if you're authing users then they'll have a session and the overhead is already there
If you don't want to re-request a token everytime they login store their current token in the DB and and load it into their session when they login
I'm assuming you are using OAuth for authorization. Whether you are using JWT or other tokens is irrelevant to this situation.
When performing authorization you will be issued an access_token with an expiration and, depending on the grant type you are requesting (Client credentials, Authorization code, Implicit, Resource owner), a refresh_token.
The client should keep the access_token and the expiration. The refresh_token, if issued, must be kept secret (beware of using the correct grant for your use case).
In subsequent calls, your client should not request new tokens on each call, it should use the stored access_token.
Once the API starts returning 401 Unauthorized, the access_token has probably expired. Your client should try to refresh the access_token using the refresh_token if you got one.
If you have no refresh_token or the refresh request also failed, because the refresh_token is no longer valid, you can perform a new authorization flow.
You can use the expiration time as a clue to know when to get a new access_token either through refresh or through a new full authorization flow. This will avoid the 401 Unauthorized. In any case, your client should have a fall back policy when this response is received after having used a valid access_token for some calls.
You can create a manager and store the auth-cookie during login in thread local like the code below. You can get the cookie from getAuth() as long as the thread lives.
public class Manager {
private static final ThreadLocal<String> SECURITY_CONTEXT = new ThreadLocal<>();
public static void setAuth(String auth) {
SECURITY_CONTEXT.set(auth);
}
public static String getAuth() {
return SECURITY_CONTEXT.get();
}
public static void clear(){
SECURITY_CONTEXT.remove();
}
}
I suggest you to use the following scenario:
1) First, call auth(username, password) rest api to get the auth token.
If the given credentials are okay then just send back the auth cookie to the client with HTTP 200 response code.
2) Then, you can call protected rest apis. You need to send auth cookie with your request each time.
3) Servlet filter (or something similar) checks each incoming request and validates the token. If the token is valid then the request goes forward to the rest method, if not you need to generate an http 401/403 response.
I suggest you not to write your own authentication layer. Instead of install and use an existing one. I suggest you OpenAM. It is a superb open source access management system.
I also suggest you not to open session on the server side for authentication purpose. If you have 10 clients then 10 sessions needs to be managed by server. It is not a big issue. But if you have 100 or 1000 or millions different clients than you need more memory to store sessions on the server.
If you are worried about too many hits to the database, then i'm assuming there is a lot of web activity.
I would not recommend using Session in your case, but rather store the token in a cookie on the client.
In a high traffic environment(which i'm assuming yours is), the use of Session can consume a lot of server memory, and scalability can be a concern as well, having to keep sessions in sync within a cluster.
As #Cássio Mazzochi Molin also mentioned, you can use an in-memory cache to store any user specific data and tokens. This will reduce the hits to the database, and also allow you to scale the application easier, when the need arises.
The de-facto standard is not implementing your own solution (basic rule in security: don't implement your own stuff!), but use the de-facto standard solution, namely JSON Web Tokens.
Documentation on the site, but the basic idea is, that you only need to store one value (the server's private key), and then you can verify every claim, issued originally by the server (which will in your case contain an expiry time).
You should use JsonWebToken (JWT in short) for this kind of stuff. JWT has build in support to set the expiration date. There are plenty of libraries to use this method and you can read more here
There are currenlty 4 java implementations and all of them can check if the token is still valid (exp check)
So if I'm understanding correctly you are using the same token for all of your requests (which means as long as your app is up and running and you refreshing the tokens, you should be ok. I literally had the same problem and this is how I've resolved it. I have a singleton class, which is initialized at the app start for once and refreshes the token when its invalidated. I'm using C#, Asp.NET MVC5 and AutoFac for DI, but I'm sure you can do the same with Java and Spring.
Updating property of a singleton with Thread Safety
Use json web tokens , to exchange information between two clients. The token will only alive for the 24 hours period, after that time all consequent calls in the header will be rejected.
Auth Token for each request is correct approach, Consider auth server scaling for performance issue.
On first successful authentication (username and password), generate private public keypair. Store private key as Session Security Token (SST) and send public key as Public Security Client Key (PSCK) to client
In all request other than login (or authentication) client will send PSCK to protect theft of username and password and server can verify PSCK for expiry internally at regular intervals saving processing time.
If system is having performance issue on authentication side, setup seperate auth server with scalability.
No token or password to be cached, exchanged unencrypted and send outside security zone. Do not post using URL parameters.

How to access Bitbucket API from a Java Desktop App via Jersey+Oltu?

As the title states it, I want to access the bitbucket API from a native Java Desktop Application. Bitbucket requires Applications to use OAuth2, and for that I found that Oltu should do the job.
However, my knowledge of OAuth is very limited and so I am stuck at a very early point. Here is what I did so far:
Step 1: I registered an OAuth Consumer with my Bitbucket Account with the following details:
Name: jerseytestapp
Description:
CallbackURL: http://localhost:8080/
URL:
Question 1: Could I automate this step?
Step 2: I ran the following Java code:
package jerseytest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
public class BitbucketJersey {
public static void main(String[] args) {
OAuthClientRequest request;
try {
request = OAuthClientRequest
.authorizationLocation("https://bitbucket.org/site/oauth2/authorize")
.setClientId("jerseytestapp")
.setRedirectURI("http://localhost:8080")
.buildQueryMessage();
System.out.println(request.getLocationUri());
} catch (OAuthSystemException e) {
e.printStackTrace();
}
}
}
Step 3: I received the following locationURI and opened in Firefox
https://bitbucket.org/site/oauth2/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A8080&client_id=jerseytestapp
Question 2: Do I need to use the browser or can I do this from the java application?
I receive the following answer message in Firefox:
Invalid client_id
This integration is misconfigured. Contact the vendor for assistance.
Question 3: What would be the correct next steps, and what is wrong with my approach?
Answer 1: You can automate the creation of OAuth Consumers, but you probably don’t want to.
Bitbucket provides documentation on how to create a consumer through their APIs, although the documentation is lacking many pertinent fields. Even so, you could still craft an HTTP request programmatically which mimics whatever Bitbucket's web interface is doing to create consumers. So yes, it could be automated.
Here's why you probably don't want to. In your case, you have three things that need to work together: your application, the end user, and Bitbucket. (Or in terms of OAuth jargon for this flow, those would be the client, resource owner, and authorization server, respectively.) The normal way of doing things is that your application is uniquely identified by the OAuth Consumer that you’ve created in your account, and all usages of Bitbucket by your application will use that single OAuth Consumer to identify your application. So unless you’re doing something like developing a Bitbucket application that generates other Bitbucket applications, you have no need to automate the creation of other OAuth Consumers.
Answer 2: You can authorize directly from your Java application.
Bitbucket states that it supports all four grant flows/types defined in RFC-6749. Your code is currently trying to use the Authorization Code Grant type. Using this grant type WILL force you to use a browser. But that’s not the only problem with this grant type for a desktop application. Without a public webserver to point at, you will have to use localhost in your callback URL, as you are already doing. That is a big security hole because malicious software could intercept traffic to your callback URL to gain access to tokens that the end user is granting to your application only. (See the comments on this stackoverflow question for more discussion on that topic.) Instead, you should be using the Resource Owner Password Credentials Grant type which will allow you to authenticate a Bitbucket’s username and password directly in your application, without the need of an external browser or a callback URL. Bitbucket provides a sample curl command on how to use that grant type here.
Answer 3: The correct next steps would be to model your code after the following sample. What is wrong with your approach is that you are trying to use a grant type that is ill-suited to your needs, and you are attempting to use your OAuth Consumer's name to identify your application instead of your Consumer's key and secret.
The following code sample successfully retrieved an access token with my own username/password/key/secret combination, whose values have been substituted out. Code was tested using JDK 1.8.0_45 and org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.0.
OAuthClientRequest request = OAuthClientRequest
.tokenLocation("https://bitbucket.org/site/oauth2/access_token")
.setGrantType(GrantType.PASSWORD)
.setUsername("someUsernameEnteredByEndUser")
.setPassword("somePasswordEnteredByEndUser")
.buildBodyMessage();
String key = "yourConsumerKey";
String secret = "yourConsumerSecret";
byte[] unencodedConsumerAuth = (key + ":" + secret).getBytes(StandardCharsets.UTF_8);
byte[] encodedConsumerAuth = Base64.getEncoder().encode(unencodedConsumerAuth);
request.setHeader("Authorization", "Basic " + new String(encodedConsumerAuth, StandardCharsets.UTF_8));
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
OAuthResourceResponse response = oAuthClient.resource(request, OAuth.HttpMethod.POST, OAuthResourceResponse.class);
System.out.println("response body: " + response.getBody());
Your main problem was that you were giving the customer name instead of the client id:
.setClientId("jerseytestapp")
The only way to get the client id that I know of is to query:
https://bitbucket.org/api/1.0/users/your_account_name/consumers
However, even then it was still not working so I contacted bitbucket support. It turned out that the documentation is misleading. You actually need to use the client key instead.
.setClientId("ydrqABCD123QWER4567") // or whatever your case might be
https://bitbucket.org/site/oauth2/authorize?client_id=client_key&response_type=token

Django and Java Applet authorization failed

I'm building a Django App with allauth.
I have a page, with authentication required, where I put a Java applet. This applet do GET requests to other pages (of the same django project) which return Json objects.
The applet gets the CSRF token from the parent web page, using JSObject.
The problem is that I want to set ALL the pages with authentication control, but I cannot get the sessionid cookie from the parent web page of the applet, so it cannot do GET (and neither POST) to obtain (or save) data.
Maybe it is a simple way to obtain this, but I'm a newby, and I haven't found anything.
Ask freely if you need something.
Thank you.
EDIT:
Has I wrote downstairs, I found out that the sessionid cookie is marked as HTTPOnly, so the problem now is which is the most safe way to allow the applet to do POST and GET request.
For example it is possible to create a JS method in the page, which GET the data and pass it down to the applet?
Maybe in the same way I can do the POST?
EDIT:
I successfully get the data, using a jquery call from the page. The problem now is that the code throws an InvocationTargetException. I found out the position of the problem, but I don't know how to solve it.
Here is the Jquery code:
function getFloor() {
$.get(
"{% url ... %}",
function(data) {
var output = JSON.stringify(data);
document.mapGenerator.setFloor(output)
}
);}
And here there are the two functions of the applet.
The ** part is the origin of the problem.
public void setFloor(String input) {
Floor[] f = Floor.parse(input);
}
public static Floor[] parse(String input) {
**Gson gson = new Gson();**
Floor[] floors = gson.fromJson(input, Floor[].class);
return floors;
}
And HERE is the log that come out on my server, where you can see that the applet try to load the Gson's library from the server (instead from the applet)
"GET /buildings/generate/com/google/gson/Gson.class HTTP/1.1" 404 4126
Somebady can help me?
You can do something like this in your applet:
String cookies = JSObject.getWindow(this).eval("document.cookie").toString();
This will give you all the cookies for that page delimited by semicolons.

How to secure URL parameters in java

Sample URL http://dineshlingam.appspot.com/guestbook?name=xxx&skills=zzz
Sample Code
public class GuestbookServlet extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException
{
String userName = req.getParameter("name");
String userSkills = req.getParameter("skills");
if(userName != null && userSkills != null)
{
res.setContentType("text/plain");
res.getWriter().println("Name : " + userName + ", Skills : " + userSkills);
}
else
res.sendRedirect(req.getRequestURI());
}
}
I am manually enter this URL to web browser.
How to secure parameters value.
Give me any one suitable example. Because I don't know the java concept and google-app-engine concept.
Really I don't know the SSL. So please I need detailed explanation of SSL with Example.
I am using eclipse to develop my application. Please help me. Thanks.
Your code is a classic example of a page vunerable to a CSS (Cross-Site-Scripting) attack. Using HTTPS wont mitigate that. Instead you need to escape any input before adding it to the page.
For example by using StringEscapeUtils.escapeHtml() and StringEscapeUtils.escapeJavaScript() from the Apache Commons Lang library.
Using https does not secure url parameter by any mean. You have to put parameters either in header or body if you want to make it secure. However if you are making a call directly from browser for this you cant put it in header neither in body because it is a a GET request. +1 to nfechner for highlighting XSS issue in your code.
For your problem here are the possible workaround with https:
Instead of GEt call use a POST call by putting this search in separate form in your page and use HTTPS on top of that.
If you want to use GET request you have to put the parameters in Headers, make a search page, When user hits the search button, make ajax call to above resource by passing it into header using https call.

Categories

Resources