I have a nearly finished web project with EJB3.1 deployed as WAR in Wildfly 8.2. It´s secured by a self-written JAAS-realm with form authentication (auth-method FORM).
Now I want to add a EJB-Webservice which is basically defined as
#Stateless
#WebService
public class ProductImportWebservice {
#Resource
WebServiceContext wsContext;
[...]
#WebMethod
public Product createOrFind(String name) {
[...]
}
}
The webservice works as expected but now I have the problem that I want to protect access to the Webservice by username/password.
So I annotated the webservice or the #WebMethod with
#RolesAllowed("ADMIN")
which is a valid role in the JAAS-authentication.
Effect: The SOAP-client gets the answere "reqeust not allowed / not authenticated" - but gets no authentication-request and attempts with BASIC-authentication are ignored.
If I add the URL of the webservice to the security-constraint in the web.xml I get an authentication request... but the problem now is that it´s the form based authentication - as a user with a browser would expect it. This is unusable for a "normal" SOAP-client :-(
The concrete question now is: Is there a way to have both - BASIC authentication for the webservice and FORM-based authentication for the rest of the application?
The only other way I would see is to split the WAR package up to an EAR-package and deploy the webservice in a different web-context.
The concrete question now is: Is there a way to have both - BASIC
authentication for the webservice and FORM-based authentication for
the rest of the application?
You can't use both FORM and BASIC authentication for the same web application.
If you need to do this, create two separate applications, with a shared codebase.
Reference:
https://docs.oracle.com/javaee/7/tutorial/security-webtier002.htm#JEETT01227
The auth-method subelement configures the authentication mechanism for
the web application. The element content must be either NONE, BASIC,
DIGEST, FORM, or CLIENT-CERT.
Related
Hello I recently received a demand to migrate the ldap authentication service to oauth2 from a jsf project, but I have no idea where to start, from what I've been seeing in the project I have an ldap security domain configured in wildfly where I can make use of some features that comes from FacesContext as:
.login(username, password)
.getUserPrincipal()
.isUserInRole(rule)
.logout()
.invalidateSession()
What I would like to know is if there is a possibility to make my own security domain the same as the configured ldap, where I would implement the methods above, any content where I can start is welcome
I made an implementation of org.jboss.security.auth.spi.UsernamePasswordLoginModule;
I wish to use Spring Security (version 5.1.2) to generate a CSRF token for my Angular 7 application. I have the following in my SecurityConfig file:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
with the following RequestMapping in my controller:
#RestController
#RequestMapping("/authentication")
public class AuthenticationController {
#GetMapping("/csrf")
public void getCsrfToken(){...}
#PostMapping("/register")
public RegisterOutputDTO register(#RequestBody UserDTO input){...}
}
I gathered from various sources that the csrfTokenRepository would automatically generate a cookie with header XSRF-token on my first GET call (which is what /authentication/csrf is for), but I am not getting a cookie back from the server. Hence on my next POST call I am getting a 403 response. What could I possibly be missing?
As indicated on the comments to my question, I found the answer to my problem. A cookie can not be sent cross-domain.
My frontend was deployed on localhost:3000 and my backend on localhost:9080, which are considered different domains apparently. If I go to localhost:9080 (I get a white page, but that doesn't matter) and I then go to the application tab in Chrome, I find that the XSRF cookie I was looking for is stored like I was expecting all along. The cookie was available from the GET call I executed from my front-end. The problem is that the cookie needs to be available for localhost:3000 so that Angular can make use of the cookie.
There are multiple ways you can solve this issue in your local environment.
Use a proxy
You can use a proxy to map certain url paths to your backend. This is the solution I went with.
I run my Angular application with a webpack dev server. Webpack provides an easy way to proxy certain urls to your backend. For example:
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 3000,
proxy: {
'/api': 'http://localhost:9080'
}
}
The Angular application runs on localhost:3000. Any calls to localhost:3000/api/*. will be forwarded to localhost:9080/api/*. So in my case I no longer perform a GET call on localhost:9080/api/authentication/csrf, but I call localhost:3000/api/authentication/csrf which will then get forwarded to my backend. (I added /api to the path in my rest controller, for those wondering.)
Deploy both applications on the same port
Using the frontend-maven-plugin you can build the frontend to its dist folder and then let maven package the dist folder along with the backend for deploy. I haven't tried this, but there are various resources that show this should be easy to do with Spring boot. So both frontend and backend would be available through localhost:9080 for example.
Use Spring Profile to disable csrf locally
You can make use of Spring #Profile annotations to create a different configuration for local environment and the rest (test, acceptance, production). Csrf can simply be disabled for development. I do not prefer this option since I like to keep DEV and other environments the same as much as possible. It's also not a real answer to the problem statement.
Special thanks to the answer of user #dspies which helped me find the problem.
I am building a web application using an AngularJS front-end and a Spring Boot REST back-end (they are running on separate servers i.e. port 3000 and port 8443). The back-end is supposed to connect to multiple external services (with separate authentications) and provide endpoints for the front-end to use.
For security, I decided to use Apache Shiro. For simplicity, I will pretend there are just 2 external services (ES1 and ES2).
I have created 2 x AuthorizingRealm which connect to the respective external services and attempt authentication using the provided tokens.
In the doGetAuthenticationInfo method, if the login is successful, I return a SimpleAuthenticationInfo with the principal, credentials and the name of the realm.
In the doGetAuthorizationInfo method, I check the realm name of the principal and, if it checks out, I return a SimpleAuthorizationInfo with the role "USER" and a permission (e.g. ES1_permitted).
I also extended the UsernamePasswordToken class for each realm to separate usage even more (through the supports method).
In a configuration class, I create a bean for a DefaultWebSecurityManager that uses my two realms and a bean for the Shiro filter.
I added 4 filters:
anon AnonymousFilter
perm PermissionsAuthorizationFilter
es1 ES1Filter
es2 ES2Filter
My filter chain looks something like:
/api/es1/login -> anon
/api/es1/** -> es1, perms[ES1_permitted]
/api/es2/login -> anon
/api/es2/** -> es2, perms[ES2_permitted]
/** -> anon
Somehow, when I served front-end and back-end from the same server (no CORS), it seemed to work. However, now that CORS is an issue, I can't seem to get this to work as expected.
Is there a simpler way to achieve this complete separation of authentication/authorization? I am willing to switch to Spring Security if it can be done there as well.
PS: I am using the Java API, not configuration files (spring xml or shiro.ini).
I am using Spring4 with Spring Security 3.2.4.
I have some http configurations in my security configuration in order to host form based authentication and REST services (with authentication) together.
For the pages and REST services which require app-authentication everything works fine with my current configuration but for the pages which does not require authentication, such as login and register, the anonymous authentication is not initialised somehow. Speaking in Java:
SecurityContextHolder.getContext().getAuthentication() returns null.
I expect that anonymous authentication is initialised as the documentation (http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#introduction) refers:
Anonymous authentication support is provided automatically when using the HTTP configuration Spring Security 3.0 and can be customized (or disabled) using the element. You don’t need to configure the beans described here unless you are using traditional bean configuration.
Does anyone have an idea why does it not happen although the documentation refers? (Beside the fact, that the documentation for 3.2.4 refers to 3.0 version and some of the given configuration suggestions refer deprecated implementation)
I tried using Basic Authentication by changing the server.xml config of Tomcat 6.0 but it did not worked: BASIC authentication in jersey JAX-RS service and Tomcat 6.0 getting failed
Hence I am opting a way where no server specific config is needed and I can add up the roles directly in my code (either client or server; not sure about theavailable options).
Please provide me some ideas about the possible options for setting the user roles so that I can authenticate my Web Service methods using the #RolesAllowed annotation.
You need to go back and figure out why your security constraints weren't working. Maybe start with the default file realm before moving on to JDBC realms. #RolesAllowed in an annotation that triggers behavior in the container.
If you really want to do it yourself (a bad idea) they you'd probably start by creating a custom servlet filter that implemented the entire basic http challenge mechanism. Next you'd have to replace the SecurityContext provider in Jersey.
They "thing" that enables #RolesAllowed in jersey is this: http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/RolesAllowedResourceFilterFactory.java Which, by the way, don't forget to add as an init-param to your jersey servlet. The RolesAllowedResourceFilterFactory gets its security info from an injected SecurityContext which I'm sure at some point just delegates off to the Servlet API for credential info.
So basically if you don't want to take the time to get security constraints working you are going to end up replacing most of the chain...like I said, a bad idea.
The features on application servers are there to keep you from having to spend time creating infrastructure code, if you write your own infrastructure code you're going to have a bad time.