Preprocessing a REST request for BASIC authentication on tomcat + JAX-RS - java

I'm developing a REST api and i want to use apply BASIC authentication on it.
What i want to do :
Intercept request for methods like GET, PUT, POST, DELETE.
Fetch username and password from authorization header.
Authenticate User by validating UserName + Password from database.
Accordingly allow or deny access to service.
I'm using Apache Tomcat 7, JAX-RS for this project.
So what is the best way to achieve this?

Write a ServletFilter to intercept all the incoming request to your REST web services. Depending on the authentication, doFilter the request to your REST webservice or deny with 401.

Related

Bypass basic authentication for only frontend application

I have a frontend application written in React and a backend application written in SpringBoot. I have implemented basic authentication in the backend application(for all endpoints) using Spring Security. So now a username and password are required to access every endpoint.
Requirement :
I don't want to pass a username and password from the frontend application to access backend application endpoints so basically, I want to bypass basic authentication for my frontend application.
If someone wants to access any endpoint outside my frontend app for example Postman, RestTemplate, etc then a username and password are required.
For example -
if the request is coming from www.abc.com (frontend app URL) then basic authentication should be bypassed for all endpoints but if the request is coming from www.xyz.com, Postman, RestTemplate, or any other client then basic authentication should not be bypassed.
I know how to bypass authentication on a specific endpoint within the backend application but I don't know how to bypass authentication for the requester, I did research over the internet as well but not found something useful. Looking for working code to fulfill the requirement.
If you use some kind of reverse proxy (e.g. nginx) to serve your frontend, you can set the basic authentication parameters there.
e.g.
location / {
...
proxy_pass http://127.0.0.1:8080;
proxy_set_header Authorization "Basic TOKEN";
}
where TOKEN = base64(username:password)

Java: Authenticate user from JAAS protected Restful API (Jersey) on Glassfish

