Play Framework User Authentication/Membership - authentication

I want to support user authentication in a Play Application. It is Web App and I think that the built-in "Secure" module is too simple for my needs. In fact, the user group discusses how the Secure module is really for demonstration purproses. However, how can I develop such a system?
Essentially, the application will allow the user to login and then they will have their own settings and so forth applied throughout the application. There are some pages for which unauthenticated users can view but if the client is authenticated, then the view of those pages will be different. Pretty simple setup but most documentation just refers to the simple Secure module.

If your only special requirement is that some pages be publicly visible, I've got your answer: Play framework: How to require login for some actions, but not all . I just copied the Secure module and made a few small additions.

You can use the PlayPlugins for this. I started to write a plugin which enabled Security in powerful way. It's an migration from BasisSecurity for Grails. At the moment I don't find the time to further development. You can see the current state here https://code.launchpad.net/~opensource21/+junk/permsec.

from your requirements the current authentication module seems enough. If not, what I did for my project was:
Copy the classes from the module (Secure controller, the annotation, the tag) to your project
Extend the controller adding additional functionalities
I don't have my code handy to put samples here, but in general I:
renamed the classes (so apologies if I say one name meaning another, don't remember the original names!)
added methods in Secure Controller to handle OpenId and OAUth authentication
added support methods in my User model that given the Id of a service (Google OpenId, Twitter id, etc) returns an existing user from the DB with that ID, or if it doesn't exists creates and returns a new user linked to that id.
added some flags (like admin, supervisor, etc) to User class
modified the check method in security controller so it checks the values of the annotation with the flags of the user. Something like (pseudocode)
var ok : Boolean = false
ok = ok || (annotation.value == "admin" && currentUser.isadmin)
ok = ok || (annotation.value == "supervisor" && currentUser.issupervisor)
...
added the annotation to the corresponding methods, and added the Secure controller (via #With) tot he classes that require access check
With this I have a secured system, and it seems to work quite well (fingers crossed :P)

Don't know if it could help you but look at the deadbolt module to manage access rights to views/controllers...
http://www.playframework.org/modules/deadbolt-1.0/home

Related

JHipster: How to restrict user to access own data with REST

JHipster implements several best practices for authentication and authorization.
Mainly described here: https://www.jhipster.tech/security/.
But I still do not see an example how to design a solution, which does not involve putting user verification logic all over the place for a very common use case.
Let's say you have a WebPage using REST-API like BankAccountResource from JHipster Sample App and you want to restrict this to only ADMIN role or currently logged in User. Let's say you have 50 of such services for your customers: BankAccount, Address, BillingAddress, UserData, Devices... For every resource a GET and UPDATE must be restricted. Also loading device /api/device/{id} might not include user-id.
How do I prevent UserA from loading UserB's device by guessing it's id?
How do I avoid planting that code in every method?
I guess JHipster/SpringSecurity has concept/objects to handle such use cases. Could you point me, explain how to use them please?
Maybe this question helps a little bit: Restrict URL access control by id in jhipster
Spring Security hast PostFilters to check if an object e.g. loaded by a method may be accessed. If you need more control you can use Access Control Lists for fine grained access control.
References:
https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5/#domain-acls
https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5/#method-security-expressions

Dynamic Roles/Hierarchy with SimpleMembership

I finally got my MVC 4 application all set up with SimpleMembership, but now have run into a new problem. I have a menu system (in a sidebar) that gives users access to various functionality throughout the app. I recently realized that, in order to be somewhat user-friendly, I need to disable or remove various menu links based on roles. So I set up a role system and a relationship to these menu links, which works perfectly. However, the "basic site access" role should not have access to all of the links in the menu (and their corresponding controllers/actions). Previously, I had given site access by simply applying the Authorize attribute globally, via my filter config:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizeAttribute());
}
Now I've figured out that, in order to control "basic" access to the app, I would need to add individual Authorize attributes at the action level (with the "admin" role having full access). While this is fine, albeit somewhat annoying, it doesn't seem very scalable. What if my client adds a new role through the administration interface and wants to control access to various tasks? I have already coded the menu system to disable links dynamically, based on what roles have access to which tasks. But there's no way (that I know of) to dynamically apply different roles to the Authorize attribute.
Though I've read about why SimpleMembership may not be the bee's knees, I've just finished migrating from ASP.NET Membership (which had serious shortcomings of its own), and I certainly do not want to roll my own user/role management system. Has anyone successfully implemented something to handle this scenario?
You should definitely take a look at Fluent Security if you have a lot of controllers/actions that you don't want to decorate with annotations.
It allows all authorisation to be handled from Global.asax. It's well documented and there's a good tutorial on it here.

