Well, "safe" is a very relative term and has to be balanced between what you're trying to protect and the convenience your users might demand.
That said, if you're looking for a more secure SSO than Cookies, a lot depends on your method of authenticating users for your main application. E.g., if it's done at the Web server level, then you might want to look at using the Remote_User environmental variable. (FWIW, I use Tomcat's built in SSO functionality and this for my SSO)
Or, some commercial SSO apps will defined specific additional HTTP header tags that define who the authenticated user is.
If it's done via another Java web app, you can look at cross context functions to pass this information from Webapp to webapp and not deal with passing info back to the client (other than session id information).
Have the basic information that will be passed to the SSO application be something like:
userid;ip;time-issued;md5 security key
Where: userid is the validated user id info.
ip is the remote client ip
time-issued is the time the cookie was created
md5 security key is a hash of all the previous info plus a shared salt key(and if possible, the user's MD5 password hash)
The authenticating application should create a cookie with a key based encryption of this information. E.g.:
The receive SSO agent should decrypt the information, then validate it against the MD5 hash, verify that the remote client IP is the same (note that Proxy servers can play heck with this part), and the timestamp is not too old. It should then issue an new MySSOCookie of the same format with a new timestamp back to the client.
Note that this will add to the processing time needed to deal with each request.