I have been playing around with authentication. I want to be able to have some extra functions on certain pages available for those who log in. The problem is that if I don't use the #Security.Authenticated(Secured.class) annotation for the controller class I cannot get the username from the session so I cannot check if the user is logged in or not.
How should I go about this? Should I make sure all pages are authenticated and then have some sort of a guest login that automatically gets used for those other sessions or is there a way to check if the user is logged in even on a class without the #Security.Authenticated(Secured.class) annotation.
It would be great if someone could point me in the right direction, if there is a tutorial available that does this or just some guidance.
You should do two things:
Prevent unauthenticated users from viewing the functionality in your template:
#if(session().containsKey(Secured.SESSION_AUTH_KEY)) { /* Your comment form */ }
Prevent unauthenticated users from accessing your action:
#Security.Authenticated(Secured.class)
public static Result submitComment() {
...
}
With:
public class Secured extends Security.Authenticator {
public static final String SESSION_AUTH_KEY = "email";
public String getUsername(Http.Context context) {
return context.session().get(SESSION_AUTH_KEY);
}
public Result onUnauthorized(Http.Context context) {
...
}
}
Related
Suppose, there's a site that provides an API, such as this:
Users post questions, answers on that site
You can make GET and
POST calls
There are two types of authentication: weak (only gives
read rights) and strong (gives both read and write rights)
Right now, I'd like to read users' questions and answers (only need weak access) and send them messages or post my own questions in the future (would need strong access)
The site's API has actions both to do with users (e.g. send a message) and with site in general (see about, see most popular questions)
What I have right now looks like this:
public class Wrapper {
private AccessToken accessToken;
public Wrapper(...) {
//does some stuff
//gets access token:
getAccessToken(...);
}
public AccessToken getAccessToken(...) {
AccessToken result;
//gets access token, given the auth info provided as arguments
accessToken = result;
return result;
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
and User class:
class User {
private String username;
private ArrayList<Question> questions;
private ArrayList<Answer> answers;
public User(String username) {this.username=username;}
//getters and setters
}
So, to use it you would use something like this:
public class Main {
public static void main(String[] args) {
Wrapper wrapper = new Wrapper(...);
ArrayList<Question> questions = wrapper.getQuestions(new User("username"));
wrapper.sendMessage(new User("username2"));
}
}
I have issues with this.
First of all, class User feels superfluous, since all the functionality is inside the Wrapper class.
Second, I wonder if what my methods do is wright - from the design's perspective: in getAccessToken I both return AccessToken and set a Wrapper's field accessToken to the result. Is this the right approach? Or should the method only return access token and then that result should be assigned to a class' field explicitly? Same goes for the getQuestions and getAnswers methods: they both get the ArrayLists, return them and assign a User's field to the result - all inside the single method.
I would like for a User class to have some meaning. I thought of doing it something like that:
Wrapper wrapper = new Wrapper(...);
User user = new User("username");
user.getQuestions(wrapper.getAccessToken());
user.sendMessage(wrapper.getAccessToken());
So, the Wrapper class would only serve as a place to get an access token from, which doesn't feel right as well. I could place the access token functionality inside the User class and use it like this:
User user = new User("username", ...);
user.getQuestions();
user.sendMessage();
The User's constructor would take both username and auth data, would get access token and store it inside a user and then use it when getting questions/answers or sending messages. I could make the accessToken field inside User class static so that all users shared the same token.
However, there are actions the site API provides, that aren't obviously connected with users: for instance, getting the site's most popular questions. It feels right to use a generic Wrapper class for that purpose which contradicts with the previous approach.
I'm new to this and only know a couple design patterns. Perhaps, there are widespread patterns that are to be used for this type of problem? Any help/advice is appreciated.
There are a few alternatives that you can do to solve your problem, but there is likely not one that is better than all others. The solution you choose will depend on the trade-offs and how you want your system to operate. The following are two common solutions to this type of problem.
Have the Wrapper generate a User: Instead of generating a User object separate from the Wrapper, you can have the Wrapper generate the User object. This allows the Wrapper to embed the AccessToken within the User without any outside client knowing that a user has an AccessToken. For example, you can use the following Wrapper and User definitions:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
public User(String username, AccessToken token) {
this.user = user;
this.token = token;
}
// ... getters and setters ...
}
Note that getAccessToken is now private, as no other client needs to access this method. All of the methods of Wrapper continue to accept a User argument, but they now should obtain the access token by calling getToken on the User object, rather than using a stored AccessToken in Wrapper.
Also note that the token field is final, since the access token associated with a User should not change over the life of a User object.
Embed the Wrapper in User: This technique is similar to (1), but it also embeds the Wrapper object in the User object. This allows the User class to act as a live object, which can be queried for questions and answers and can be used to send messages. Since all of the methods of Wrapper accept a User argument, this is a good sign that the methods should be moved to User. The following is a halfway point to refactor the Wrapper methods into User:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
return wrapper.getQuestions(this);
}
public ArrayList<Answer> findAnswers() {
return wrapper.getAnswers(this);
}
public boolean sendMessage() {
return wrapper.sendMessage(this);
}
// ... getters and setters ...
}
Using this technique, clients can now directly get questions and answers from a User object. Note that the findQuestions and findAnswers methods start with find. This tips off clients that this call may be a long call (as opposed to getQuestions or getAnswers, which would make a client assume that it is a simple getter and the method would return nearly-instantly). The fact that these methods execute a remote call should also be documented in the Java-docs for the methods. If the call takes a long time, the methods should return a Future (or a similar object) and be made asynchronously.
If you want to go all-in on the refactor, you can move all of the implementation details from the Wrapper class to the User class:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
// ... find the questions remotely ...
}
public ArrayList<Answer> findAnswers() {
// ... find the answers remotely ...
}
public boolean sendMessage() {
// ... send message remotely ...
}
// ... getters and setters ...
}
This may not be the best approach, as it may be a better idea to keep the details of accessing the remote API abstracted in the Wrapper class. This is a judgment call that will depend on the nature of your specific application.
There are numerous other techniques that you can do, but the above two are common approaches to the problem you are trying to solve.
I have implemented my own Authenticator from Play Framework and DeadboltHandler from Deadbolt.
Using the methods onUnauthorized respective onAuthFailure I can send users that are not logged in to the "login page" instead of the actual page they are trying to access.
However, instead of sending a user directly to the "login page", I want to specify what page the user should be sent to depending on which page the user tries to reach. For example, if the user tries to access /settings the user should be redirected to the login page. If the user tries to access /player/1 the user should be redirected to another page, say, "create user" page.
I was hoping that there is some smart way to do this with annotations, something like: #someannotation(redirect = route/id) so I can redirect to the relevant route if the user is not logged in, else to the standard "login page".
Any one got any ideas?
Code snippet example for controller and route method:
#Security.Authenticated(Secured.class)
#SubjectPresent(content = "createuser")
#DeferredDeadbolt
public class Settings extends Controller {
#SubjectPresent(content = "login")
#CustomRestrict(value = { #RoleGroup({ UserRole.player}), #RoleGroup(UserRole.server_owner) })
public static Result settings() {
Code snippet example for DeadboltHandler onAuthFailure:
#Override
public F.Promise<Result> onAuthFailure(Http.Context context, String content) {
return F.Promise.promise(new F.Function0<Result>() {
#Override
public Result apply() throws Throwable {
System.out.println(content);
There are a couple of different ways you can do this.
Approach 1: Repurpose the content value
In this approach, you can use the content value of the constraint annotations to give a hint to the handler. You can use a class-level constraint to define the default redirect, e.g. go to the login page, and method-level constraints to override the default redirect. All constraints have the content value, I'm just using SubjectPresent as an example; you can also mix constraints, e.g. have SubjectPresent at the class level and Restrict at the method level.
#SubjectPresent(content = "login")
public class FooController extends Controller {
public Result settings() {
// ...
}
public Result somethingElse() {
// ...
}
#SubjectPresent(content = "create-user")
public Result viewUser() {
// ...
}
}
In your DeadboltHandler implementation, you would then need a test on the content:
public CompletionStage<Result> onAuthFailure(final Http.Context context,
final Optional<String> content) {
return CompletableFuture.supplyAsync(() -> content.map(redirectKey -> {
final Result result;
if ("login".equals(redirectKey)) {
result = [redirect to login action]
}
else if ("create-user".equals(redirectKey)) {
result = [redirect to create user action]
} else {
result = [redirect to default authorization failure action]
}
}).orElseGet(() -> [redirect to default authorization failure action]), executor);
}
Approach 2: Use the ROUTE_PATTERN tag
Instead of specifying keys in the constraint annotations, you can instead use the route specified in the request to determine the requested action.
public CompletionStage<Result> onAuthFailure(final Http.Context context,
final Optional<String> content) {
final String route = requestHeader.tags().get(Router.Tags.ROUTE_PATTERN);
// examine the route and work out what you want to do
}
I am trying to extend the user authentication example, which is also presented here, so that multiple users can login to the server. I would also like to assign a different home directory for each user. So far, I haven't been able to find any such utility provided by the Apache SSHD API, so I have tried the following workaround, by using the utilities provided by the Apache FtpServer.
What I attempt to do is:
create a UserManager object to manage a list of users and store their information in a property file, in a way similar to this example
create a PasswordAuthenticator that makes use of the UserManager in its authenticate method, as follows:
public class MyPasswordAuthenticator implements PasswordAuthenticator {
private UserManager userManager;
public MyPasswordAuthenticator(){
this.userManager=null;
}
public MyPasswordAuthenticator(UserManager manager) {
this.userManager=manager;
}
#Override
public boolean authenticate(String username, String password, ServerSession session) throws PasswordChangeRequiredException {
if (this.userManager==null) return false;
User usr=null;
try {
usr = userManager.getUserByName(username);
} catch (FtpException e) {
e.printStackTrace();
}
if (usr==null) return false;
else{
String pass=usr.getPassword();
return password.equals(pass);
}
}
}
However, the usr.getPassword() returns null, even though a) the password fields in the property file do have values b) I have checked the functions getName() and getHomeDirectory() and they return their respective String values.
My question is, why does this happen and what should be done to fix this?
I have found a way to make it work, it is:
usr = this.userManager.authenticate(new UsernamePasswordAuthentication(username, password));
I am designing an sdk/client library for a http api. The api support multiple authentication mechanisms: basic auth, oauth, digest etc.
My client library is simple at the moment like this:
public MyAPIRestClient implements MyAPIClient {
public MyAPIRestClient(String endpoint, String user, String pass){
login(user, pass)
}
public void login(String user, String pass){
//http code to login and get a cookie etc.
}
public Book getBook(String name){
// http code to get a book
}
}
What is the best design pattern to enable me to have multiple authentication mechanisms, without having to code all possible auth methods in the same client class? And to enable future auth mechanisms to easily be injected?
It is an odd thing to do you by yourself when this matter is very complex, difficult and has very good mature solutions including Apache Shiro and Spring Security. But I assume it's just an exercise in design patterns.
I would probably go for the chain of responsibility pattern. Have a generic interface like:
interface Authenticator {
/**
* Analyze the request and return an Authentication object
* upon success, or null otherwise
*/
Authentication authenticate(HttpServletRequest request);
}
Implement it for each authentication mechanism, checking cookies, POST data or what have you.
Then, call them like:
public Authentication authenticateRequest(HttpServletRequest request) {
for (Authenticator ator : supportedAuthenticators) {
Authentication a = ator.authenticate(request);
if (a != null) {
// Logged in successfully!
return a;
}
}
throw new LoginFailed();
}
The first thing that came to my mind is the strategy pattern:
public abstract class Authenticator{ //or interface
public abstract boolean login(String user, String password);
}
The Authenticator is the pattern. You can extend/implement it with various authentication methods. In your main class you hold a specific pattern in a member, which you then call directly:
public class Main{
private Authenticator auth;
//choose auth in constructor or by choosing it in a List in some GUI
//and create an Object that extends/implements Authenticator
public void login(String user, String password){
if(auth.login(user, password)){
//do whatever is needed to complete login
}
}
}
This way you have minute control over which authentification method(s) are used.
If you change auth to an array or ArrayList, it is essentially the same as #Konrad Garus answer.
I would suggest to have an interface which will have signatures of basic authentication methods,and the implementing class can have different definitions of those authentication methods.
I want the session to be checked before sending a
user to the login - whereby each URL request results in checking whether
this is from a valid session - if not, send them to the login page,
else process as normal. If the user already has an active session, we
will not show them the login page but take them to a pre-defined main
page.
I searched on google related to it, and come to know that it will done by using #Before annotaion in controller but dont know about #Before working and how to use? I'm using play 1.2.5.
You can use the #Before this way:
#Before
static void addUser() {
User user = connected();
if(user != null) {
renderArgs.put("user", user);
}
}
static User connected() {
if(renderArgs.get("user") != null) {
return renderArgs.get("user", User.class);
}
// Find your user from session
String username = session.get("user");
if(username != null) {
return User.find("byUsername", username).first();
}
return null;
}
// ~~render your login if the user is not finded in session
public static void index() {
if(connected() != null) {
render();
}
login();
}
You can find this sample code in YOUR_PLAY_DIR/samples-and-tests/booking.
As #emt14 said, you can do this with the Play secure module more easily. Check out the forum apps samples in YOUR_PLAY_DIR/samples-and-tests/forum.
The Play secure module does exactly that out of the box. It is used by most applications and integrates with different plugins as well. Check out the documentation here.
If you still want to implement it yourself you can use the secure code as an example.
Otherwise #Before can be used on any of your controller static methods and has access to all the scope Objects, including session.