Secure JPA binding in Play framework - security

I have a page:
<input type="hidden" name="user.id" value="123" />
<input type="text" name="user.name" value="John" />
and an action:
public static void save(User user) {
user.save();
}
Play loads the user entity from database by the user.id parameter, binds HTTP parameters to the object and the action saves it.
That is ok for trusted user like admin but not trusted user can change HTTP parameters to:
?user.id=456&user.name=John
and thus edit a different entity.
I check whether user has changed the user.id by putting user.id also to the session and then I validate its equality. This works fine since session is signed and can't be modified but how can I check easily many entities on the page – e.g. when doing a bulk update? Or just do it application wide by default?
I don't want to put 20 ids to the session and then check each id if it is equal to HTTP parameter.
One solution came to my mind. I would put a signed id as a token to each entity and check it during binding. How would you implement this?

From what I understand what you want is authentication and authorization.
Authentication tells you who the user is and you can pHk answer to do that or use the secure module
If you want to manage authorization (what the user can do, in your case what object the user can update) I would recommend looking at the security-permissions module.
It is based on the secure module but the drools based rules give you all the flexibility you need.

I'll try to clarify my solution proposed at the end of my question which would solve it generally.
Each entity will have another field – a token – which is the entity id signed by the secure key. This token does not have to be stored in database but can be computed on the fly. When a edit page is rendered it includes the signed id in e.g. __at field:
<input type="hidden" name="user.id" value="123" />
<input type="hidden" name="user.__at" value="9e01f3c8...4ccba38b9" />
<input type="hidden" name="user.address.id" value="124" />
<input type="hidden" name="user.address.__at" value="83df099...4a276fc8" />
When these entities are being bound in controller it sings again the received id and compares it to the __at field. If these signed values are not same then it indicates the user has changed the id.
I am not an encryption expert and didn't look how Play session is signed but I guess it is similar. Do you think this mechanism could work?

You can use checkAuthenticity method in a controller to check the authenticity of the form submitted.
In your server code you also have to check that the user as the rights to update theses entities. This can be done by adding a join to the user table in your jpa queries so you select not only on the object id but also on the user connected

You'll have to make sure that save can only be called by authenticated users. One way Play! allows you to do this is by using the #Before annotation. An example from the play documentation:
#Before(unless={"login", "authenticate"})
static void checkAuthenticated() {
if(!session.contains("user")) {
login();
}
}
The user session attribute would then be put in the session only when the user has authenticated. Only authenticated users will be allowed to send HTTP requests to your save() route. Note in particular the unless and only annotation parameters.
The code above comes from the OpenID example in the Play! documentation. I have used this once and so far this seems to work perfectly.

Related

sails + waterlock, how to implement the workflow with corresponding HTML templates

Background
About 6 months ago, I started developing a web app with Sails.
I was hoping to easily implement Authentication and Permission using sails-auth or sails-generate-auth and sails-permissions. 6 months later I realize that these modules aren't well maintained anymore. I decided to fall back using Waterlock.
Questions
I am newbie when it comes to NodeJS, Express & Sails. Coming from Rails, I had biased expectation. I need to be taken by the hand...
I was able to install Waterlock properly, and was able to play with the API.
1. Login
POST http://localhost:1337/auth/login
Passing email and password in the form-data (See screenshot bellow):
which returned (in POSTMAN):
{
"auth": {
"password": "$2a$10$5swWYJLZ.KbKWA9.8Hg8eOr.8HiCBiddWDyHyGSB3y7bluJZwvjDS",
"email": "my.email#mydomain.com",
"createdAt": "2016-10-04T13:01:17.594Z",
"updatedAt": "2016-10-04T13:01:17.607Z",
"id": 12,
"user": 13
},
"createdAt": "2016-10-04T13:01:17.603Z",
"updatedAt": "2016-10-04T13:01:17.603Z",
"id": 13
}
I guess my user was created and stored along with his encrypted password.
Next I tried implementing the UI (that's where I need guidance):
UserController.js:
'new': function(req, res) {
res.view();
},
user/new.ejs:
<h1>Sign up</h1>
<form action="/auth/login" method='POST'>
<input type='text' placeholder='me#mydomain.com' name='email'>
<input type='password' placeholder='password' name='password'>
<input type='submit' value="Create account">
</form>
Question 1: After create/login the user i.e. auth/login, how do I redirect to another URL? e.g. /user/show/:id id of the user just created.
I tried adding the login action the AuthController, but that just overrides the actual useful action.
UPDATE: I found that waterlock.js has Post actions hooks, but still don't know how to redirect to /user/show/:id of the user just created or logged in.
Question 2: Shouldn't I remove the "password": "$2a$10$...ZwvjDS", returned?
2. JWT
Alright, JSON Web Tokens. So I am authenticated, and next I create a JWT that I can pass in the header of my next request.
With POSTMAN
POST http://localhost:1337/user/jwt
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxM3x1bmRlZmluZWQiLCJzdWIiOiJzdWJqZWN0IiwiYXVkIjoiYXBwIG5hbWUiLCJleHAiOjE0NzYxOTIxNDc3OTgsIm5iZiI6MTQ3NTU4NzM0Nzc5OCwiaWF0IjoxNDc1NTg3MzQ3Nzk4LCJqdGkiOiI5ODgyYWY2MC04YTM1LTExZTYtODI0Yy1mNTZhYWE0MDhiZmIifQ.GYT4f49ggW8VwaEqTy0JskX6nHWZUMvM0A92KD1EC4I",
"expires": 1476192147798
}
Question 3: I am authenticated, a session was created right? Why do I need a JWT? Is it better than sessionAuth?
Actually found my answer here
Question 4: Right after LOGIN, I need to POST http://localhost:1337/user/jwt to obtain a JWT. How should I implement that in Sails?
3. How do I how use my access_token
Question 5: Where do I store the access_token and use it in the next request ? (the best practice for Sails)
Ad. 2) Certainly yes. Client shouldn't have access to his encrypted password
Ad. 4) JWT should be in service, no controller, because is more secure way. So, yep. It should be done in server side and client shouldn't have access to JWT logic.
Ad. 5) Whatever you want. IMHO header is best place.

