1
votes

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?

1
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

1 Answers

2
votes

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.