readium / lcp-specs

🔐 Releases, drafts and schema for Readium LCP
https://readium.org/lcp-specs/
BSD 3-Clause "New" or "Revised" License
9 stars 5 forks source link

Transmitting a hashed passphrase in OPDS and in an OAuth flow #41

Open HadrienGardeur opened 4 years ago

HadrienGardeur commented 4 years ago

In order to provide a seamless experience with LCP, a number of organizations are interested in the ability to transmit the hashed passphrase associated to a user/license.

This has been implemented before by:

IMO, we need to cover the following scenarios:

OPDS 2.0 and OAuth could use the same JSON key, while OPDS 1.x requires an XML element and a namespace for it.

cc @leonardr @llemeurfr @RemiBauzac @picheromy

HadrienGardeur commented 4 years ago

Here's my proposal:

Regarding the name of this new JSON key, I would suggest using lcp_hashed_passphrase for a few reasons:

In OAuth 2.0 this could be transmitted in the Response Document:

{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "lcp_hashed_passphrase": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}

In OPDS 2.0 this could be transmitted in the properties of a link:

{
  "links": [
    {
      "href": "https://example.com/license.lcpl",
      "rel": "http://opds-spec.org/acquisition/",
      "properties":  {
        "lcp_hashed_passphrase": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
      }
    }
  ]
}

In the future, we'll be able to use this same JSON key in a user's profile as well.

llemeurfr commented 4 years ago

I totally agree about using the term "LCP hashed passphrase". The LCP spec itself will be enhanced this way.

HadrienGardeur commented 4 years ago

This current proposal doesn't cover use cases where the acquisition of an LCPL license triggers the discovery/exchange of a hashed passphrase through authentication.

Let me explain some of the reasons behind this:

leonardr commented 4 years ago

4.2 of the LCP spec says "There are no requirements for how [the User Passphrase] is to be created." 4.1 talks about prompting the user, but it doesn't look like a requirement.

I bring this up because I think we (Library Simplified) do want to have a piece of middleware generate the User Passphrase for an authenticated user and then share the User Key with the user's client so they can decrypt books.

If this is a problem I'd like to talk about possible alternatives (having the client generate the User Passphrase) or safeguards (requiring that the client display the User Key in its UI somewhere).

HadrienGardeur commented 4 years ago

@leonardr

It's perfectly fine to generate a passphrase as long as it's easily available to the user. You can for example provide the passphrase in the required "hint" URL included in every LCP license.

That said in general, I would recommend doing things in the following order:

RemiBauzac commented 4 years ago

Hello @HadrienGardeur @llemeurfr and @leonardr , I'm pleased to see that the subject comes back on the top of the stack. I'm sorry because my English is no better than it was a few months ago 😄

From Hadrien:

  • we want to avoid situations where authentication replaces the normal behavior (asking the user for a passphrase), since this could be used for bad reasons (for example, using authentication to avoid giving the passphrase to the user)
  • there's a lot of complexity around authentication, which would require additional discovery for OAuth 2.0 as well as other authentication techniques

I do not completely agree with Hadrien on the subject of authentication because:

  1. User authentication may be imposed by some suppliers/publishers (UK ones) on their content, and in this case we have found no better than :
    • generated a passphrase unknown by the user
    • to request user credentials, and thus distribute the key
  2. requesting user authentication is the simplest, most efficient and transparent way for the user. In this case (and if publishers allow it, this is the case in most countries), we have:
    • a passphrase known to the user (chosen by him or not). He can know his passphrase by seeing it on his invoice or in his personal account (from his bookshop or public library).
    • A simple way to do without the passphrase if the reading device allows hashed key retrieval
    • Another way to enter directly the passphrase on reading device.
  3. Authentication mechanisms must reflect real use cases. We do not use OAuth2 or ODPS for our own pleasure. It just answer real cases questions. Some cases are very simple, and simple things can answer it. Some cases are more complex, and complex authentications scheme are needed.

Again, getting hashed key from user authentication result (or whatever you want) must not break the "basic case". This is a device decision :

So I think we can start to define what are the different key discovery use cases, and then define the best ways to answer this use cases.

I hope to have the opportunity to discuss the subject directly with you.

HadrienGardeur commented 4 years ago
  1. User authentication may be imposed by some suppliers/publishers (UK ones) on their content, and in this case we have found no better than :
    • generated a passphrase unknown by the user
    • to request user credentials, and thus distribute the key

I understand that scenario, but IMO if you go down that road you're no longer part of the LCP ecosystem. It's a different DRM solution based on LCP, but that shouldn't reference LCP in its name.

  1. requesting user authentication is the simplest, most efficient and transparent way [...] [...] Some cases are very simple, and simple things can answer it. Some cases are more complex, and complex authentications scheme are needed.

These two statements somehow contradict one another. My second point was that authentication is a complex matter, with many scenarios that won't always result in a simple UX.

I don't think that we should be producing a technical note that will encompass all scenarios (it's impossible), which is why the suggested approach (define a JSON key and highlight how it may be used in an OAuth Response Document or in OPDS 2.0) IMO works best than what was discussed within EDRLab before.

llemeurfr commented 4 years ago

We should not mix in the same issue discussions about the new LCP key retrieval feature we want to propose to implementers with a discussion about the core LCP passphrase access mechanism, i.e. asking the user. It is true that implementations hiding passphrases from their user cannot market their solution as Readium LCP compliant, as expressed in the LCP Compliance Rules released by EDRLab.

@HadrienGardeur, if I understand well, your proposal tries to simplify the protocol and keep only 2 steps: a. authentication (whatever it is) b. direct retrieval of the hashed passphrase. In some cases these two steps are even merged, as the hashed passphrase is given as a response to the OAuth 2.0 authentication. My first question is, what happens if an off-the-shelves OAuth server cannot easily return the hashed passphrase? (I'll take a look at https://github.com/go-oauth2/oauth2)

RemiBauzac commented 4 years ago

Hi @HadrienGardeur

I understand that scenario, but IMO if you go down that road you're no longer part of the LCP ecosystem. It's a different DRM solution based on LCP, but that shouldn't reference LCP in its name.

Yes you're right, I totally agree, but if I am a "book shop" (or public library) having "LCP friendly" and "not LCP friendly catalog"... what can I do ? Using Adobe (👏 ) ! I know that there is no solution in that case, this is a real issue for me.

Hi @llemeurfr, Yes, I mix two different things. My bad ! Sorry. I agree with the 2 steps (Authentication, then key retreival) scenario, even in OAuth2, because sometimes, the server which owns the users for authentication are not the same than the server which owns the keys. This is a little bit more complex, but it can be useful. For off-the-shelves OAuth servers, It's not really a big deal to add informations in token response.

Have a nice week end.