REST based token auth approach

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

REST based token auth approach

Sean Blaes
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:


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

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: REST based token auth approach

Marcus Bond

Hi Sean,

 

I would suggest applying a custom filter on the “login” url that can check the request, login and return a token in the response.

Other urls would be secured with another filter (or the same one if you want to make it aware of your login mechanism) that checks for the token, that much you know already.

 

Whether or not to use a session depends upon whether you wish to authenticate on every request vs. maintaining a logged in session.. since the subject has logged in and received a token it seems almost pointless to not maintain a session (regardless of where you store it) since you will want it to expire (session timeout) and you can use Shiro for this aspect even if nothing else goes into it, thus separate authentication with the token becomes redundant.

 

As for the noSessionCreation filter, I only use this when authenticating on EVERY request, however as suggested above a token could reference an authenticated session so you wouldn’t use it.

 

Regards,

Marcus

 

 

 

From: Sean Blaes [mailto:[hidden email]]
Sent: 06 August 2012 22:29
To: [hidden email]
Subject: REST based token auth approach

 

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:

 

 

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

 

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: REST based token auth approach

Les Hazlewood-2
In reply to this post by Sean Blaes
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:


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 <[hidden email]> 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:


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


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: REST based token auth approach

Sean Blaes
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

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:


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 <[hidden email]> 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:


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



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: REST based token auth approach

Les Hazlewood-2
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 <[hidden email]> 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

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:


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 | <a href="tel:888.391.5282" value="+18883915282" target="_blank">888.391.5282
Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk


On Mon, Aug 6, 2012 at 2:28 PM, Sean Blaes <[hidden email]> 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:


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




Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: REST based token auth approach

Sean Blaes
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

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 <[hidden email]> 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

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:


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 | <a href="tel:888.391.5282" value="+18883915282" target="_blank">888.391.5282
Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk


On Mon, Aug 6, 2012 at 2:28 PM, Sean Blaes <[hidden email]> 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:


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





Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: REST based token auth approach

Marcus Bond

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:[hidden email]]
Sent: 07 August 2012 21:10
To: [hidden email]
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

 

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 <[hidden email]> 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

 

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:

 

 

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 | <a href="tel:888.391.5282" target="_blank">888.391.5282
Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk

On Mon, Aug 6, 2012 at 2:28 PM, Sean Blaes <[hidden email]> 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:

 

 

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

 

 

 

 

 

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: REST based token auth approach

Sean Blaes
I think that the token bearer approach that Les was suggesting is one where a token is provided and is used for authentication each and every time. It's more or less the common approach where an API key is provided to consumers. They use that key or token the first time and every time. So, I think the only real difference is in my approach you authenticate then get a token which expires after a period if unused, whereas in Les' approach the token is provided once and used from that point forward, it never expires. In general though, they're not all that much different. The advantage with my approach for my environment is that I'm using the existing authentication/authorization infrastructure we have in place. That makes sense because this is being used by an iOS application that end users will log into, so the credentials are not actually from app to app but rather from end user to application, and I'm just passing through their provided username and password. This way, I don't have to manage a whole different credential store and the credentials provided only give that user access to those resources they should have access to.

In my case, what I'm doing is exactly the same as normal web sessions using a JSESSIONID as you suggested. I'm providing an authentication "service" which provides them an authentication token, which they use from that point forward. I will be persisting this token (and nothing else) using Terracotta/EhCache, which we already have in our infrastructure and as such, is very convenient. It will take care of the distribution/replication for us. Also, a difference my approach is that I'm using a custom header parameter, not a cookie, to pass the authentication token. Again, this is because it's the way our legacy services work, and I'm not sure I would condone that for green-field development. I just want to avoid forcing my downstream clients that have already coded to that legacy interface to change their code.

So, what I've done so far is implement a custom AuthTokenSessionManager extending DefaultWebSessionManager, and have overridden the getSessionId method to pull the session id from a header parameter. Then, I've created a custom RestPassThruAuthTokenFilter that extends PassThruAuthToken filter such that it will allow calls to /authenticate to pass through, but all other calls will be rejected with a 403 if there is no existing authenticated subject.

-- 
Sean Blaes
Sent with Sparrow

On Wednesday, August 8, 2012 at 2:07 AM, Marcus Bond wrote:

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 [[hidden email]]
Sent: 07 August 2012 21:10
To: [hidden email]
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

 

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 <[hidden email]> 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

 

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:

 

 

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 | <a href="tel:888.391.5282" target="_blank">888.391.5282
Stormpath wins GigaOM Structure Launchpad Award! http://bit.ly/MvZkMk

On Mon, Aug 6, 2012 at 2:28 PM, Sean Blaes <[hidden email]> 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:

 

 

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

 

 

 

 

 


Loading...