Accessing and handling JWT in a 'unsecure' RestHandler function

Hi all

I’m looking for some advice or rather best practices usage for working with cbsecurity and JWT.
We’re new working with the Coldbox ecosystem, so please apologize any wrong assumptions or dumb questions.

As a bit of a background for what we want to achieve; we’re using coldfusion for our webshop for a long time now. Unfortunately still on model-glue for the most part. We are in the process of re-developing our mobile apps. To do so, we want to set up a REST API to provide the needed data for the mobile apps.
We opted for using coldbox to create the REST API as we can wire existing components through Wirebox and thus have a first step to migrate away from model-glue.

So for the customer authentication we’re going to use JWT provided from the cbsecurity module. I setup relatively short expire window and use the auto refresh validator, which works like a charm on secured functions. But, as we are providing a webshop, customer don’t have to be authenticated to browse our products. Having an account enables additional features, like wishlisting items and stuff. On that matter we want to show directly on the browsable lists if the authenticated customer has the product on the wishlist or not. To do that we need to check if the customer is authenticated and if so, fetch the correct data.

For getting products we have a Products endpoint. As stated a customer doesn’t have to be authenticated to browse the products thus we cannot have a secured annotation on the index function. But to add additional data if the customer is authenticated, I need to check the JWT, which I can do with the helper method jwtAuth(). The first problem I encountered is if no token or an expired token is provided, it will throw an exception. Which can be worked around with a try catch block. The real problem is that if the token is expired and don’t use the secured annotation, it won’t auto refresh the token, even if the refresh token is provided through the necessary header key.

This raises the question on how to approach this situation the best. Would you try to get the token in the index function and catch the TokenExpiredException exception and manually refresh the token with the jwtService.refreshToken() function? So that it would look something like that.

try {
 var token = jwtAuth().getToken(); 
 // or jwtAuth().getUser() as I need the customer information as well
} catch (TokenExpiredException tee) {
 // read refresh token from header
 // call jwtService.refreshToken();
}

The JWT also provides the user information, which we’d like to use directly without the need to exchange the customer id as an additional query parameter.

Sorry for the long text. TL;DR: I want to use JWT from cbsecurity inside a RestHandler component without securing the function with the secured annotation as it should be available for unauthenticated user as well. What’s the best approach to receive a token, get the user context and handle missing or expired tokens, and especially refresh the token if it is expired.

Thanks in advance for any help and suggestions.

You might be able to use the isLoggedIn() method to check to see if the passed token is valid or not. Here’s a simple implementation of what the check might look like.

Then you could use the prc.oCurrentUser variable that cbSecurity sets for you by default. The setting is in your cbsecurity module config under authentication.prcUserVariable.

if ( jwtAuth().isLoggedIn() ) {

    // assert: the user passed a valid token! 	
    prc.response
		.setData( true )
		.addMessage( "Your are logged in and authenticated." )
        .addMessage( "Your name is #prc.oCurrentUser.getFirstName()#." )
	;

} else {

	prc.response
		.setData( false )
		.addMessage( "You are not logged in." )
	;

}

Thank you very much for your answer and the hint.
I’ll have a solution where I check for the incoming token and refresh token and will refresh it manually if needed. If there was a refresh I’ll add it to the header the same way the secured annotation handles it. Though, I think the isLoggedIn() functionality will make my solution probably prettier. I’ll give it a shot :slight_smile: