How to propagate spring security login to EJBs? - authentication

Context
I have a J2EE application running on a JBoss 4.2.3 application server. The application is reachable through a web interface. The authentication is done with basic authentication. Inside of the EJBs I ask the security context of the bean for the principal (the name of the logged in user) and do some authorization checks if this user is allowed to access this method of the EJB. The EJBs life inside a different ear than the servlets handling the web frontend, so I can't access the spring application context directly.
Required change
I want to switch to Spring Security for handling the user login.
Question
How can I propagate the spring login information to the JBoss security context so I can still use my EJBs without having to rewrite them?
Ideas and links
I already found a page talking about "Propagating Identity from Spring Security to the EJB Layer", but unfortunatelly it refers to an older version of Spring Security (Acegi) and I'm not familiar enough with Spring Security to make this work with the actual version (3.0.2).
Here is something that looks similar using WebLogic.

If you properly configure spring-security (filter in filter chain, security-context.xml),
you may use annotation #Secured, to restrict users with needed user roles. You may use this annotation on class level or/and method level.
If you need to know all authorization info about current user, you may use this helper (i wrote this for my webapp, but it maybe useful for other. MyUserDetails is a service bean, the spring-security's UserDetail descendant.):
public class LoginHelper {
/**
* #return user object if user is authenticated and null if is not
*/
public static User getUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Object principal = authentication.getPrincipal();
if (principal instanceof MyUserDetails) {
return ((MyUserDetails) principal).getUser();
}
}
return null;
}
/**
* Check for authenticated user
*
* #return true if user is authenticated and false if is not
*/
public static boolean isAuthenticated() {
final User user = getUser();
return user != null;
}
}

I have the same issue, and it would be great if someone could think of a better way to integrate Spring Security and a Java EE application with EJBs.
I think you can annotate your classes with your own annotations such as #MyAnnotation("ADMIN"). And then create an interceptor to manually check the beforementioned "LoginHelper" to get the users's privilege and compare with the method's annotation attributes. And throw an exception when the Names don't match.

Related

OAuth2 (Okta): How to set authorization

