Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using dart RPC and shelf_auth for some procedures

I'm using dart-lang/rpc with the shelf_rpc package.

Some of my Resources require authentication. I decided to go with JWT and want to use the JwtSessionHandler from shelf_auth.

My simplified setup looks like this:

final ApiServer _apiServer = new ApiServer();

main() async {
  var loginMiddleware = authenticate([new UsernamePasswordAuthenticator(lookupByUsernamePassword)],
      sessionHandler: new JwtSessionHandler('my app', 'shhh secret', usernameLookup), allowHttp: true);

  _apiServer.addApi(new Api());

  // Create a Shelf handler for your RPC API.
  var apiHandler = shelf_rpc.createRpcHandler(_apiServer);

  var apiRouter = shelf_route.router()
    ..add('/api', null, apiHandler, exactMatch: false);

  var handler = const shelf.Pipeline()
      .addMiddleware(loginMiddleware)
      .addMiddleware(shelf.logRequests())
      .addHandler(apiRouter.handler);


  var server = await shelf_io.serve(handler, '0.0.0.0', 8087);
}

/// Stub implementation
lookupByUsernamePassword(String username, String password) async =>
  new Some(new Principal(username));
/// Stub implementation
usernameLookup(String username) async =>
  new Some(new Principal(username));

How can I only add the loginMiddleware to requests that start with /account (for example)? Or even better: is it possible to define the loginMiddleware on the RPC Resource itself (instead of defining a path prefix which can potentially change and annul the authentication)?

like image 337
enyo Avatar asked Oct 30 '22 20:10

enyo


2 Answers

I have found a solution, although it doesn't seem to be the cleanest.

Instead of adding the loginMiddleware to the pipeline, I add it to the route like this:

var apiRouter = shelf_route.router()
  ..add('$_API_PREFIX/v1/account', null, apiHandler, exactMatch: false, middleware: loginMiddleware)
  ..add('$_API_PREFIX', null, apiHandler, exactMatch: false);

This registers the apiHandler twice, but the first route only matches /account routes, and adds the loginMiddleware.

like image 148
enyo Avatar answered Nov 15 '22 08:11

enyo


You would just create a handler that only does something when that path starts with account. This should work.

 shelf.Handler _accountHandler(shelf.Handler innerHandler) {
   return (shelf.Request request) {
   if (request.url.path.startsWith("/account")) {
   /// do something here
   }
   return innerHandler(request);
 };
like image 41
BeatingToADifferentRobot Avatar answered Nov 15 '22 08:11

BeatingToADifferentRobot