Is it possible to make a web application which uses JAAS authenticate via tomcats default authentication method.
To illustrate: Tomcat uses the tomcat_users.xml for authentications. The web application has defined its own method in jaas.cfg. How do we configure the jaas.cfg in such a way that it uses the Tomcat's method in so that when the configuration in Tomcat changes the application's authentication method switches aswell.
Current config looks like this:
BonitaAuth {
org.ow2.bonita.identity.auth.BonitaIdentityLoginModule required;
};
BonitaStore {
org.ow2.bonita.identity.auth.LocalStorageLoginModule required;
};
BonitaAuth-default {
org.ow2.bonita.identity.auth.BonitaIdentityLoginModule required domain="default";
org.ow2.bonita.identity.auth.LocalStorageLoginModule required domain="default";
};
BonitaStore-default {
org.ow2.bonita.identity.auth.LocalStorageLoginModule required domain="default";
};
/**
* Used by the REST server
*/
BonitaRESTServer {
org.ow2.bonita.identity.auth.BonitaRESTServerLoginModule required logins="restuser" passwords="restbpm" roles="restuser";
};
The Tomcat user repository is defined by Tomcat Realms.
The tomcat_users.xml file is used by MemoryRealm.
To use your JAAS configuration (jaas.cfg) configure JAASRealm:
http://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#JAASRealm
It is possible to use Java EE authentication and implement your own realm.
You have 3 options:
implement Tomcat Realm interface
http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/Realm.html
Extend RealmBase
http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/realm/RealmBase.html)
Extend JAASRealm
http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/realm/JAASRealm.html
Configure your own realm in server.xml
<Realm className="org.myrealm"/>
Tomcat will call to your authenticate method http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/realm/RealmBase.html#authenticate%28java.lang.String,%20java.lang.String%29
In the method you can call your JAAS authentication.
Related
I have this service
#ApplicationPath("/services") public class MyRestEasyApplication extends Application {
Packeged package bitsexcel.ws.resteasy.services; My project is named RsJavaWeb and run in this url http://localhost:8080/RsJavaWeb/ on Wilfly Server
I have not web.xml descriptor with nothing except <welcome-file-list>
I can't find my service in any url
I tried with:
http://localhost:8080/RsJavaWeb/services/person/1
http://localhost:8080/RsJavaWeb/ ?
And ever more but I can't find the service
Find the context root of your application (you can see it from WildFly UI console).
Then you should send requests at http://localhost:8080/{context-root}/services/...
I'm writing some tests with the codeception REST module.
The project I'm working on is in the early stages and we haven't implemented token-based authentication yet; so for now the authentication is done via a REST API but it uses $_SESSION for persistence.
To test authenticated requests I need to keep the PHPSESSID cookie and send it with every request. Is there a way to read/set cookies when working with the REST module?
Ok I got the solution. My suite name is api, so codeception generated a file at tests/_support/Helper/Api.php. Before making changes here, I had to edit my suite YAML file api.suite.yml to enable the helper. My YAML file looks like this:
class_name: ApiTester
modules:
enabled:
- REST:
depends: PhpBrowser
url: https://website.com/api/
part: Json
- \Helper\Api
Now that the file is enabled, run codecept build so that it updates the generated files to read your helper.
In the Api helper class, I added two methods:
public function capturePHPSESSID()
{
$cookie = $this->getClient()->getCookieJar()->get('PHPSESSID');
echo "Cookie: ", $cookie;
}
/**
* #return \Symfony\Component\HttpKernel\Client|\Symfony\Component\BrowserKit\Client $client
*/
protected function getClient()
{
return $this->getModule('REST')->client;
}
This is all that you need to read the PHPSESSID cookie! Feel free to capture it so you can then write a method to re-use it by setting calling $this->getClient()->getCookieJar()->set(....)
Some pointers more than anything required here.
I'm trying to get both X509 and LDAP working in my application. I want users to be authenticated using their PKI certs and then for the APP to get their authorities from our LDAP server.
I have LDAP working with a customer userDetailsContextMapper at the moment however how to add the x509 properly stumps me a little.
I think what I want is a PreAuthenticatedAuthenticationProvider that uses an injected ldapUserDetails service.
How can I do that? Do I need a UserDetailsByNameServiceWrapper to wrap the LdapUserDetailsService up to be used within the pre-authentication provider?
I ask because unfortunately the testing platform and the development environment at the moment is detached, and I don't have local LDAP or PKI set up to test against so its about a 6 hour process getting a new war onto the dev environment... Restrictive I know... So I want to get it right first time.
Cheers!
NOTE: THE FOLLOWING WORKS WITH Spring-Security-Core v1.2.7.3, Configuration names are different in 2.0RC2
Following a few different ideas, this is what I came up with. This assumes you already have LDAP working with a custom and UserDetailsContextMapper (see: ldap documentation):
Ensure both the LDAP and a PreAuthenticatedAuthentication Provider are in the provider list:
grails.plugins.springsecurity.providerNames = [
'preAuthenticatedAutehnticationProvider',
'ldapAuthProvider',
'daoAutehnticationProvider',
'anonymousAuthenticationProvider',
'rememberMeAuthenticationProvider']
Then in your spring resources (grails-app/conf/spring/resources.groovy) configure the following beans:
ldapUserDetailsService(org.springframework.security.ldap.userdetails.LdapUserDetailsService,
ref('ldapUserSearch'),
ref('ldapAuthoritiesPopulator')) {
userDetailsMapper = ref('ldapUserDetailsMapper')
}
userDetailsByNameServiceWrapper(org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper) {
userDetailsService = ref('ldapUserDetailsService')
}
preAuthenticatedAuthenticationProvider(org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider) {
preAuthenticatedUserDetailsService = ref('userDetailsByNameServiceWrapper')
}
And bobs your uncle and you have some aunts!
For reference the pages I used to come up with this solution are:
No AuthenticationProvider found using spring security
Wrap your LdapUserDetailsService in a UserDetailsByNameServiceWrapper
Instead of the LdapAuthenticationProvider configure a PreAuthenticatedAuthenticationProvider that will be able to process the PreAuthenticatedAuthenticationToken issued by your CustomX509AuthenticationFilter.
Inject the wrapped LdapUserDetailsService into the PreAuthenticatedAuthenticationProvider.
http://blog.serindu.com/2011/05/26/grails-spring-security-using-preauthenticated-authentication-provider/
Covers how to wire up a preAuthenticationAuthenticationProvider in grails
http://forum.spring.io/forum/spring-projects/security/108467-combine-pre-authentication-with-ldap-for-user-details-and-authorities
there's an LdapUserDetailsService that does all the good things the LdapAuthenticationProvider does - except for authentication
http://pwu-developer.blogspot.co.uk/2012/02/grails-security-with-cas-and-ldap.html more on how to wire up that ldapUserDetailsService
Hope this helps someone else!
I've developed a REST api for my Symfony2 application. This api will be used by a mobile app. Much of the functionality is done in the context of the currently authenticated user, ie:
$this->container->get('security.context')->getToken()->getUser()
I'm hoping that the mobile app will be able to post to the login action just like a traditional web form. If the credentials check out then Symfony2 does it's thing and sets a cookie (does this even work in the context of a mobile app accessing an api?). Then later api requests from that mobile phone will (hopefully) work with the native symfony2 security.context service container.
Would this work? I need to figure out this authorization process before I take the API to the mobile developers. If possible I'd obviously like to be able to use the native security.context service instead of building out a new auth system for the api that uses xAuth or something similar.
Thanks
I think you should do it stateless (without cookie).
I had the same problem, what i did:
in your app/config/security.yml, add:
security:
...
firewalls:
rest_webservice:
pattern: /webservice/rest/.*
stateless: true
http_basic:
provider: provider_name
...
Now you can make a request to your webservice:
class AuthTest extends WebTestCase
{
public function testAuthenticatedWithWebservice()
{
$client = $this->createClient();
// not authenticated
$client->request('GET', '/webservice/rest/url');
$this->assertEquals(401, $client->getResponse()->getStatusCode());
// authenticated
$client->request('GET', '/webservice/rest/url', array(), array(), array(
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'password'
));
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
}
Here you are, How to create a custom Authentication Provider awesome article.
To Authentication to a Symfony2 application through api, you need use:
WS-Security
Yes Marc, jules is pointing to an example just to show you how to test authentication with http_basic.
To be RESTful you should avoid using cookies, otherwise just call it an API. About how secure is your authentication system you can go with http_digest over https or more secure signed request with api_key/api_secret approach.
Have a look here http://wiki.zanox.com/en/RESTful_API_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.