1

I'm new to ServiceStack and using it to provide an endpoint that will receive incoming requests from a remote service. No end user is involved.

The authentication flow goes like this (as specified by the author of the remote service):

  1. "Their" remote service calls "our" endpoint, with JWT in header
  2. "Our" endpoint extracts the 'kid' from the JWT
  3. "Our" endpoint calls "their" oauth endpoint, with 'kid' as parameter
  4. "Their" oauth endpoint returns a public key in form of a JWK (RS256)
  5. "Our" endpoint verifies the JWT signature using the JWK

Does ServiceStack support this authentication flow?

I think I need to write code that hooks into the request's authentication and does steps 2-5 above. Is that right?

Edit: I found this answer which looks to be what I'm after, i.e. custom AuthProvider that overrides PreAuthenticate with steps 2-5 above.

using System;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Web;

namespace MyService
{
  public class CustomJwtAuthProvider : AuthProvider, IAuthWithRequest
  {
    public CustomJwtAuthProvider ()
    {
      Provider = "CustomJwtAuthProvider";
      AuthRealm = "/auth/CustomJwtAuthProvider";
    }
    public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
    {
      return session.IsAuthenticated;
    }

    public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
    {
      throw new NotImplementedException("Authenticate() should not be called directly");
    }

    public void PreAuthenticate(IRequest req, IResponse res)
    {
      // Get kid from JWT
      // Get public JWK from oauth endpoint
      // Verify JWT signature using JWK
      if ( /* JWT sig verified */ ) 
      {
        req.Items[Keywords.Session] = new AuthUserSession
        {
          IsAuthenticated = true,
        };
      }
    }
  }
}

Then in the ApplicationHost.Configure():

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
  new IAuthProvider[] {
    new CustomJwtAuthProvider(),
  }));

Does this approach seem right? Do I need to hand-roll the JWT authentication, or can I leverage ServiceStack's built in features and plugins more?

DaBozUK
  • 590
  • 1
  • 8
  • 24
  • As @mythz answered below, the JWT verification is independent of the ServiceStack JWT implementation. Therefore I can just call the bespoke JWT/JWK verification code within my service endpoint, or hook up a custom AuthProvider as shown above in my Edit. – DaBozUK Sep 03 '19 at 17:06

1 Answers1

2

For them to be able to send you a JWT that ServiceStack accepts as an Authenticated Request, your App would need to be configured with either their AES Key if they're using HMAC-SHA* algorithm or their public RSA key if they're using JWE.

This flow is very strange, for them to be able to send you a custom JWT Key they would need to be able to craft their own JWT Key which means they need either the AES or private RSA Key your App is configured with where they'd be the only ones you will be able to authenticate with your App via JWT?

It's very unlikely that you'll want to configuring your App with that of a remote Service, instead you should probably use a JWT library like the JWT NuGet Package to just verify the JWT they send you is from them, then extract the KID, call their endpoint and validate the JWK they send you using a .NET library like JWK to verify their key.

Note this flow is independent from ServiceStack's JWT Support which you would use to enable stateless authentication to your Services via JWT. Here you're just using JWT and JWK libraries to verify their keys and extract required info from them.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • Ok, I'm pleased to see that you @mythz consider this a strange flow. I'm new to this, but even my untrained eyes could see this is far from typical. See my Edit to the original question regarding a custom AuthProvider. Would you consider this still a valid approach considering your suggestion of JWT nuget package. Because I think I still need to intercept the authentication step on my endpoint method and call these custom verification steps. - Also as far as I can tell, they create the JWT Key and we have no key. – DaBozUK Sep 03 '19 at 16:39
  • 1
    @DaBozUK No this isn't something you're configuring your App with, you would just be doing the validation from within the Service they're calling. If they're only calling a few of your Services you can just do the validation from within your Service implementation. If they want to be able to call any of your Services then you could register a Custom AuthProvider which basically accepts their JWT/JWK keys as valid Authentication (again its independent to ServiceStack's built-in JWT support). – mythz Sep 03 '19 at 16:45