I'm working on a Java-based web app using Tomcat 7.0 as the application server. After the helpful responses to a prior question, I've decided to use bcrypt to securely store passwords in my HSQLDB. However Tomcat's default Realm implementations can't handle bcrypt, so I need to write my own; that's the only reason I'm writing a custom realm though as in all other ways plain JDBCRealm would work. I've been googling and looking at examples and I'm rather confused on a couple of points.
First, should I extend RealmBase, or JDBCRealm? Most examples I found use RealmBase, but I've successfully been using JDBCRealm for the app up to this point (as it's still in development I started off with storing the passwords in plaintext and just using JDBCRealm to handle authentication), and one answer to a question on Code Ranch recommended just extending that. I'm not exactly sure which methods I'd need to override in that case, though. Just the authenticate method, or something more? If did this would JDBCRealm still be able to handle and manage user roles, getPrincipal, and all that?
Second, in the CodeRanch example linked above, unless I'm missing something, the getPassword method seems to be returning the unencrypted password. Since I'm going to be using bcrypt that won't be possible, and it seems kind of inadvisable anyway, I would think. In other examples like on this blog post, getPassword seems to just return the password directly from the database. So which way is correct? I can't find what exactly getPassword is used for; the documentation doesn't say. Will it be ok to just return the encrypted value stored in the database for this?
If anybody can tell me what class I should extend, what methods I should override, and what getPassword should return, I would really appreciate it.
Well after some trial and error I figured out how to do this. I extended JDBCRealm and only overrode the authenticate method and it works perfectly. I put BCrypt.java in the same directory as my custom realm, and this code is what worked:
import java.security.Principal;
import org.apache.catalina.realm.JDBCRealm;
public class BCryptRealm extends JDBCRealm
{
#Override
public Principal authenticate(String username, String credentials)
{
String hashedPassword = getPassword(username);
// Added this check after discovering checkpw generates a null pointer
// error if the hashedPassword is null, which happens when the user doesn't
// exist. I'm assuming returning null immediately would be bad practice as
// it would let an attacker know which users do and don't exist, so I added
// a call to hashpw. No idea if that completely solves the problem, so if
// your application has more stringent security needs this should be
// investigated further.
if (hashedPassword == null)
{
BCrypt.hashpw("fakePassword", BCrypt.gensalt());
return null;
}
if (BCrypt.checkpw(credentials, hashedPassword))
{
return getPrincipal(username);
}
return null;
}
}
Related
I'm creating a RESTful service with Jersey (2.28) and use Apache Shiro for permission handling. So I used the buildin HttpMethodPermissionFilter which creates permissions like resource:read or resource:write. Now I have the problem that a user may only be allowed to read or write a specific resource and that I would need something like resource:write:<id> or resource:write:<name> or what ever as identifier.
I thought about extending the filter but at that point - even while I could access the body or the url - I have no idea how the data looks like.
Solutions I thought about:
Always pass a query parameter in the url, like /api/resource?id=xxx and if given apply that parameter for the permission string. But there is no way to tell if the parameter is required or not if both resource:read and resource:read:<id> exist. The filter might create a wrong permission for the given url. I could apply the filter only to urls where I know it must be the case, but seems all a bit wonky and error prone.
Remove the filter and ask for the permissions inside of the requested method.
#GET
#Path("/resource/{id}")
public Response getResource(#PathParam("id") String id) {
if(AuthorizationHandler.hasPermission("resource:read:" + id) {
return Response.status(Status.OK).entity("Resource GET works").build();
}
// return 403 or handle exception or ...
}
Somewhat like that, but it will leave me with exception handling in every method which also seems not much preferable. Maybe I could use an ExceptionMapper to handle responses... haven't tried that.
Does maybe someone else have another idea how to solve this efficently or maybe point me to an already existing solution? I'd prefere to use the #RequiresPermissions("resource:read") annotation (or a custom one), but could also define the urls / filters in the shiro.ini file /api/resource/** = noSessionCreation, jwtf, rest[resource] or I fallback to solution 2 if that's recommended.
I am simply trying to check whether a given user has a given WebSphere administrative role, within a Java servlet.
The idiom:
HttpServletRequest#isUserInRole
... works for non-administrative roles, and the iscadmins administrative role defined in this documentation page.
However, all other roles in the page above (which seem to differ from iscadmins, scope-aside, by having their first letter capitalized) are not reflected when invoking isUserInRole.
I've tried checking both with the primary administrative user (file-based, created with the profile) and with other users whom I've explicitly added administrative roles to.
In all cases, only iscadmin role checks return true when assigned.
Using standard WAS 8.5.5 if that's any relevant.
I am wondering whether there is something crucial I misunderstand about security and scope in this context.
Note
I have tried different combinations to check for role names that have a first capitalized letter: as is, lowercase, all-caps, etc. even got more creative with the Admin Security Manager role...
After hours and hours of headaches and searches through undocumented APIs, I think I've found what I'm looking for.
Fair warning
I couldn't find any documentation about this, not even javadocs.
I cannot honestly tell if this is the recommended approach.
This said, the approach below works for me (tested by assigning and removing the Admin security manager role from the logged on user, then reloading the servlet and debugging).
Also, the mistery remains on why these roles are not visible through the HttpServletRequest#isUserInRole idiom.
Code recipe
// relevant imports
import com.ibm.websphere.management.authorizer.AdminAuthorizer;
import com.ibm.websphere.management.authorizer.AdminAuthorizerFactory;
import static com.ibm.ws.security.util.Constants.*;
// you'll need the com.ibm.ws.admin.core.jar plugin in your classpath for this
AdminAuthorizer aa = AdminAuthorizerFactory.getAdminAuthorizer();
// all admin roles are there as constants,
// save for "iscadmins", which you can retrieve with
// the HttpServletRequest#isUserInRole idiom anyway
String role = com.ibm.ws.security.util.Constants.ADMINSECURITY_ROLE;
// that's it!
boolean test = aa.isCallerInRole(role);
First of all, I am fully aware of the authentication modules that are available to Play. That said, I am unable to implement even the simplest example code from let's say SecureSocial. With a little bit of research it became clear that a lot of things were broken in their example code provided here when the Play Framework updated to version 2.3.x.
With the help of online docs and the excellent video tutorial by Philip Johnson on implementing standard (unsafe) authentication I did succesfully implemented the following:
// Class which is used by the #Security annotation
public class Secured extends Security.Authenticator {
#Override
public String getUsername(Context ctx) {
return ctx.session().get("auth");
}
#Override
public Result onUnauthorized(Context ctx) {
return redirect(routes.Application.login());
}
}
// Controller class that serves routes
public class Application extends Controller {
#Security.Authenticated(Secured.class)
public static Result index() {
return ok(index.render("Your new application is ready."));
}
public static Result login() {
session().clear();
session("auth", "a1234"); // dummy data simulating succesful login
returning redirect(routes.Application.index());
}
}
I need to ultimately implement a safe login system to authenticate users.
My question is two-sided. What would be the better of the following: 'reinventing the wheel' (at least partly) by taking the working code base and improving it or give implementing one of the authentication modules another shot?
We all do not like reinventing the wheel, that said, I have a much better chance of succesfully compiling when I made it myself it seems...
I am aware that for a wholesome security-in-depty (a.k.a. layered security) a secure connection implementation is also needed (HTTPS with TLS1.2` at the time of writing). This is beyond the scope of my question.
I don't know if there's a right answer to this question. Whether to build your own framework or to try an existing framework (which might not work perfectly) is a matter for your own judgement. Personally, I'd probably use SecureSocial as a starting point but then write my own code if I couldn't get it working. It sounds like this is the approach you've already tried.
To use SecureSocial you'd probably need to check out the master branch and build from source. It might be hard to use if the examples are out of date, but then again writing your own auth code is difficult too.
I'm looking for the best way to test a class which internally makes HTTP requests to a pre-defined URL. Generally, the class in question looks more or less like this :
public class ServiceAccess {
private static final String SERVICE_URL = "http://someservice.com/";
public ServiceAccess(String username) throws IOException,
UserNotFoundException, MalformedURLException {
URL url = new URL(SERVICE_URL + username);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
if(conn.getResponseCode() == HTTP_NOT_FOUND) {
throw new UserNotFoundException("user not found : " + username);
}
// and some more checks
}
}
I would like to test that the class properly reacts to the HTTP server's responses, including response codes, header fields, and such. I found the mockwebserver library that looks just like something I need. However, in order to use it, I would need to somehow change the URL that the class connects to.
The only sensible option that I see is to pass the URL in the constructor : however, it seems to me that this does not play too well in terms of design, since requiring the client to pass an URL to such a class looks fishy. Furthermore, I have not seen any other web service access libraries (Twitter4J, RestFB) that would require their clients to pass the URL in order to actually use them.
I'm not a Java whiz, but I'd like to get it as right as possible. All answers welcome.
What is fishy about passing the URL? Not sure I get that.
Generally for things like this, don't you want the URL to be a property? I would think in the same way that the database url for your instance is going to be constructed of properties, you would want to do the same here. In which case, in your test you just override the property/ies.
The other interesting thing about these kinds of tests is I think it's a really good idea to have tests of the actual protocol (which is what you are doing with the mock) and also the actual service and then run the service tests on a schedule, just as a way to make sure that the downstream services you are consuming are still there and honoring their end of the contract. Was reading the excellent Continuous Delivery book from Addison Wesley, contemplating making this part of a pipeline today.
if you have written your tests first, you would have never written such code :)
your class violates single responsibility rule. refactor this class. extract part responsible for networking (in your code - getting connection). then ServiceAccess should use that class. then you can easily test ServiceAccess in unit tests. unit testing networking code is pointless - guys from oracle have already done that. all you can test is that you have provided correct parameters and that's the role of integration tests
Iff you can't change the code, you could use PowerMock to mock HttpURLConnection.
I'm a newbie in Liferay and I'm creating a hook to authenticate using a expando column instead of an email address.
My authentication class works fine, but one problem still remains:
After a successful authentication, I must redirect the page to the user's public or private page (any of theese is enough for me)
I followed the common of instructions for this on any forum on Internet:
Create a class that extends com.liferay.portal.kernel.events.Action and do the logic there. In my case, my class is named CustomPostLoginAction
Modify portal.properties adding the entries
login.events.post=com.liferay.sample.hook.action.CustomPostLoginAction
auth.forward.by.last.path=true
default.landing.page.path=/web/guest/home
Redeploy and "voilá"
When I reboot my web server, everything is fine, but when I run my hook using any browser, once I get successfully authenticated, it stills showing me the default login error messages. When I check my console, I found that my action class is never called and no special action is executed after my authentication class. So I have the following questions:
Where can I found an example to class to be used as a value for the property "auth.pipeline.post" if needed?
On the method authenticateByEmailAddress on my authentication class, the last argument is a java.util.Map containing parameters like "doActionAfterLogin", "redirect", "structsAction", etc. Do I get something if I assign values to those keys on that map? If yes, where can I found an example of valid values to assign to each one of them?
Do I have to change something in my custom login page? (it works, but still I have to ask this)
Is it necessary to work with the class DefaultLandingPageAction? If yes, how can I do it? Because I have only the portal's bytecodes (.class)
And most important: What am I doing wrong?
For the record:
I'm using Liferay 6.1 bundle with Tomcat 7 and SDK included with Liferay's default database.
If any of you need to watch any of my source code and/or properties files, just let me know and I will publish them.
Thanks in advance to all of you.
I can't add a comment to your original post so I'm gonna have to post an answer to ask you for some additional information (will update my answer accordingly).
Did you modify portal.properties directly or did you create a new portal.properties inside your hook?
Once you extended com.liferay.portal.kernel.events.Action, did you override the run method?