>> For example, in shiro.ini:
>>
>> securityManager.rememberMeManager.cookie.domain = .mysite.com
>
> Also, how is this configuration made using Spring? I'm not using INI
> config. Is it as simple as something like this?
>
> <bean id="securityManager"
> class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
> <property name="rememberMeManager" ref="myRememberMeManager"/>
> </bean>
> <bean name="myRememberMeManager"
> class="com.mysite.security.MyRememberMeManager">
> <property name="cookie.domain" value=".mysite.com"/>
> </bean>
I thought Spring allows you to set nested properties via the '.'
property notation. i.e:
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="rememberMeManager.cookie.domain" value=".mysite.com"/>
</bean>
I *thought* this worked the last time I needed to try it, but I can't
remember now. Of course, the above example would probably only work
if you're using the default CookieRememberMeManager. If using a
custom RememberMeManager implementation as your example above shows,
then yes, it should work fine.
>> 1. Authenticate once per session, and ensure the session id cookie is
>> also a subdomain cookie and then just ensure the session id
>> accompanies every request. Granted, this does require server state
>> (Sessions), and only you will know how many sessions your server (or
>> cluster). Just make sure you configure Shiro with a Cache if you use
>> its native session support (and a distributed cache if running more
>> than one application node in a cluster).
>
> So doing this would mean that a 3rd party app would need to direct its
> users to my login page for them to login, which would then redirect
> them back to the 3rd party app? It would have to do that each time a
> new session is created, right? The 3rd party app would need to be able
> to handle cookies, but I'm sure most platforms can already do that.
Yep that would be the way to go with the cookie approach, since the
3rd party app couldn't set cookies on behalf of your domain (browser
security restriction). Note that even with OpenID, the 3rd-party app
would need to direct the user to your website - they would just enter
their OpenID instead of a username/password.
>> 2. Authenticate on every request, which means Shiro will no longer
>> need to store its authentication state in the session. If you have
>> other parts of code that rely on a Session, you'll still need to go
>> with an approach like #1.
>
> This is where I get confused on how to proceed. If my API requires
> auth on every request, wouldn't the 3rd party app need to somehow
> store that auth information and send it with every request? What are
> some good methods of doing this in a secure manner?
>
> Let me be clear here... when I say 3rd party app, I mean several
> different things:
>
> 1. A mobile client (iPhone, Android, Blackberry, Symbian, etc.)
> 2. A web-based JAVASCRIPT client, without a server-side component,
> hosted on someone else's server.
> 3. A RIA client, such as an AIR app or something similar
>
> If the application is just a single page of Javascript, it doesn't
> seem safe for it to request a username and password and store them in
> JS variables to send with each request. I'm starting to think that a
> server-side component might be a requirement to do this right for
> 3rd-party apps.
Yes, there is some concern about that, given that you can't control
the client tier. If you enforce TLS connections, it becomes a little
more secure since the traffic is encrypted, but you can't guarantee
that the client itself is secure. In other words, TLS guarantess a
point-to-point (host to host) secure channel, but it doesn't guarantee
end-to-end (app-to-app) security.
WS-Security however was created to help address this gap. I've heard
of people using WS-Security with REST by including the WS-Security
information as an HTTP header. That is, you don't have to use SOAP to
use WS-Security, but you would need some custom coding to handle this
special case for your REST calls.
So, if you want things to be as secure as possible, the client has to
understand these mechanisms - either by performing strong encryption
itself, or by using a WS-Security library or something similar. Or it
can simulate what a web browser does with HTTP Digest authentication.
Or you use TLS Mutual Authentication (aka client ssl certificates).
Including username/password pairs in HTTP headers and sending them
over a non-mutual (server certificate only) TLS connection might work,
but it is not as secure as the above options. But these options place
mandates on your client tier - you will have to decide if you can
mandate these options, given the clients you have to support.
> I guess there are two approaches:
>
> 1. The 3rd party app runs completely in the client, and the client
> makes requests directly to my API
Yep, but see the above comments about the client communicating securely.
>
> 2. The 3rd party app runs in the client, but makes requests to a
> 3rd-party server component. The server component makes requests to my
> API.
I think this is where TLS mutual authentication is a best practice
(IMO) - both servers would trust each other, and can ensure that all
data is transmitted safely. But there is an additional network hop
(client -> 3rd party server -> your server) instead of just client ->
your server. The extra hop may or may not be acceptable depending on
your performance requirements.
And you probably wouldn't want any of your system's username/password
pairs being sent by the client to the 3rd party server since you
couldn't guarantee that they would remain safe (you can't control how
the 3rd party client and the 3rd party server function together).
> So I assume your 3rd party applications are running on a server, and
> that your secret key is protected from the public?
No, they can be desktop apps, but they are controlled - the apps do
not openly share their id/key with end-users (i.e. it is part of the
app's codebase and/or private config).
Sorry if my reply only muddied the waters, but hopefully it will give
you some ideas!
Best,
Les