I'm writing an application using Oauth2 using Okta, and I'm running into a problem:
What I would like to do is have Okta (or some other method) to automatically set up and provide authorization details of my user. I already have Okta able to support authentication of the user, I am specifically looking for help regarding authorization. In particular, what I would like to do is divide authorization of my APIs into 3 segments:
1) A group of APIs which are available to any user, even ones who are not authenticated.
2) A group of APIs which are only available to authenticated users.
3) A group of APIs which are locked under permission-based (authorization) requirements.
It's the 3rd group I'm having trouble with. I have my security context set up as follows:
#Configuration
#EnableOAuth2Sso
public class SecurityConfig extends OAuth2SsoDefaultConfiguration {
public SecurityConfig(ApplicationContext applicationContext) {
super(applicationContext);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/anyaccess/**").permitAll()
.antMatchers("/credential/**").hasRole("ADMIN");
super.configure(http);
http.logout().logoutSuccessUrl("/");
}
}
So /anyaccess can be accessed by anyone, and anything else except /credential can be accessed by any authenticated user.
When I log into my application through Okta, I get an Authentication and Principal object which seem to be automatically generated somewhere, somehow (it's this somewhere, somehow that I'm mostly looking for clarification on). However, those objects do not have any set permissions, nor do they appear to provide a way to add additional permissions for future requests. How can I:
1) Set up these Authentication and Principal objects to contain the permissions I want per user?
2) Make sure that these are set up automatically on user sign-in through Okta and don't require an additional API call?
3) Persist changes to this configuration and make that part of my application authorization service?
4) Is there any way I can manage this through Okta configuration, or so I need to have a separate service set up to manage this and tack that onto my Okta authentication service?
Thanks.
You can add user's groups to a "groups" claim and the Okta Spring Boot starter will automatically convert those to Spring Security authorities.
From the top menu, go to API and click on Authorization Servers.
Click on the default authorization server.
Click on the Claims tab.
Click the Add Claim button.
Update the popup form to match the image below.
Note that the Filter Regex is .*.
Then you can use #PreAuthorize("role_name") on your methods.
This blog post has more information.

Simple custom authenticator in JAX-RS

In JAX-RS (or Jersey) REST service, I'm trying to make custom authentication for my users in database.
Currently I have #GET annotated method which should interact with user asking for credentials just like it is done in Spring framework with authentication provider - no custom login form, just plain HTTP login with browser popup form.
Currently I can handle HTTP Basic Access Authentication provided in header, but I need to ask for credentials before accessing content interactively and then make token-based authentication on this base.
I have to keep the application light-weight but I don't know how can this "easy" task be done..
Edit: I found something in Wildfly configuration (I'm using 9 Final version) but I don't know how to use it for login using datasource..
If you already can handle HTTP Basic authentication, then you only need to get a a "login form" from the browser? We solved this by implementing an javax.ws.rs.ext.ExceptionMapper and overriding toResponse(Throwable ex). Our app throws a NotAuthenticatedException which gets mapped to javax.ws.rs.core.Response.Status.UNAUTHORIZED. Then we add a response header appropriately:
#Provider
public class RESTExMapper implements ExceptionMapper<Throwable>
{
#Override
public Response toResponse(Throwable ex)
{
//our application maps a not logged in exception to javax.ws.rs.core.Response.Status.UNAUTHORIZED in this Pair
Pair<Integer, ObjectMap> ret = buildResponse( unwrap( ex));
ResponseBuilder rb = Response.status( ret.left()).entity( ret.right()).type( "application/json");
if( ret.left() == UNAUTHORIZED.getStatusCode())
return rb.header( HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"YOUR SERVICE NAME\"").build();
else
return rb.build();
}
The important part is setting the response header if the user is not logged in, that makes the browser display the HTTP Basic Login Dialog.

ServiceStack - prevent unauthorized access to static files

I understand there is more than one way of handling service authentication/authorization, but I cannot make it work for static files.
Is there a way of configuring the behavior to be the same as with services; if not authenticated a request to index.html should redirect to login page the same as a request to secured dto/service.
I am currently looking into RawHttpHandlers but since it is too early in the pipeline how do I get the authentication setup in the apphost config?
thanks in advance
Gjergji
You would have to use IAppHost.RawHttpHandlers because that's the only custom handler in ServiceStack's Request Pipeline that gets executed before the built-in static file handling is accessed.
But you should still be able to access the Users Session with the available extension methods, e.g:
this.RawHttpHandlers.Add(httpReq =>
{
var isStaticFileRequest = httpReq.PathInfo.StartsWith("/static");
if (isStaticFileRequest)
{
var session = httpReq.GetSession();
if (!session.HasRole("TheRole"))
return new ForbiddenHttpHandler();
}
return null;
});
This handler simply checks if it's a request for a static file, in this case the path info starts with /static, and if is checks the user session if they have the required role, if not it returns a Forbidden request, otherwise it returns null to tell ServiceStack to continue executing the request.
Note: if it's needed you can access any registered dependency from outside of ServiceStack with HostContext.Resolve, e.g:
var authRepo = HostContext.Resolve<IAuthRepository>();

Authenticate against EJB via RESTeasy webservice

I am trying to setup a REST-webservice with RESTeasy that access EJBs that are deployed on a JBoss 7.1.1.
I've been successful in:
Setting up Beans to be accessed via REST
Configuring SSL for the connection
Setting up a PreProcessInterceptor that uses HTTP Basic Auth to ask the User for his credentials.
Currently I basically just check the credentials hardcoded in the interceptor.
This works to make sure that the User is authenticated, but our Beans query for the name of the currently logged in Principal for some Beancalls like this:
#Resource
private SessionContext context = null;
[...]
String userName = context.getCallerPrincipal().getName();
Currently userName is now always anonymous. What is the right way to set the caller principal? Do I do this in an Interceptor? Or in the Bean itself? My goal is to basically be able to call a method loginUserWithEJBOnJboss(String user, String pass) that uses the login-methods that are configured within the jboss and sets the principal correctly.
I am at a loss here, google didn't find anything. Maybe I am just searching for the wrong words.
So yeah, as always soon after asking I find the solution myself. I think sometimes I only ask because I know this will happen.
So the solution are these methods:
SecurityContextAssociation.setPrincipal(new SimplePrincipal(username));
SecurityContextAssociation.setCredential(password.toCharArray());
They do pretty much all I wanted :)

How to secure my Restful api created in the play framework

I want to add user authentication to my restful api that I have created using the Java based Play! framework.
I currently have the Web based (browser accessed) app secured using the 'secure module' Details here: http://www.playframework.org/documentation/1.1/secure
Can I use the same module for authentication for when the restful apis are called directly via http requests?
If not, I would appreciate some pointers to tutorials/module for integrating another auth method (hopefully one that can apply to both web app access from browser and also http api access).
PS It would be nice to avoid doing HTTPS and digest if possible.
If you are already using a username/password mechanism adding http basic authentication for your API calls should not be difficult. You can create an interceptor that does something like:
public class ApiInterceptor extends Controller
{
#Before
static void checkAccess() {
if ( request.user == null || request.password == null) {
unauthorized();
}
boolean canAccess = .... ;// check user and password here
if ( !canAccess ) {
unauthorized();
}
}
}
But this means that you need to use SSL since the username and password go in clear text over http.