I have an application deployed on a Weblogic domain which gets a request from the browser for login.
The actual login process occurs on a SECOND Weblogic domain which resides on the same machine.
I need the following:
- Identify on the first domain that a call was made for login.
- Forward the login request to the second domain.
- Send the response from the second domain to the first one so it will continue the process; e.g. if the user was authenticated successfully, then need to open a session for him, return a response to the browser etc.
NOTES
- I assume that I should use filter in web.xml for identifying that a login request has arrived and if I'm right I would like to hear how it connects to the call to the second server.
- I'm interested in how to implement the communication between the 2 domains.
- How would you prevent fake "successful authentication" calls to the first domain; i.e. I want to make sure that if my first domain got a successful authentication call then I want to be sure that the call indeed passed through the authentication server, (i.e. the second domain).
I would appreciate any idea or help on this, Thanks !!!
Well,I have two ideas,just for your own consideration!
First,just use digital certificate to sign the request,for webserivce https is the option,this is the common way to deal with fabrication problem.
Second,Implement your custom security provider is a more standard way than do it in the filter,it's typcially a JAAS LoginModule implementation,which call the webservice on the second domain for authentication.By this way ,authentication is delegated to weblogic server and the application for on first domain has loosely coupled with the second domain.
By the way, check the weblogic documentation for detail of how to implement a custom provider,this is for weblogic version 10.3.2
Developing Security Providers
Related
I have java web application using struts 1.x. Recently my application has gone through penetration testing and our testers found some security holes. Let me explain. In my application i have 2 users called ‘Admin’ and ‘user’. First our PenTester logged to my application as ‘Admin’ and they use ‘Burp tool’ to intercept the request and copy the whole request content into notepad and then forward the request. Now My application log in as ‘Admin’. They use another browser instance to login as “user” and use burp tool to intercept the request. This time they removed the whole request content and copy back the whole request content of ‘Admin’ and then forward the request. Now my application logged in as ‘Admin’ without asking any user id/password? How to restrict this situation? I already stored userid in my session variable after successful login of each user. The moment they intercept the request and copy the ‘admin’ request content, my session variable userid also changed to ‘admin’. How to validate this situation? Your help is really appreciated.
That is not really that much of an issue since the first part "copy the whole request content" is not easily doable if you have a proper HTTPS / SSL connection. That only works if the PC the user is logged in on as an admin is compromised in which case: nothing you can do about it anyway because they can just sniff the keystrokes and get the plain password.
If on the other hand you communicate without the S, namely just HTTP then the solution is: get a certificate and switch to HTTPS.
Apart from that your application can pin a session to an IP which means if the session id / cookie is stolen and someone else uses it you can detect an IP mismatch and ask for credentials again.
To prevent direct replay attacks like copying the request and sending it again you can introduce a hash that incorporates the timestamp or alternative measures, see. How do I prevent replay attacks? . The problem however is that copying the entire request means copying the cookies as well and if the "admin" cookie is copied this measure will not prevent you from "generating" a new hash based on the now admin user.
Warning: This is an extremly long post, simply because I don't know how to explain our specific problems any other way (sorry).
Short version:
We are building a very modular suite of Java applications (both client and server side). Some clients have to authenticate against the servers, and the servers can authenticate against different types of user stores. Servers can also call other servers on behalf of their authenticated user, i.e. using their credentials. This has worked fine so far using simple username/password credentials, but now we have to optionally support SSO via Kerberos (and later other authentication systems). So far, we're failing (partly miserably).
Long version:
Our central Java library for handling principals is called User Access Layer (UAL). This library is used by both client and server applications and provides three types of funcationality:
Authenticate users based on their credentials (results in a failed authentication or basic information about the user, i.e. at least a login name or ID)
Perform principal queries
Perform principal modifications in the user store, if the backend supports it
(2) and (3) can be performed either using credentials specified by the caller or (if the backend supports it) as a technical user.
Actual access to the user store is handled by the configured backend. We provide a number of backends (LDAP, WebDAV, a custom JDBC database, a custom XML file) which can all be configured through a unified configuration file, usually named useraccess.xml. This file defines which backend (or backends) should be used and how it is configured, e.g. LDAP server and structure data for the LDAP backend or the database URL and database user credentials for the database backend. All backends implement the same interfaces so the application code is independent from the backends configured for a particular installation.
In our product, UAL is used by two different types of applications:
Clients (both command line/desktop clients and web frontend applications opened by a user in a browser). These applications use UAL to perform principal queries (e.g. our file browser application when modifying the ACLs of a WebDAV resource) or principal modifications (we have a web based user management application). Depending on the application, they get the credentials used for their UAL operations in one of the following ways:
a. User provides the credentials on the command line when calling the application
b. Application opens a dialogue and prompts the user to input credentials when a server access requires them
c. A login screen displayed when the user first accesses a web frontend application
Servers. which use UAL to:
a. Authenticate a user based on the credentials provided via the used protocol (e.g. HTTP/WebDAV or SOAP/WSSE)
b. Perform authorization for a user based on the user's (or the user's groups') attributes
c. Perform UAL operations (queries/modifications) on behalf of the client
d. Call other servers on behalf of the client, i.e. passing another server the user's credentials (e.g. via HTTP/WebDAV or SOAP/WSSE)
Until now, all our credentials were user name/password pairs, which worked fine as long as we made sure to keep these credentials in the user's session where necessary to later use them for accessing another server. We could do that every call that retrieved credentials or passed them to a server went through some of our code which could store/provide the necessary credentials.
Everything has become much more complicated with the requirement to support SSO via Kerberos. We've tried several approaches and modified our code base several times, but every time we believe to be on the right track, we realise that there's one spot we overlooked which cannot work the way we intended.
What makes things so confusing is that we have to handle credentials in several different ways. These are some of the ways we have to provide credentials to a server:
Via Apache HttpClient when accessing a HTTP/WebDAV server
Via SOAP/WSSE when accessing a web service
Via JNDI when accessing the LDAP server (in UAL)
And some of the ways we have to receive and verify credentials from a client:
As a login module in Apache Jackrabbit
When receiving a SOAP/WSSE message in one of our JAX-WS web services
A very common use case for us is the following:
Client calls server A via SOAP, providing credentials
Server A retrieves the credentials from the SOAP message and verifies them (responds with an error if they are invalid (authentication error) or the user is not authorized to perform the desired operation (authorization error))
Server A then calls WebDAV server B on behalf of the user, passing the user's credentials so that the WebDAV operation can be carried out with that user's permissions (and using that user's name and other attributes)
Server B retrieves the credentials from the HTTP message and verifies them
Server B then performs a principal query on the user store C, passing the user's credentials to the user store (depending on the configured UAL backend, this may simply compare the user's name and password to those in the user store XML file, or use them to establish an LDAP connection and query the LDAP store as that user)
And the problem is: There seems to be very little information on the internet to help with our specific problems. For starters, most resources simply describe how to setup a JAAS configuration file for a container to let its web applications perform user authentications. But our code has to run on both clients and servers and use one configuration file to specify the user store config for both authentication and principal queries/modifications. Furthermore, this has to work, with the same code, with user name/password credentials against a variety of user stores (some of them custom written) and with Kerberos (and later other) tickets against an LDAP server. And finally, it's not enough to have an authentication library which reliably tells us that user has provided the correct credentials (as many JAAS login modules seem to do), since we actually have to keep the user's credentials for further calls.
Since Apache Jackrabbit, which is the base for one of our core components, needs us to configure a JAAS login module, and there already are JAAS login modules for LDAP and Kerberos authentication, we have successfully modified UAL to perform all its authentication tasks via JAAS. For this we had two write login modules for our custom backends, and I had to implement my own LDAP login module since the default JAAS one would successfully authenticate the user against the LDAP server, but then throw away both the user's credentials and the LDAP context, so we couldn't perform further LDAP query using the same credentials. All our own login modules store the credentials in the authenticated subject's private credentials set, which is what JAAS's default Kerberos login module does as well. Using the resulting subject, we can then perform user queries. This works with all our backends and with both passwords and Kerberos tickets.
We were also able to modify our SOAP services to extract the credentials from the SOAP message. In the case of password credentials, we can simply pass them to JAAS when the authentication callback asks for credentials. However, there doesn't seem to be a way to do the same with a Kerberos ticket. Instead, our SOAP services currently handle those on their own, passing them through the necessary GSS API calls to verify the ticket, retrieve a matching ticket for the SOAP service's configured service user, and create a Subject containing the credentials and user information. Using this subject, we can then perform queries/modifications through UAL. However, this not only means that our SOAP services completely bypass UAL when authenticating Kerberos tickets, they also need some Kerberos configuration data (the service user name, the realm and the keytab file) in their own configuration, in addition to the useraccess.xml which already contains the same data (but not directly accessible to a generic UAL client because these settings are specific to the UAL LDAP/Kerberos backend). Obviously, things will only get worse when we add support for other ticket based authentication methods and they also have to be manually implemented in each SOAP service in addition to the UAL backend that actually handles the user store access.
Worst of all, we're still unsure how to get all this into our Jackrabbit based WebDAV server. Jackrabbit needs a login module, which should be fine for handling user name/password credentials but (as far as we can tell) fail for Kerberos tickets. We could probably fetch those manually from the HTTP headers, but that won't stop Jackrabbit from calling the login module and the login module from failing because it will still ask for a password and then fail to authenticate against Kerberos without one.
I can't shake the feeling that either our approach or (quite possibly) our understanding of how all these pieces should fit together is fundamentally flawed, but nothing we can find on the net spans enough of our requirements to indicate what we're doing wrong (or, more importantly, how it should be done to make it right). Because of the complexity of even describing our problems I so far shied away from posting this as a question, but if you've read this far and can give us any pointers on how to resolve this, you could save us from weeks of frustration.
You can remove everything after
Until now, all our credentials were user name/password pairs, which worked fine as long as we made sure to keep these credentials in the user's session where necessary to later use them for accessing another server. We could do that every call that retrieved credentials or passed them to a server went through some of our code which could store/provide the necessary credentials.
You problem is plain simple: you need credential delegation with Kerberos. The basic technique is quite simple. Since you have multiple problem areas here, I would recommend to break them up to have you problem solved:
OS/environment configuration for Kerberos credential delegation
How to request a delegable service token
How to retrieve the delegated TGT from the client
How to reuse the TGT from the client and request another service token
Since your inbound channel is HTTP, here are the answers:
If you are in an Active Directory environment, request your admin to set "trusted for delegation" on the machine account which will accept the GSS security context.
This is a bit tricky because it depends on the client language and library. In Java it is as simple as setting GSSContext.requestCredDeleg(true). Eloborate on the rest.
Inspect the code of my Tomcat SPNEGO/AD Authenticator library, I am extracting the client's TGT and storing it in the Principal implementation served by HttpServletRequest#getPrincipal method.
Assuming that your backend client library supports GSS-API properly, there are basically two ways to do it: (1) explicit credential usage: pass the delegated GSSCredential instance to the client lib and it should the rest. (2) implicit: Wrap your client action in a PrivilegedAction, construct a Subject with the private GSSCredential and invoke Subject.doAs with both. JAAS will use the implicit credential from the thread's subject and perform the operation on behalf of your user.
It seems like you haven't even reached point 2 or 3 yet.
I have an web application (Java-html5/js) which runs on our servers that is accessed simply by its URL, no login options or checks. I have been asked to secure it, but I have no access to its source code and I have not managed to contact the developer behind it. It is widely being used on the company, so there is no option to shut it down. The other applications on the network require authentication, so I can use those credentials for this app as well, by redirecting him from a another page. But once he logins, how can I stop him from just accessing the actual unsecured url?
If you're unable to change anything on this server, you may do the following:
Install a proxy server with authentication on another machine - if there's not already one in the company
restrict access to the app server to this proxy's IP address by putting it behind a firewall or changing routing rules
You need to go through the proxy to access and you need to authenticate. Way complicated but should work
I have an application(client application) hosted in a Tomcat server and this application has to be integrated as a Tab in another application(parent application). In the Parent application the user authentication is done. in the Parent application Html we are using iframe to integrate the client. Everything is working fine except this. The Problem is, if some one knows the URL they can access the client application. How can we avoid this.? we are using JAVA,SERVLET,HTML,Tomacat as technologies.
Thanks :)
One of possible solution is token based authentication.
The parent application should add special token either as a URL parameter or as HTTP header. The token should contain authentication information in encrypted form. "Client" application should extract the information and decide whether authentication passed or failed. In order to guarantee that no-one can copy this token and then get unauthenticated access to your application you should make the token to be one-time or limited in time range.
You can also use x-frame-options in your header. I found this article with some quick googling: http://www.jtmelton.com/tag/x-frame-options/
This will prevent your app from loading in frames except for the domains which you allow permission. You might check into browser compatibility, I'm not sure when this was implemented in different browsers.
Also, you can check the 'host' and 'referrer' header fields to check that requests are coming from a domain you trust before sending a response.
OAuth is the standard for authorizing third party apps. You should check into that as an authentication approach.
None of these will give you a completely secure app. You should consider consulting with a security expert.
From parent application add cookie and from child application get that cookie and validate user.(if both are running on same domain).
I've spent the last day or so looking in CAS and have managed to get the server working with a simple test application. When I enter a protected area, I'm redirect to a login page - when I log in, I'm taken back to my previous page.
From there, the next step would be deploy two client applications, log into client A, visit the client B protected area and have the system handle the authentication for me (since I'm already logged into client A).
This isn't actually working however. I have to log into the client B site whether I'm logged into the client A site or not.
CAS is running on Tomcat, client A and B are the same project deployed as separate wars on a single instance of JBoss AS 6.
Any ideas how I can achieve the suggested behavior?
EDIT: Yes, both are using CAS. The issue is that it doesn't seem to be recognizing that the user is already logged in. It's as if the CAS isn't able to determine that there is a 'link' between the two services and that when one service has been authenticated, the other service should be automatically authenticated.
I should note that at this stage, I am not using SSL within the application. I'm focused on getting a simple example up and going using HTTP before I look at introducing SSL.
Both of your applications need to be configured to use the CAS server for authentication. The normal procedure would be that application A redirects you to your CAS login page, lets you log in and redirects you back to A. If you then try to log into B, it checks with the CAs server whether you're already logged in and, if so, sends back information about the logged in user.
Again, both your applications need to support CAS as a login mechanism, which I am not sure about from your description.
Detailed description of the CAS protocol can be found here.
CAS was working without SSL in that it would take you to the login site and authenticate you correctly. The issue was if you tried to access via another site, it would ask you to sign in again.
Once I enabled SSL and tried it, it was working correctly. Once logged into client A, it would automatically authenticate you in client B. I had spent some time on the wiki and while it spoke of the importance of using SSL, I do not recall it explicitly stating that SSO will not work without SSL enabled. Maybe a warning should be added to the wiki?
If you want to focus on your applications and make your life easier, use a cloud provider for the CAS server: http://www.casinthecloud.com (free servers are available for tests).