How to integrate atk4 login with existing PHP app

Atk4 has basic login functionality and I could build it out to add user registration, forgotten password link, email verify etc using atk4, tmail templates and so on. But if I want to integrate it with an existing open source application that already provides that functionality, what do I need to do to allow that systems login to be allowed so that atk4 protected pages can be viewed after login on the third party app?
There are four alternatives.
Separate sites, separate domains, separate servers, separate database
The most secure way to do that is by passing secure token from the other system to Agile Toolkit. The token should contain the username and hash of some secret passphrase along with that username $user.":".md5($secret.":".$user)
You can check the argument inside API Class:
$this->auth=$this->add('YourAuth');
if($_GET['login_token'])){
list($user,$token)=explode($_GET['login_token']);
if(!verify_token($token))throw $this->exception('Break-in attempt');
$this->api->auth->login($user);
}
$this->auth->check();
Separate site, domain, but same user access
You would need to build same encryption in Agile Toolkit Auth class. Fortunately you can easily do that, by re-defining encryptPassword
class MyAuth extends SQLAuth {
function encryptPassword($password,$salt=null){
return ....
}
}
If you need different connection to database you can also add:
function init(){
parent::init();
// Ouch, last occurrence of static method use!
$newdb=DBLite::connect(
$this->api->getConfig('user_dsn'));
$this->db=$newdb->dsql();
}
Sharing session - same domain and same computer, but no code access
Agile Toolkit uses the Application's realm as a name. That's the argument you specify to the constructor when you create your app instance inside index.php:
$api=new MyFrontend('myrealm');
You would need to call
session_name('myrealm');
session_start();
Then you need to set the session variable, something like myrealm_MyAuth_info, you can probably get this by dumping contents of $_SESSION from Agile Toolkit. You need to set it to something like array('user'=>'john'), as long as it's not "false" anything is ok.
Sharing computer, domain, session and some code
This is similar to previous approach, but it should be easier to do:
include 'yourapp/atk4/loader.php';
include 'yourapp/lib/Frontend.php';
$api = new Frontend();
$api->auth->login('john');
This assumes that your "Frontend" class properly sets the "auth". If this does not work, some tweaks might be needed, for example you might want to move $auth->check() into initLayout() function, if you are calling it from within API.

GWT: Authentication for some part of application using GWT login page

