Les / Sean,

 

This token bearer approach.. can you let me know the difference between this 
being stateful and with stateless?

 

The way I see it is if a client first logs in with their credentials and is 
given a token (they swap their username / password for a token) lasting for a 
period of time then this token / subject / timeout information needs be stored 
somewhere server side (in memory or in a db) and looked up each time a request 
comes in with that token hence the request appearing stateful – the state is 
which user for which token. Normal web sessions operate in the same way but the 
token is a JSESSIONID that happens to be sent via a cookie or a query 
parameter.. there needn’t be any other data in the session but the token serves 
to look up a subject.

 

The reason I am asking is that it seems from the conversation these two 
approaches are considered conceptually different but I am slightly confused as 
to how?

 

Marcus.

 

 

 

From: Sean Blaes [mailto:[email protected]] 
Sent: 07 August 2012 21:10
To: [email protected]
Subject: Re: REST based token auth approach

 

It's not going to be an extreme volume, and the big catch is that changing to 
passing credentials on each hit would mean all of our clients would have to 
migrate to the new approach. That would be a pretty drastic change. We 
previously were handling auth ourselves for internal clients, but now that 
we're extending the api to external clients (though it's not really going to be 
a public api), we need more robust controls and authorization especially. I'll 
probably stick with the session-based approach for now...

 

-- 

Sean Blaes

Sent with Sparrow <http://www.sparrowmailapp.com/?sig> 

 

On Tuesday, August 7, 2012 at 2:43 PM, Les Hazlewood wrote:

The two approaches are identical except that the one I outlined does not 
require sessions/server-side state.  In the session case you're currently 
using, the session ID essentially _is_ the bearer token.

 

The sessionless approach, while requiring a bit of implementation that I 
described, will scale much better (i.e. no need to worry about session 
clustering if you need to support HA/failover).  However, I don't know how many 
clients/requests you will need to support.

 

Cheers,


--
Les Hazlewood | @lhazlewood
CTO, Stormpath | http://stormpath.com | @goStormpath | 888.391.5282
Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk



On Tue, Aug 7, 2012 at 12:28 PM, Sean Blaes <[email protected]> wrote:



Thank you Les, think my situation is a little bit different. In this case, I'm 
building an API that allows a mobile application to talk to the server. We 
currently authenticate using the application user's credentials 
(username/password), using a /authenticate REST api endpoint. That responds 
with an authentication token that the application retains. Subsequent calls 
from the mobile app to the server use the authentication token to validate the 
user's login and authorize them for whatever action they wish to take…

 

This will definitely be exposed only over SSL, because I recognize that the 
token based approach could be vulnerable especially to session takeover attacks.

 

What we're currently doing is basically letting Shiro create a session and 
we're passing the session id back as the token via the /authenticate method. 
Then, we use that session id to retrieve the subject in later requests. So, 
we're just trying to figure out how to best implement this approach.

 

-- 

Sean Blaes

Sent with Sparrow <http://www.sparrowmailapp.com/?sig> 

 

On Tuesday, August 7, 2012 at 2:14 PM, Les Hazlewood wrote:

For web-scale scalability, most REST implementors prefer that REST APIs should 
be stateless.  While you _can_ have REST APIs that use sessions, most choose to 
remain stateless and authenticate on every request as a best practice.

 

Assuming you'll authenticate every request, your token will be the data you'll 
need to submit to Shiro on each request.  

 

In security circles, this is known as a 'bearer token' - the data isn't actual 
authentication principals+credentials, instead it is a token that you 
automatically assume that the presenter of the token (aka 'holder' or 'bearer') 
is allowed to have it and you can trust it.  I should point out that bearer 
tokens are less secure than other mechanisms, but I won't talk about that here, 
as that is a different thread entirely.  But sometimes (e.g. your case?) maybe 
they're the only mechanism that can be used.

 

Assuming you want to perform bearer token authentication In Shiro, you can 
implement the AuthenticationToken interface, e.g.:

 