Display Email of the logged in user in MVC 5

Can someone please advise how do we display the EmailID of the logged-in user in a View. I am using ASP.NET MVC 5 identity.
Regards,
Ram
Assuming that you are using the user's email as the username then once the user has already been authenticated you can access the name from the User Principal Identity.Name
#if (Request.IsAuthenticated) {
<span>#User.Identity.Name</span>
}
That is the simple approach. If you did not use the email as the username then you will have to attach that info using claims and then you can use an extenion method to retrieve it. I had the reverse problem. I stored the email as the username and needed to get the logged-in user's Full Name to display. I then had to do what I described for you and had to add a custom DisplayName() extension for the IIdentity .
You can easily use the #inject feature call for injecting both UserManager and SignInManager (This feature available in .NET Core).
In your view add the following:
#inject SignInManager<YourUserIdentity> SignInManager
#inject UserManager<YourUserIdentity> UserManager
After the injection, you should be able to work with UserManager and SignInManager methods. For instance:
#if (SignInManager.IsSignedIn(User))
{
<a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello #UserManager.GetUserName(User)</a>
}
else
{
}
Pay attention for passing the User object when you need to reference the current logged in user.
In your case, if you would like to get the logged in Email Address, you can use the following technique:
var loggedInUserName = #UserManager.GetUserName(User);
var loggedInEmail = await UserManager.GetEmailAsync(
UserManager.Users.FirstOrDefault(u => u.UserName == loggedInUserName)
);
Or just keep it inside a ViewBag as you like.
Hope this will be handy for anyone :)

Moneybookers response is a GET instead of a POST

I have implemented Moneybookers to our site.
The request is fine, the payment goes to our Moneybookers account, the money is debited from the user's account.
The response URL is https://example.com/finance/responsemoneybookers
The problem:
-After payment, the user click Confirm, and the user is being redirected to https://example.com/finance/responsemoneybookers
Moneybookers should POST the transaction data so we can validate it, but instead of POST, it just make a standard GET request with no data. What could be the problem ?
Add
<input id="status_url" name="status_url" type="hidden" value="https://example.com/finance/responsemoneybookers" />
to your form

JSF to Bean to JSF

So I'm having a problem trying to pass a String value.
The String value is entered through a login page as username.
The JSF then calls the Bean to verify log in information then proceeds to another JSF page.
I was wondering how to pass the username along to the new JSF page. Thank you.
If you're performing a navigation instead of a redirect, then you basically don't need to do anything. The information is also just available in the navigated page.
E.g. in login page,
<h:inputText value="#{bean.username}" />
and in the navigated page:
<p>You have entered the following username: #{bean.username}</p>
If you're however performing a redirect instead of a navigation, then you basically need to store the information in a bit broader scope. You didn't clearly elaborate the concrete functional requirement in the question, but if I guess it right, you just wanted to remember the currently logged-in user for the remaining of the HTTP session. In that case, just store it in the session scope during the login action.
public String login() {
// ...
User user = userService.find(username, password);
// ...
externalContext.getSessionMap().put("user", user);
// ...
return "nextpage?faces-redirect=true";
}
This way it's available by #{user} throughout the entire HTTP session.
<p>You're logged in as #{user.name}.</p>
You can also use <t:saveState> without using session scope. <t:saveState> is longer than the request scope but shorter than session scope.
This may help you : http://myfaces.apache.org/tomahawk-project/tomahawk12/tagdoc/t_saveState.html

How to Prevent CSRF in Play [2.0] Using Scala?

A lot of web frameworks have a standard setup for generating forms with auth tokens.
Do I have to create such measures manually, or does Play come with a build in means of prevening CSRF?
The documentation on the Play website doesn't seem to address this.
I use the play2-authenticitytoken module:
The authenticity token is a way around one of the most serious internet security threats: CRSF attacks. It ensures that the client submitting a form is the one who received the page (and not a hacker who stole your session data).
How it works:
In a nutshell:
on every form post, we add a hidden parameter containing a uuid
the uuid is signed and its signature is stored in the session (which translated into a cookie)
When the user submits the form, we get: the uuid, the signature and the other form inputs.
We sign the incoming uuid again
Validation passes if the signatures match (session.sign=uuid.sign)
Should an attacker inject a different id, he will never figure how to generate the correct signature.
For completeness sake, I have an example here in Scala for Play 2.0
https://github.com/jacobgroundwater/Scala-Play-CSRF
This method also uses the cookie + hidden-field approach.
Example Usage
Use the SessionKey action to help sign a form:
object Application extends Controller {
def login = SessionKey{ (key,signature) =>
Action { implicit request =>
Ok( views.html.login(signature) ).withSession( key->signature )
}
}
}
When parsing forms use the following to check for the signature:
object Authenticator extends Controller {
def login = ValidateForm{
Action { implicit request =>
Ok( views.html.index("You're Loggd In") )
}
}
}
Since Play 2.1 there's support for this in the framework. Nick Carroll wrote a nice little article on how to use it:
http://nickcarroll.me/2013/02/11/protect-your-play-application-with-the-csrf-filter/

Resources