I have implemented a Restful API for my simple application using Jersey, this API (Restful webservice) is protected by JAAS (Java Authentication and Authorization Service).
Now if user try to access a URL something like example.com/api/user/info/1, A popup(BASIC-Authentication) appears in browser to take input for username and password on successful login user is able to see the result (success).
so far so good.
Now I was thinking about the 3rd party application that will access my Restful web service. must authenticate before accessing any endpoint. (I know if an un-authenticated user will try to access my endpoint URLs JAAS will intercept that).
I am also aware that if I provide username and password in the request header, JAAS will automatically authenticate that as well.
Confusions:
1 - I do not want to embed username and password onto each request (I am not suer why, but I just don't want it (Please share your comments)) so that if I am accessing secure endpoint get authenticated automatically. I just want to authenticate a user and generate a token and then use that token in rest of the communication.
2 - I want to provide some endpoint for 3rd party applications to deliberately initiate the authentication process.
example.com/api/authenticate but the username and password still in header. and when endpoint's relative method is called it extract username and password from that request's header. I am aware of 2 annotations #QueryParam and #FormParam, but I want something like #HeaderParam.
Why? I think that is more secure way. (Is that right?)
#Path("authenticate")
public String authenticate( ) {
}
3 - I tried multiple techniques to login programmatically but none seems to work on Glassfish, so is it right its not possible on Glassfish? I am using Realm based JAAS.
4 - I am looking for some way once I have authenticated the user prorgammatically, add some information to the session. and in any other request get that information from session. (I am using Jersey based classes for endpoints and EJBs for business logic) - I know in EJBs through context we can lookup principal and then from that we can retrive the user record from database etc. but is there any thing Jersey Endpoint classes can add to the session and get them back in any other endpoint class?
5 - Is it enough for 3rd party application to save cookies returned by my Webservice and embed them in next request to have long lasting session for JAAS authenticated user (so that authentication process may not be required on each request)

Sample about RESTful and Shiro Integration

I am developing a Java web application using RESTful as web service. And now I want to apply Apache Shiro to secure my application. The mechanism is: after user logged in successfully, a token (combined from username, password and logged time) will be returned to client. Then every single REST request will attach this token to authenticate at server (no need to authorize). But now I dont know how to configure to accept this.
And by the way, could you please give me any sample about Shiro & RESTful integration? Thank you
If the REST application and the Java web application are the same Webapp, then you only need to check subject.isAuthenticated(). Use a session cookie without the password or username (it isn't a good idea to be passing around the password as it could be stolen).
Most of this behavior comes by default if both parts are in the same Webapp.
In your REST method you'd have something like:
Subject subject = SecurityUtils.getSubject();
if(subject == null || !subject.isAuthenticated()) {
return 401; // Not Authorized
}
Hope that helps.
In addition to the above response, you can send back a token (session-id) from your REST Server, post successful login. Your iOS/Android application will then need to store this, and send this with every REST request it makes. Here is sample of what your post login REST response can be:
session-start-timestamp: 1394683755389,
session-timeout: 1800000,
session-id: "068C8E0E289788A7ABC5FE47B2CC0D28"
The session-id will be maintained by your REST Server, and its TTL will be reset every time a new request with this id comes in.
On browsers, this id gets sent automatically. For your case, you would want to send it explicitly with each HTTP request (which is what REST request is)
Hope this helps

Disable redirect to last accessed resource on form login Glassfish

I'm going to rewrite my previous question.
Glassfish redirects after form login to the last accessed resource, how do I go about to turn this off?
Our problem is that we get 415 in FF and IE because if I have a JSESSION cookie Glassfish will redirect to the last resource I tried to access but does not switch content type from (x-form-urlencoded).
Pseudo example (requests are the browsers' XMLHttpRequest):
GET /secure/resouce1 (json) -> Response "you're not logged in."
GET /login.xhtml
POST /j_secure (x-form-urlencoded) -> New location /secure/resource1 (x-form-urlencoded)
GET /secure/resource1 (x-form-urlencoded) <- HTTP ERROR 415 content type not JSON.
You will probably need to write a Filter to check for and catch that case. I like this tutorial (hoping the translation to English is understandable).
In my opinion it is better to use Basic or Digest authentication over SSL for RESTful services. Other options are including the credentials as part of the payload or creating a dedicated login service, which accepts credentials and returns a token. There are various reasons why form based authentication is less suitable for RESTful service: it requires a session, it does not use the existing HTTP Authorization and more.
If you need to call your RESTful service using AJAX then using a cookie for authentication can be a valid solution. They should only affect if the user can make a call, but not how the server responds.
If you would like to keep using form based authentication for your application I would suggest adding an additional JAAS authentication provider which will handle the RESTful services authentication. You can read more about it here.
Another option, which should be easier than JAAS, would be using Spring Security or Apache Shiro instead of the container based authentication.
Here is an example of configuring form based authentication with Spring Security. This post shows an example of how to secure RESTful services using Spring Security.
in your login page
reset the JSESSIONID cookie to prevent redirect last page
// login_form.jsp
Cookie jsess = new Cookie("JSESSIONID", null);
jsess.setMaxAge(0);
jsess.setPath(pageContext.getServletContext().getContextPath());
response.addCookie(jsess);

Restful Java - Grant access to resources

I developing a resful webservice that will have differentes resources (the application database stores urename and password).
On the other and I have a client that can access to those resources. To access to some of these resources the client must be registered (existing in the database). Im using GAE as application server and Jersey to create the Restful WS, so my question is what is the best way to access this resources?
I thought in sending the username and password in the WS request (as POST) and then check if the couple exists in the db and answering at the request.
Do you think this kind of authentication is secure (I dont think I can use https on GAE)?
Thanks in advance fo the responces
Danilo
You should be using OAuth 1.0 or 2.0
You might want to use some form of transport layer security such as SSL to secure your service.
Also, REST tries to make use of HTTP features, so you could put a Authorization header in the HTTP request.
Edit: a simple example
Transport Layer Security
Go to one of the many companies that sell SSL certificates, for example Verisign. Buy a certificate. Install it on your web server. You web server will have documentation on how to install it.
Using HTTP authorisation
Get the client of your web service to use BASIC authorization (they are passed in plaintext so you've got to be using SSL for this to be effective). This involves putting the BASE64 encoded username and password in the Authorisation header. Write a security Filter and configure your web app to pass all requests to your RESTful service through the filter. Your security filter should extract the username and password from the request Authorisation header and check them. If the credentials are invalid you reject the request with a 403 status code. If the credentials are OK, just propogate up the filter chain.
public MySecurityFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
//Get the Authorizatiuon header
String auth = ((HttpServletRequest)request).getHeader("Authorization");
//Extract the username and password
if (checkCredentialsOnMyDatabase(credentials[0], credentials[1])) {
chain.doFilter(request, response);
} else {
//Reject the request with status code 403
}
}
}
Also note that if you are using one of the popular frameworks like Jersey then it has a lot of security functions built in that may help you.

Categories

Resources