Skip to content

Instantly share code, notes, and snippets.

@tizzo
Created June 8, 2016 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tizzo/771279585779ab95d119db2c4be6c783 to your computer and use it in GitHub Desktop.
Save tizzo/771279585779ab95d119db2c4be6c783 to your computer and use it in GitHub Desktop.
Probo JWT Proposal Draft

Schema

Needs to capture:

  • The user Probo ID
  • Human readable
{
  "key": "coordinator-1",
  "context": {
    "actingUser": {
      "id": "d0229483-18c5-4182-99ef-c38577f73961",
      "slug": "github:tizzo",
      "admin": true,
    }
  },
  "permissions": {
    "assetReceiver": {
      "backup": true,
      "read": {
        "buckets": [
          "3280f824-991d-4fb3-a48a-aed430a444f2"
        ],
      }
    },
    "loom": {
      "write": [
        "stream-build-3280f824-991d-4fb3-a48a-aed430a444f2"
      ]
    },
  }
}
app.get('/api/streams/:streamId', jwtHandler.createMiddleware('permissions.loom.write', 'req.params.streamId'), function(req,res) { /* do stuff. */});
var jwtHandler = require('probo-jwt');
var app = require('express')();
jwtHandler.configure({
  keys: {
    "coordinator-1": fs.readFileSync('/some/path/to/coordinator-1.pub'),
  },
});
app.use(jwtHandler.createMiddleware('permissions.assetReceiver.backup'));

// The above is short for:
app.use(function(req, res, next) {
  var token = parseToken(req.headers.bearer);
  var claims = jwt.verify(token)
  if (claims.context.actingUser.admin) {
    return next();
  }
  if (!claims.permissions || !claims.permissions.assetReceiver || !claims.permissions.assetReceiver.backup) {
    res.writeHead(403);
    res.end('Access denied');
    return;
  }
  next();
});
@tortillaj
Copy link

@tizzo @lliss this JWT service is great overall. I think our processes would be simplified if the actingUser object also included the token & refreshToken of the service. Right now these service tokens are passed as parameters or post objects throughout the system, and adding them to the JWT would normalize and simplify the process. For example, imagine cases where the web UI needs to get info about a user from Github, or the container manager wants to know if a user is an admin of a Github organization. It's an easier task if the GH tokens are included!

Lastly, the slug field will be very weird for stash. I recommend splitting into 2 fields. Additionally, "slug" the word means the provider's slug. We use the word "type" to differentiate "provider" (you can see this in the Repo model). I'm only recommending naming changes to normalize with the rest of the system.

"context": {
    "actingUser": {
      "id": "d0229483-18c5-4182-99ef-c38577f73961",
      "provider": {
            "type": "github"
             "user": "tizzo",
             "token": "...",
             "refreshToken": "..."
        },
      "admin": true,
    }
  },

@tortillaj
Copy link

Since actingUser.provider will be different depending on the provider type (GH, BB, Stash, etc) ... I assume these tokens are for a build, project, repo, or organization ... but not for a user directly. (i.e. "a JWT for a user acting within a project" etc). Do we care about the entity the JWT refers to? Or more clearly, will the system need to know that this JWT is for a user acting within a project, repo, build, or organization?

I feel it might make things easier if the JWT's context specifically named its entity and entity id. I guess it's totally possible for the system to know the JWT entity based on the context of the code itself, but wanted to propose the question to see what we think. I was mostly thinking about situations outside REST routes, where the entity and entity id are not part of a route.

@tortillaj
Copy link

@tizzo and i discussed this, and i was making this more difficult than it needed to be

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment