Cannot get the JWT Token

I am trying to setup JWT Tokens but I am not succeeding…
I followed the samples and have following code in my server implementation:

        Plugins.Add(new AuthFeature(() => new AuthUserSession(),
            new IAuthProvider[]
            {
                new JwtAuthProvider
                {
                    HashAlgorithm = "RS256",
                    PrivateKeyXml = privateKeyXml
                },
                new CredentialsAuthProvider() //Sign-in with UserName/Password credentials
            }));

and then I have a client:

        var authClient = new JsonServiceClient("http://localhost:63404/");
        var jwtToken = authClient.Send(new Authenticate
        {
            provider = "credentials",
            UserName = "Stefan",
            Password = "p@55word",
            UseTokenCookie = true
        });

but then jwtToken.BearerToken is always null.

Any idea what I am doing wrong? I just get and AuthSession object back. I would need the BearerToken because I want to have a SS MicroService to handle authentication.

Thanks for the help!

Did you try to retrieve the JWT Token from the Cookie?

var jwtToken = authClient.GetTokenCookie(); //From ss-tok Cookie

Yes I did, still null.
I can see a session record created in the DB. Not sure what’s going wrong.

I also tried to add the

        var tokenResponse = authClient.Send(new ConvertSessionToToken());
        var jwtToken2 = authClient.GetTokenCookie(); //From ss-tok Cookie

But then I get a forbidden on the call to ConvertSessionToToken

On the MetaData page of my service I see that the ConvertSessionToToken requires authentication.

ConvertSessionToToken converts an existing Authenticated Session into a JWT Token which is why it needs to be authenticated.

Can you provide the raw HTTP Headers when Authenticating with UseTokenCookie = true using something like Fiddler. Also are you able to authenticate normally, i.e. call a Service that requires Authentication with the same Service Client after authenticating?

Hi,
Will try the Fiddler tool.
Here is the complete code (maybe I am doing something wrong)
source

I can confirm that after the authentication call, I can access a service with the [Authenticate] header.

FYI the issue is because you’re not using it over a secure connection, which you can inspect by looking at the WebServiceException thrown, e.g:

try
{
    var tokenResponse = authClient.Send(new ConvertSessionToToken());
}
catch (WebServiceException ex)
{
    ex.ToString().Print();
}

Which should print out:

403 Forbidden
Code: Forbidden, Message: Sending JWT over insecure connection forbidden when RequireSecureConnection=true
Server StackTrace:
 [ConvertSessionToToken: 2/16/2017 4:40:20 AM]:
[REQUEST: {PreserveSession:False}]
ServiceStack.HttpError: Sending JWT over insecure connection forbidden when RequireSecureConnection=true
   at ServiceStack.Auth.ConvertSessionToTokenService.Any(ConvertSessionToToken request) in C:\src\ServiceStack\src\ServiceStack\Auth\JwtAuthProvider.cs:line 279
   at lambda_method(Closure , Object , Object )
   at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto) in C:\src\ServiceStack\src\ServiceStack\Host\ServiceRunner.cs:line 107

In production you’d want to ensure JWT Tokens are sent over a Secure Connection, but for testing you can disable it with:

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
    new IAuthProvider[]
    {
        new JwtAuthProvider {
            HashAlgorithm = "RS256",
            PrivateKeyXml = privateKeyXml,
            RequireSecureConnection = false,
        },
        new CredentialsAuthProvider()
    }));

Also note that when you use UseTokenCookie it has a similar effect to ConvertSessionToToken where it:

removes the our Session from the App Servers Cache as now the Users Authenticated Session is contained solely in the JWT Cookie and is valid until the JWT Cookies Expiration, instead of determined by Server Session State.

If you didn’t use UseTokenCookie, e.g:

var authClient = new JsonServiceClient(Config.ListeningOn);
var authResponse = authClient.Send(new Authenticate
{
    provider = "credentials",
    UserName = "Stefan",
    Password = "p@55word",
    RememberMe = true,
});

The JWT Token is returned in authResponse.BearerToken and the session is left untouched, i.e. it’s still stored on the server.

But when you use ConvertSessionToToken it embeds the current authenticated UserSession in the JWT Token Cookie:

authClient.Send(new ConvertSessionToToken());
var jwtToken = authClient.GetTokenCookie(); //From ss-tok Cookie

and deletes the Server’s UserSession so the authenticated requests are happening solely from the JWT Token.

FYI I’ve added your sample code in the JwtAuthProviderTokenCookieExample.cs stand-alone integration test which shows some of this behavior if you want to play around with it.

Ah brilliant! Thanks!

I understand the idea behind reauthenticating the serviceclient in favour of using RefreshTokens. But if you do this with ClientCredentials in a mobile app, this means I have to store uid and pwd on the device in order to be used after the user closes the app? This way I need to retrieve uid and pwd to be able to reauthenticate if the JWT token has expired. Is this correct? Because that’s the idea behind a RefreshToken. Then the refreshtoken can be saved (secure) on the device and that is used to get a new token.

They don’t have to use userName/password, they just need to be able to re-authenticate again, e.g. they could use an API Key instead.

Ok, but is there a way to get this API key in the Authenticate call as well? Of is there another call needed to retrieve an API key based upon UID/PWD?

Using an API key was an example, you can get it from the API Key Auth Provider. They’re generated on registration and can be accessed from the built-in GetApiKey Service.

@stefandv FYI support for JWT Refresh Tokens were added in v4.5.8: http://docs.servicestack.net/releases/v4.5.8#jwt-refresh-tokens

2 Likes