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

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)

Related

Secure Rest-Service before user authentification

I have a web application that provides several rest services (Jersey). Most of the endpoints are secured by BASIC authentification. Further more I use SSL for transport and demand POSTs for every call.
The clients/consumers are android apps.
So far so good. The only service that seems to be vulnerable is the registration. It's the 'first' service to call and a user does not exist yet. So I cannot use OAuth, etc. I also have to keep the endpoint easy accessible to enable the user to regster.
How do I secure this service, so it's not spammed by a bot flooding my database?
How about these?
Use a registration link with a token in the request parameter. Ensure that the tokens expire after sometime. You could create a token endpoint url as well for a client to get a valid token.
Use a custom header or a dynamic custom header in your request. Additionally, you could check for a dynamic custom header to validate the request's authenticity.
Use registration confirmation workflows, such as an email / text verification as soon the registration is done. Run a process every day to delete any user accounts, which are not validated in say x days.
I do not think you can really secure the registration URL in a HTTP way. IMHO, anyone who has the registration url can be a right guy trying to register. So if you ask me, option 3 is better than others.

How to authenticate (login / logout) in RESTful web application in Spring?

I would like to authenticate with
http://myhost/login?user=...&password=...
and logout with
http://myhost/logout
I am using Gradle, Spring Boot and Java config, so no web.xml, no context configurations, no web forms and so on.
Can't escape from google noise on multipage and multifile samples...
Have you considered using a servlet filter? Seems like what you want to do for passing the username and password as http parameters. Otherwise, you might also consider HTTP BASIC authentication. It passes the username and password in the http headers using base64 "encryption". Of course, complete website security is a different discussion.
See this example of using HTTP BASIC authentication.
One approach is using tokens.
The login service would accept the credentials, generate a token (a UUID type 4 for example, see https://en.wikipedia.org/wiki/Universally_unique_identifier), store the token in a table and return it.
In every call, the client would have to send the token in the header or as another parameter, so a filter or something would check it to allow access.
On logout, the token would be deleted (you may want to have a process that deletes the tokens after a certain amount of time or something like that).

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);

JAX-WS, Authentication and Authorization - How to?

What is the best way to do authentication and authorization in web services?
I am developing a set of web services, requiring role based access control.
Using metro - SOAP, simple java without EJBs.
I want to Authenticate the user just one time, using username and
password, to be matched against a data base. In the subsequent calls.
I would like to use some kind of session management. Could be some
session id, retrieved to the client at login, to be presented in all
calls.
So Far:
Read authentication using a database - but I want application level validation;
Read application authentication with jax-ws - but i don't want to do the authentication mechanism every time;
I think I can use a SOAP Handler, to intercept all the messages, and do the authorization control in the hander, using some session identifier token, that comes with the message, that can be matched against an identifier saved in the data base, in the login web method.
EDIT:
I still have some questions:
How to know the name of the web method being called?
What kind of token should I use?
How to pass this token between calls?
EDIT 2
Because of #ag112 answer:
I'm using Glassfish.
I use WS-Policy and WS-Security to encrypt and sign the messages. Using Mutual Certificate Authentication. I would like to complement this message level security between applications, with the authentication and authorization for the users also in message level.
I am just developing the services, and I don't know almost nothing the clients, just that they could be created in different languages.
At this point I think the most important thing is to do what ever I need to do to authenticate and authentication the users, I the most easy way to be implemented for the client applications.
#Luis: Here are my inputs.
Well exact solution for your problem depends upon kind of web service clients you expect, do you have control over web service client system, your app server etc.....but assuming you don't have any control over web service client, for you it is just a SOAP message over HTTP transport, here is probable solution.
You can of course performs session management & authentication at message level or transport level. It means either you can have session token and auth token information in SOAP message or you can use standard HTTP Session and HTTP authentication mechanism.
Of course transport level solution is much simpler and industry wide standard in case if transport layer is HTTP. For message level, ws specifications like ws-security can be used.
Your each web service request is simple HTTP GET/POST identified by a unique HTTP URI.
Typically in jax-ws metro environment, WSServlet is one which entry servlet for any web service call and which eventually delegates the call to right service provider implementation class. Since you application is going to be deployed in web server, you can exploit all session and authentication facilities provided by J2ee web container.
Since you are looking for role-based access control, I would use standard <web-resource-collection> in web.xml to specify which role you would like to have in case of particular HTTP URI. You can use standard JAAS login module which can do authentication and populates the JAAS subject with role. If user name/password are provided in SOAP XML, JAAS login module can also search/parse SOAP XML to retrieve those information. JAAS/app server will automatically create auth token and store it as cookie so that each subsequent request need not to go through authentication process again. This is all J2ee standard. You can find plenty of help on internet on this. Please let me know your app server so that I can provide you additional details.
If you still want to use SOAP message level session management, authentication & authorization process, then to provide you more details, may I know more details about your client side.
EDIT1:
Well based on your further inputs, here is my more thoughts:
Message security namely encryption and signature needs to happen each message travels between server and client. where as message authentication- you intend to do once and give a session token/auth token to client for subsequent calls.
Question still remains: if you put a unique session Identifier in SOAP response of first time authentication, do you expect client to parse SOAP response XML and ensure that client should send you session identifier each time in subsequent SOAP requests.
OR
You want to keep session management transparent to client and for client it needs to send username/password token first time and subsequent calls need not require any username/password token. In this case you would need to rely on transport based session management for e.g. HTTP cookies
Now what is the best for you depends upon your use case. Can you tell me what is expected use case flow? how another system (web service client) makes more than one service call to your system? Is another system user driven/some background process? What is exact need that you want only first service call to go through authentication process not subsequent calls?
PS: Glassfish server provides a way of configuring message authentication provider which automatically enables/disables message level authentication.
EDIT2:
I understand you do not want to store user credentials in client app and web service server need those user credentials.
OAuth is open standard protocol which allows site A to access user's private data on site B. Ultimate idea is site A gets auth token which has specific expiry time. So Token containing encrypted from of user credentials or jsession id help you avoid need of re-authentication. You only need to decide where you want to keep token at client app side
You can keep token as cookie if transport is HTTP protocol.
Having said that ofcourse passing user credentials each time seems bit easier and straight forward.
You can also go for OpenEJB.
It used JAAS with WS-Security.
I hope the link is useful.
After all the help, I create this answer to simplify, and summarize all the ideas that was discussed.
The questions has 2 requisites:
Message level security;
One time authentication.
With ag112 help, this is hard to do, or to elegant in any way. So here are to conclusions:
For message level security send the user
credentials every time (place it in SOAP header);
For one time authentication use transport level security, and do a
session management.
I prefer the first one, because the message level was the biggest requisite.
As had no answers, following #unhillbilly advise, I answer my own question, with the progress so far:
How to know the name of the web method
being called;
Using a SOAP handler, finding the name of the first element in the body.
What kind of token should I use;
I decide to use a 128 bits token, representing each session. The Webservices, continue to be session-less, the key is just for authorizations purposes.
How to pass this token between calls.
For the login web method the result has the token, in each subsequent calls, the token is a parameter.
is there a better answer?

Categories

Resources