My application has some features that are accessible to all users, and some other features to which access should be restricted to authenticated users only. All these restricted features exists within some set of GWT Places, thus, all Places available in application can be divided into two groups: "accessible for all", and "restricted". In my opinion, places with restricted access, could implement some interface (let's say it would be RestrictedAccess), and if user proceeds to one of them, and it has not been authenticated yet, it will be redirected to the login screen - it's more OO-approach than applying filters basis on URL.
What I'm trying to achieve is:
Information about if user has been
authenticated or not should be
stored on server (it's not something
that could be stored in a cookie...)
Login page is a standard GWT place+view+activity (!)
User name & password validation is done on the server side.
So far, I've introduced RestrictedAccess interface, which is implemented by some set of places. My FilteredActivityMapper.Filter implementation, which is passed to the FilteredActivityMapper wrapping application activity mapper has the following logic:
Place filter(Place place) {
if (place instanceof RestrictedAccess && !userHasBeenAuthenticated()) {
return new LoginPlace();
}
// return the original place - user has been already authenticated or
// place is accesible for all users
return place;
}
private boolean userHasBeenAuthenticated() {
// remote call - how to do ???
}
The problem is with userHasBeenAuthenticated() method (user should not be redirected to the LoginPlace, if it has been already authenticated). If I want to store this information on the server-side, I have to do GWT RPC/request factory call here, but both are asynchronous, so I cannot work on its result in the filter method.
I know that I can use web.xml filters or some external framework (e.g. spring security), but none of this approach allows me to have login page as a standard GWT - based form, or indicating in the more OO way that access to some place should be restricted.
Thanks in advance for any hints
EDIT: I've started to wondering if places filtering (restricted/not restricted) should take place on the client side at all. If, as it was suggested, there is a possibility to hack code indicating if user has been authenticated or not, there is also possibility to hack places filtering code, so that it will be possible to access restricted places without signing in.
Piotrek,
I think there is a security issue with calling userHasBeenAuthenticated() - it would be possible to hack the client side code to return true every time this function is called.
The solution I've implemented is to simply return SC_UNAUTHORIZED if an unauthenticated user attempts to access any remote service. I've overridden the RequestFactory onResponseReceived function which redirects to a login page if the response is SC_UNAUTHORIZED. Idea taken from:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/samples/expenses/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
This works for our situation where the Activities and Places are all data-centric - each place change retrieves data from the server. If a user isn't authenticated they simply don't get the data and get redirected to a login page.
I realize your situation is slightly different in that some places are accessible to everyone, in which case you could configure only the restricted services to return SC_UNAUTHORIZED.
I have a similar application with the same requirements. As yet I have not got round to to the implementation but I was thinking along the same lines.
What I was planning on doing is storing the authentication state client side in an AuthenticationManager class. When the app starts I was going to request the login info from the server (I was thinking of running on app engine so I would get the authentication state and also get the open id login/logout URLs) and store this in the AuthenticationManager. Acegi/Spring Security works in a simlar way so this info is available server side if you use those too.
When the user logs in/out they will be redirected by the server and the new state will be retrieved. This should keep the client authentication state in line with the server. Each RPC request on the server has to be checked for authentication too. I was using the gwt-dispacth library and this has some rudimentary authentication checking and cross site script protection in in too (although I think latest GWT has this for generic RPC).
One issue is session timeouts. Again the gwt-dispath library has some code that detects this and returns session expired exceptions to the client which can be intercepted and the auth manager updated.
Hope that makes some sense.

Where should I put CAS session checking code in a CakePHP application?

I work for a department of a university that uses CAS to provide single-sign-on authentication, and am writing a CakePHP application that needs to use this CAS service. I need to write code that:
Checks with the CAS server to see if the user is logged in
Pulls some credentials from the server if so
Checks the credentials against an internal ACL, as the set of people who can access the application is a subset of the set that can log into the CAS service.
Provides some mechanism for admin users, either by creating special admin users outside the CAS system (with all the headaches that would entail) or by promoting certain CAS users (with the different headaches that would entail).
As a relative newcomer to CakePHP, I frequently struggle with where to stick code that "doesn't belong". The best I can figure is that this code ought to go in the beforeFilter method of the App Controller, but I wonder, is this the best place for it? Also, is it too low in the stack to take advantage of admin routing?
Lastly, I know that CakePHP provides both Auth and ACL components, but when I looked into using them they did not appear amenable to interfacing with outside authentication services. Am I wrong, and would either of these be a good fit for what I need to do?
Thanks!
If you take a look at the Cake's core components you can see that your CAS requirement fits with the type of things components are typically used for (ie. auth/session).
I would recommend creating a CasAuthComponent. There is some information on extending AuthComponent, in a previous answer of mine, which may prove useful if you wish to build on top of the existing core AuthComponent.
A component (essentially reusable controller code) can interact with models, use other components (such as Session) and control user flow (redirects for example)
Note that, the core AuthComponent actually retrieves information from a model (the User model by default), so you could do something similar.
The CasAuthComponent you create could $use an external user model (CasUser maybe) which is responsible for CRUD operations on the data (retrieving users mainly).
You could take this one step further and abstract CAS interactions into a datasource used by this model, but it isn't strictly neccessary if you don't plan on reusing the code in other models.
The end result could be packaged into a plugin:
CasAuthComponent (app/plugins/cas/controllers/components/cas_auth.php)
CasUser (app/plugins/cas/models/cas_user.php)
CasSource (app/plugins/cas/models/datasources/cas_source.php) [optional]
And used in your application by putting the following in your app_controller:
public $components = array('Cas.CasAuthComponent');
If you wish to be able to administer the users from Cake, you can also include a controller and views in your plugin, which allow the user to interact with the CasUser model (ie. $this->CasUser->save()).