public class BearerAuthenticationToken implements AuthenticationToken {

    public BearerAuthenticationToken(String token) {...}

    ....

}

 

You can then create a Realm implementation that 'supports' this 
BearerAuthenticationToken implementation.  This ensures that only this Realm 
will process these types of authentication attempts:

 

public class BearerTokenRealm extends AuthorizingRealm /* or 
AuthenticatingRealm */ {

    

    public BearerTokenRealm() {

        //this makes the supports(...) method return true only if the token is 
an instanceof BAT:

        setAuthenticationTokenClass(BearerAuthenticationToken.class);

    }

 

    public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken 
token) throws AuthenticationException {

        BearerAuthenticationToken bearerToken = 
(BearerAuthenticationToken)token;

 

        //assert the bearerToken, and if valid, look up the account data and 
return

        //an AuthenticationInfo instance representing that account.

    }

}

 

In my opinion, the String contents should be encrypted with AES-256 encryption 
using a private key known only to the application.  The unencrypted value can 
be whatever you want - e.g. an account ID that you can use to look up account 
information.

 

Next, you'll need to create an AuthenticatingFilter implementation that knows 
how to extract the token from the HTTP Headers and construct a 
BearerAuthenticationToken instance, e.g.:

 

BearerTokenAuthenticatingFilter extends AuthenticatingFilter {

    

    @Override

    public AuthenticationToken createToken(....) {

 

    }

 

}

 

You can look at the source code for Shiro's BasicHttpAuthenticationFilter 
implementation to give you ideas when implementing your own BearerTokenFilter:

 

http://svn.apache.org/repos/asf/shiro/trunk/web/src/main/java/org/apache/shiro/web/filter/authc/BasicHttpAuthenticationFilter.java

 

Finally, you can set up the filter and filter chain definitions in shiro.ini 
(or equivalent in Spring or Guice, etc):

 

[main]

 

bearerAuthc = com.company.shiro.web.filter.BearerTokenAuthenticatingFilter

 

[urls]

 

/rest/** = ssl, noSessionCreation, bearerAuthc

 

I'd definitely use the SSL filter to enforce SSL to ensure the token cannot be 
modified in transit.  This is one of a few security reasons why bearer tokens 
must be secured in additional ways (e.g. they are not as strong as, say, 
digest-based authentication that don't need SSL).

 

HTH!


--
Les Hazlewood | @lhazlewood
CTO, Stormpath | http://stormpath.com | @goStormpath | 888.391.5282
Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk



On Mon, Aug 6, 2012 at 2:28 PM, Sean Blaes <[email protected]> wrote:



I've been doing a ton of research on this and just want to validate the best 
approach before I move forward...

 

My requirement is that I do token based authentication for a REST/Jersey 
service that is also integrated with Spring. This means that there is an 
"authenticate" service to which the username/password will be posted, which 
will respond with a string token. That token can be whatever I want. All other 
method request will pass the token in an HTTP header. This is the requirement 
because we support several existing clients and cannot expect them to change at 
our whim, and this is how the current service works that is using a home-grown 
auth framework.

 

I'm looking at disabling session creation, as described at:

 

 
<https://cwiki.apache.org/confluence/display/SHIRO/Session+Management#SessionManagement-StatelessApplications%28Sessionless%29>
 
https://cwiki.apache.org/confluence/display/SHIRO/Session+Management#SessionManagement-StatelessApplications%28Sessionless%29

 

Specifically with 

 

/rest/** = noSessionCreation, anon 

 

The question then is how do I best store and retrieve the fact that the user 
with a given token has been authenticated? Should I just store it in ehcache 
and and retrieve it with a "remember me manager" upon each request? Or, do I 
need to implement a secondary realm that logs in by the stored auth token 
rather than the user/password. Lastly, I could keep sessions enabled but I 
really don't need anything from the session other than this token, I don't 
think.

 

-- 

Sean Blaes

Sent with Sparrow <http://www.sparrowmailapp.com/?sig> 

 

 

 

 

 

Reply via email to