Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-Implement the Drupal Filter using JWT #520

Closed
dannylamb opened this issue Feb 2, 2017 · 26 comments
Closed

Re-Implement the Drupal Filter using JWT #520

dannylamb opened this issue Feb 2, 2017 · 26 comments
Assignees

Comments

@dannylamb
Copy link
Contributor

dannylamb commented Feb 2, 2017

Add https://www.drupal.org/project/jwt to the install and be sure to enable the optional module to make it a credentials provider. If any configuration is required to get it going we'll need to export that as well.

Then we need to develop a ServletFilter for tomcat that will verify the tokens, which we should provide upon every write request. This seems like a good starting point: http://stackoverflow.com/questions/30335106/can-tomcat-work-with-jwt-token. Though I'm sure there will be some extra tomcat setup and general fun doing a java project setup.

To verify this issue is resolved, once properly configured:

  • Visit http://localhost:8000/jwt/token and you should be able to receive a token
  • Use that token to issue a cURL request for a write operation against Fedora and provide the token. You should be able to authenticate with that
  • And, for good measure, confirm that someone without a token attempting a write request is denied.
@ajs6f
Copy link

ajs6f commented Feb 2, 2017

Just to be clear here, @dannylamb, you mean a ServletFilter that can work with any web container, right? Not one specific to Tomcat?

@dannylamb
Copy link
Contributor Author

Yes. Sorry, referring to a generic product with a name brand there. Tomcat's our default, but it should work with any container.

@jonathangreen
Copy link
Contributor

I'll take a crack at this one. May take me a bit of time though.

@dannylamb
Copy link
Contributor Author

@ajs6f My understanding here is that authn comes from the web server and Fedora doesn't really have to get involved. Are there potentially any configuration bits on fcrepo I might be missing / not aware of?

@ajs6f
Copy link

ajs6f commented Feb 2, 2017

@dannylamb Definitely way the heck outside of any sphere of Fedora's control or interest. AuthZ, different story, but authN, not Fedora's business.

@ajs6f
Copy link

ajs6f commented Feb 2, 2017

Generally, there may or may not be an immediately proximate web server, but anyway, authN comes from upstream.

@ruebot
Copy link
Member

ruebot commented Feb 2, 2017

@jonathangreen if you need a hand, please don't hesitate to ask.

@jonathangreen
Copy link
Contributor

Don't worry, if anything I will ask too many questions :)

@jonathangreen
Copy link
Contributor

So here is my understanding of this ticket, just going to write it out to get everyones feedback.

We will be using JSON Web Tokens (JWT) for authentication between Islandora, Fedora and the associated micro services. Drupal will be the source of the JWTs. When Drupal emits events events to its queue, it will pass along tokens with them, that can later be used for authorization in various services. Tokens will also be able to be obtained through a REST endpoint. All services will use HTTPS for communication so as not to expose the tokens.

The JSON Web Tokens will be provided in Drupal by the JWT module:
https://www.drupal.org/project/jwt

The JWT claim will contain:

  • drupal username
  • array of drupal roles (is this needed? I think it could be helpful)
  • site identifier
  • expiration

header:

{
  "alg": "RS256",
  "typ": "JWT",
  "iss": "site identifier"
}

claim:

{
  "exp": "1234567890",
  "name": "John Doe",
  "roles": ["1", "2", "3"],
  "iss": "site identifier"
}

The JWT header will contain a copy of the site identifier, so that any filter wanting to validate the JWT will know which site it came from in the case where there are multiple Drupal sites communicating with the same services.

We will use the JWS (https://tools.ietf.org/html/rfc7515) algorithm secured with a digital signature to create the tokens. This means that anything wanting to verify the token will only need the public key of the site that issued the token in order to verify its claims.

Fedora will have a servlet filter that will accept the JWT and use this to authenticate the request. The Fedora servlet filter will have a configuration that takes site identifiers and the associated public key which it will use to verify the claims in the token.

Seem reasonable?

@ajs6f
Copy link

ajs6f commented Feb 2, 2017

My comment is just from the Fedora POV: that seems quite reasonable. (Y'all know that the first question is going to be "But does it work with my utterly obscure obsolete institutionally-mandated SSO system?!")

@whikloj
Copy link
Member

whikloj commented Feb 2, 2017

"Yes as long as your utterly obscure obsolete institutionally-mandated SSO works with JWTs"

@jonathangreen
Copy link
Contributor

(Y'all know that the first question is going to be "But does it work with my utterly obscure obsolete institutionally-mandated SSO system?!")

We can push that off to Drupal. "Yes as long as your utterly obscure obsolete institutionally-mandated SSO works with Drupal."

@whikloj
Copy link
Member

whikloj commented Feb 21, 2017

So I was doing some reading on this and now I have a question.

I can see how this works when syncing from Fedora to Drupal.

  1. Fedora requests JWT from Drupal
  2. Drupal provides JWT
  3. Fedora sends information to Drupal with JWT
  4. Drupal validates and processes request w/JWT

But how do we plan to use this for Drupal -> Fedora requests? Am I wrong in assuming that Fedora would have to provide a token that Drupal would use with its request and then Fedora would have to validate that token before processing the request.

Is this a place for API-X to come to the rescue or perhaps I skipped a basic point?

@jonathangreen
Copy link
Contributor

jonathangreen commented Feb 21, 2017

So the thing with JWT is they cryptographically sign the JWT. So the flow of information goes something like this:

  • Drupal emits a message, containing a JWT signed with the drupal private key
  • Message goes to message broker and gets forwarded however using camel pipeline
    • Messages either end up back at Drupal, in which case the JWT is verified in Drupal
    • Messages end up at Fedora (or really any other service)
      • Fedora uses the new "drupal filter" to verify the site by:
        • looking up the site, iss in the json snippet above, in a config file and finding the sites public key
        • verifying the signature on the JWT using the sites public key
        • if the verification passes fedora can assume the token was issued by the site, its content is valid and process the request (since whoever sent the request has the sites private key)

That lets us pass tokens from drupal -> fedora without having to do database lookups to verify usernames or passwords like we did in D7.

This all assumes that the connections take place over SSL, which in the end will be another part of this request, to ensure that all the inter-service connections happen over SSL.

The pull request to Islandora is just the first in a series of pull requests that will come out of this issue.

I still need to work on:

  • Having camel call back into drupal using the token
  • writing a servlet filter on the fedora side that takes the steps outlined above.

@whikloj
Copy link
Member

whikloj commented Feb 21, 2017

Also on this topic
https://github.com/cerker/jwt-example

@DiegoPino
Copy link
Contributor

@jonathangreen @whikloj ok! Should we have a quick discussion/planning meeting about this for the drupal ->fedora part?. Mostly because I don't see how things like WebAC fit in that user-less schema.

@jonathangreen
Copy link
Contributor

@DiegoPino the schema isn't userless. The user, and their roles get passed to Fedora in the JWT.

After the JWT is validated then Fedora will have all the information in the JWT to use:

{
  "exp": "1234567890",
  "iss": "1234567890",
  "drupal": {
    "uid": "1",
    "name": "username",
    "roles": ["rolea", "roleb", "rolec"],
    "url": "https://mysite.com"
  }
}

If we want to have a planning discussion about this, maybe we could add it to the agenda for the CLAW call this week. I'd like to have @dannylamb in on the call, since he created this ticket.

@DiegoPino
Copy link
Contributor

@jonathangreen ok! again, cool. I like planning and stuff but it is not required if you all feel you know your way. What I like most is understanding stuff! (so thanks for that clarification).
So: all that user data is passed to the queue (JMS) and then (have to check the workflow that dani wrote since I can't remember in which order that went) read by camel, which then uses that info to call Fedora camel component?. Starting to get that, slowly, slowly. Thanks!

@whikloj
Copy link
Member

whikloj commented Feb 21, 2017

Okay so let me know if I missed something (or everything) here

At the end of the Drupal -> Camel -> Fedora chain.

  1. Fedora receives the request with the JWT
  2. it decodes the JWT
  3. it gets the issuer (which is the Drupal site URL)
  4. it sends the JWT to some special Drupal URL to verify the JWT and return a response code.
  5. then Fedora can either process the request or fail.

I'm guessing that for step 4 we could make use of a new public or private claim like "validationURL", like /jwt/isValid. Where the concatenation of iss and vURL make a REST endpoint that responds if a passed JWT is valid (ie. http://drupal-site.org/jwt/isValid)?

@jonathangreen
Copy link
Contributor

@whikloj there is no call back to Drupal from the Fedora side.

  1. Fedora receives the request with the JWT
  2. it decodes the JWT
  3. it gets the issuer (which is the Drupal site URL)
  4. looks up the sites public key in a configuration file
  5. verify the signature on the JWT
  6. then Fedora can either process the request or fail.

@whikloj
Copy link
Member

whikloj commented Feb 22, 2017

@jonathangreen thanks, I think my understanding of the public/private key verifying was...missing something.

@jonathangreen
Copy link
Contributor

So final puzzle piece is here:
https://github.com/jonathangreen/syn

That repo implements a valve that can be used in tomcat so fedora4 will accept islandora's JWTs.

@jonathangreen
Copy link
Contributor

I think whenever someone is ready to pull the trigger, these pull requests are good to go in now from my perspective.

@ruebot
Copy link
Member

ruebot commented Mar 8, 2017

Partially resolved with: afcd377

@ruebot
Copy link
Member

ruebot commented Mar 8, 2017

Partially resolved with: Islandora/Alpaca@5cd05d8

@ruebot
Copy link
Member

ruebot commented Mar 8, 2017

Third and final commit: islandora-deprecated/claw_vagrant@0d633be

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants