Problem/Motivation

Drupal 7 only supported cookie authentication. Drupal 8, because it wants to be API-first, has the concept of authentication providers. The only one included with Drupal core is \Drupal\basic_auth\Authentication\Provider\BasicAuth, in the basic_auth module.

This means that when you use the REST module in core (or the JSON API or GraphQL modules in contrib), you can only use:

  1. Cookie authentication
  2. HTTP Basic authentication
  3. … and no authentication (anonymous)

Neither of these are considered best practices when interacting with REST APIs. In fact, all of them are terrible choices, and are heavily looked down upon.

The vast majority of these APIs use OAuth 2.0. Specifically, OAuth 2 bearer token.

Proposed resolution

As part of the API-first initiative (#2757967: API-first initiative), we'd like to propose to add OAuth2 to Drupal 8.3 core as an experimental module. This should come as no surprise because #2757967 has mentioned it since being published on June 29.

@e0ipso is the maintainer of the https://www.drupal.org/project/simple_oauth module, which implements OAuth2 bearer token. Unfortunately, it's all Drupal-specific code. Even though the OAuth 2.0 spec is notoriously difficult to implement correctly/completely. So, bringing this module to Drupal 8 core would've had quite a big associated risk: we'd be taking on building and maintaining our own implementation of an OAuth 2 server.

A much lower risk would be to use the PHP library that is the most widely installed/depended upon library in the entire PHP ecosystem to build an OAuth 2 server: thephpleague/oauth2-server. We proposed he rewrite his module on top of that. e0ipso started doing so, and in fact finished doing so a few days ago: https://www.drupal.org/project/simple_oauth/releases/8.x-2.0-alpha1 is the first release of the 8.x-2.x branch.

Even though this branch of the module has only existed for a very short time, we think it's appropriate to include it in Drupal 8.3:

  1. including the 8.x-1.x branch would be signing us up for maintenance of the implementation of a complex spec: dangerous
  2. we're building on top of a mature, broadly used, battle-hardened implementation: thephpleague/oauth2-server with more than one million downloads and extensive test coverage. This library is used for OAuth purposes in popular frameworks like Laravel and Cake PHP 3. The library implements the following RFCs:
  3. not having Oauth2 in core could lead to many more people not using Oauth2 at all, thus being less secure and giving decoupled Drupal a bad reputation
  4. the library itself has extensive test coverage (and the Drupal module already has functional tests)
  5. this module would never get as much usage in contrib as it would in core, even if only for discoverability reasons. So only if it's in core, we'll get the massive real-world feedback we need for something like this to mature & graduate to "stable in core"
  6. There are 4 types of OAuth2 grants — we can decide which grants we want in core and leave the rest for the oauth2_advanced contrib module.

Remaining tasks

  1. Consensus about the principle that we want to add oauth2 authentication to Drupal 8 core as an experimental module.
  2. After that basic consensus: we need to agree on which types of grants make sense for Drupal core to support. (Any grant types we agree don't make sense for core can be supported by a oauth2_advanced module in Drupal 8 contrib.)
  3. After complete consensus:
    1. Review cycle
    2. Commit

User interface changes

None.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
#6 Which Grant? 2016-12-12 12-04-04.png94.95 KBe0ipso
Members fund testing for the Drupal project. Drupal Association Learn more

Comments

Wim Leers created an issue. See original summary.

Gábor Hojtsy’s picture

Project: Drupal core » Drupal core ideas
Version: 8.3.x-dev »
Component: rest.module » Idea

IMHO this should be in the ideas queue.

Wim Leers’s picture

Category: Feature request » Plan
Priority: Major » Normal
Issue tags: +Needs framework manager review, +Needs product manager review
skyredwang’s picture

I am not questioning anyone's work or decision. I haven't looked OAuth2 for 3 years. Just wondering how OAuth2 solved its own problem:

more complex, less interoperable, less useful, more incomplete, and most importantly, less secure.

-- https://hueniverse.com/2012/07/26/oauth-2-0-and-the-road-to-hell/

mikl’s picture

Great idea, this would go a long way towards establishing Drupal as a serious web service platform. OAuth2 is finicky and hard to get right, so an out of the box solution would be great.

#4: Despite these criticisms, OAuth2 has become the industry standard for web service authentication. There is no successful competing standard, and while not perfect, it's still much, much better than cookies or HTTP Basic Auth.
Thus, adding OAuth2 would be a definite improvement, and I don't think we ought to let perfect be the enemy of good here.

e0ipso’s picture

In regards to #4.

There was quite a reaction after that post (from one prominent OAuth 1 contributor). Although I haven't been following close, I don't seem to recall any security scandals related to the OAuth2 protocol itself in many years after those predictions.

Alex Bible (the author of the OAuth2 library that backs the proposed module) describes Hawk in https://www.alexbilbie.com/2012/11/hawk-a-new-http-authentication-scheme. It's interesting his take on:

The Hawk documentation says that is can be used for client to server authentication but I think it would also make an easier to implement (than OAuth) authentication protocol if you are implementing machine to machine authentication.

For delegating access to protected resources then the documentation recommends Oz as alternative to OAuth.

Which hints that without Oz, Hawk may be only covering a limited set of use cases. The following diagram explains the use cases that OAuth 2 can cover.

OAuth 2 grants

dawehner’s picture

After that basic consensus: we need to agree on which types of grants make sense for Drupal core to support. (Any grant types we agree don't make sense for core can be supported by a oauth2_advanced module in Drupal 8 contrib.)

If we talk about MVP maybe its enough to start with supporting just user access token owners, and then maybe bring in the machine one later.
Given then we of course we should really support a user-agent-based app, much better described as (

If the client is a web application that has runs entirely on the front end (e.g. a single page web application) you should implement the password grant for a first party clients and the implicit grant for a third party clients.

. On top of that we also want to support a more traditional web app. For user-agent=based apps it seems okay from a MVP point of view to start with just first party support which leaves us with the following two grant systems:

  • Password grant
  • Authorization code grant
andypost’s picture

Would be great to update summary why thephpleague/oauth2-server considered as mature, who are other competitors and how release cycle of this one fits in core release cycle

e0ipso’s picture

Issue summary: View changes
e0ipso’s picture

@andypost I updated the issue summary with some more context on why to use this library. This was also recommended by @Crell at DrupalCon Dublin during the API-First hard problems meeting. Quoting from Preston's meeting notes

Larry: I don’t know if the OAuth2 module in Drupal uses the PHP League’s implementation. As Peter said, there are a million flavors of OAuth2, but that’s the one that the PHP community seems to be consolidating around.

The other contestant is https://packagist.org/packages/bshaffer/oauth2-server-php. I would rate it at a similar lever as the League's library: +1M downloads, used on the Slim and Yii frameworks, good test coverage and sticking to the FIG recommendations.

I'm unsure if there is a lot of benefit to switch to bshaffer/oauth2-server-php, but I'm completely certain that if we did it would get the job done. I couldn't find any online post comparing both libraries.

e0ipso’s picture

The 3 grants that I think are the most interesting to have in core are:

Password grant
  • Because it's a first party grant and therefore we can assume the Drupal admin can configure the client application. Besides we can avoid the complexity added by the redirection flow of the Auth code and the Implicit grants.
  • Because it's a one to one match to the user system native in Drupal.
  • It works well to authenticate requests for a given end user.
Refresh grant
  • Because it's a first party grant and therefore we can assume the Drupal admin can configure the client application. Besides we can avoid the complexity added by the redirection flow of the Auth code and the Implicit grants.
  • Without the refresh grant, implementors will have the temptation to use very long expiration times. That makes the token slightly more vulnerable to attacks. Using a refresh grant will solve that.
  • The refresh grant usually comes hand with hand with the password grant and auth code. That's why it's not in the diagram.
Client credentials
  • Because it's a first party grant and therefore we can assume the Drupal admin can configure the client application. Besides we can avoid the complexity added by the redirection flow of the Auth code and the Implicit grants.
  • It works well to authenticate requests for a client/app wide user. This can be used for machine to machine processes, like for instance a cron job in a different server that executer REST requests that require authentication. In that scenario there is one user for the client/app, for instance crm_cleanup_process.
Crell’s picture

I've not used either bshaffer's library or the League's library myself, so have no personal experience to offer. However, there are a bunch of add-ons for the League library that talk to various other OAuth services (Facebook, Google, GitHub, Twitter, etc.). That seems potentially useful. Also if the code to use the League's library is already written, well, shipping code wins.

I'm on board with adding OAuth to core via a 3rd party library and bridge code. I am 100% against adding a custom OAuth implementation to core, for the various reasons already given. (Largely the "no, we don't want to maintain that" argument.)

pjcdawkins’s picture

I have a fair amount of experience with both libraries, and I'd lean towards recommending the League's one, as I have the impression it's easier to work with and more actively maintained.

However, I'd just like to point out the existence of the (very popular in D7) https://www.drupal.org/project/oauth2_server module, which uses bshaffer's library.

Crell’s picture

A completely unscientific Twitter feedback request suggests both libraries are "good": https://twitter.com/Crell/status/809849007849738240

giorgio79’s picture

As I understand, an oauth server would allow Drupal to become an identity provider for third parties, right? If yes, IMHO Drupal missed the identity bus a long time ago. How about we take care of the other side of the equation? Who fills out email / password fields these days? Lets use Hybridauth in core.

Don't reinvent the wheel :)

e0ipso’s picture

As I understand, an oauth server would allow Drupal to become an identity provider for third parties, right?

@giorgio79 the current proposal, as suggested in #11, will leave the 3rd party grants for a contrib module. So that statement is not 100% correct. It will allow users to use their credentials "without having to send them back and forth" between the server and the client. Moreover the two grants that are proposed do not assume a web page to have a person type their LinkedIn/Facebook/… password.

If you look at the diagram at #6 you can see that the OAuth grant that you are thinking of is Authorization code (and maybe Implicit grant). If you are curious about what those grants look like, you can watch videos 8 and 9 of this video series.

hampercm’s picture

The intent behind adding OAuth2 here is to improve authentication/authorization for REST and similar APIs, rather than replacing the traditional user login. I definitely think this is an important step for Drupal's API-first Initiative, as OAuth2 support among App frameworks like Ember.js is readily available, and much preferable to the only current option: Basic Auth.

I don't think that adding HybridAuth (which relies on third-party services to authorize access) to core is philosophically on-target, and not really the use case being discussed here.

e0ipso’s picture

@hampercm I think I understand from your comment that you think it's a good idea to include OAuth2 into core as an experimental module. Please correct me if I'm wrong.

Wim Leers’s picture

@giorgio opened #2837115: Enable one click login / registration with hybridatuh to propose hybridauth for core inclusion. Please keep all discussion about it in that issue.

budda’s picture

Having oAuth2 in core would make the whole authentication area one less thing to think above when using the API services of Drupal 8.
Using an existing library to reduce maintenance gets my vote too.

David Hernández’s picture

+1 to support open standards and even with more reason if it helps to move a step forward the API First initiative.

pounard’s picture

My 2 cents: I did a thorough comparison of various PHP OAuth2 libraries a few month ago in order to implement it for a client site, and the League's one was my choice.

I wouldn't change for anything, it has a very good support of the OAuth2 protocol, very secure, but there a few problems to go along:

  • Security provided by the library does not relieves you from writing secure controllers, it is very important to understand that a single wrong or missing comparison can make all other security measures useless;
  • You have to write an awful lot of code yourselves, it provides what it calls repositories that you have to implement yourself (it's the link between the data that transits over https and your data) - it must be implemented very thoroughly (please do not use entities for this, it would be very dumb);
  • There is one major problem: it uses JWT tokens to pass data between client and server, they are basically encrypted chunk of data that contains pretty much the library needs (user identifiers, client identifier, etc...) so it doesn't have to store it locally. This is very WRONG idea, and if you're not going to use the 6.x next major of the library, but the 5.x instead, this specific point will need to be overriden for two obvious reasons:
    • Security, even though JWT tokens are highly encrypted, it still private internal data passing through client-visible-yet-unreadable data;
    • Tokens are too long, and in real life I happened to broke the default OpenAM auth server http parameter size limit (which is 512) - which was actually the real reason why I did had to override it. Only after I read more about security.
  • It is a very good library, and its main author (he mostly is only one) is very reactive, and very nice.
  • He is mostly only one, so if he goes in vacations, you're f*cked if you need to ask questions (happened to me).

OAuth2 is not a complicated protocol, but its implementation definitely is, and even if you use a good library, you MUST read and learn the full spec before going into it: a well designed and well written API is NOT ENOUGH to ensure security.

e0ipso’s picture

@pounard there is a first draft of an implementation in https://www.drupal.org/project/simple_oauth (8.x-2.x). I'd appreciate if you could give it a quick review and log your concerns somewhere in the issue queue to get closer to a prototype for this issue.

pounard’s picture

@e0ipso I can't promise you I will, but I'll try to save some to time to do this during the next week.

hampercm’s picture

@e0ipso Yes, definitely a +1 for OAuth2 in core from me. Considering the league's OAuth2 library is already utilized in the simple_oauth module, it makes sense to me to stick with that, unless there is a great advantage to using another library. From other feedback, it appears there isn't a major difference, so I'd also +1 sticking with what is already there, the League's OAuth2 library.

e0ipso’s picture

I'm not familiar with this whole experimental module process. Should I wait until I get green light from all the framework and/or product managers before working on a patch?

It seems that Dries Buytaert (BDFL, Product Manager) gave his OK to this idea in his blog http://buytaert.net/improving-drupal-8-api-first-json-api-oauth2.

I am currently holding on to this (as stated in the Next Steps section in the IS), but I want to make sure that they are not waiting for an actual patch before doing an evaluation.

Wim Leers’s picture

Regarding which grants to include: it seems everyone wants the password grant. So let's do only the password grant in the patch that brings OAuth 2 to Drupal 8.3. So that's the MVP then. More grants can be added in future commits.

(Because this would be an "alpha" experimental module, we would be able to add new functionality even after 8.3.0 is released.)

e0ipso’s picture

@Wim Leers, as discussed in https://youtu.be/Hk0L1vfgAOI?t=6m30s I think this is a very good way to simplify the scope and have a simpler patch.

Copying from #11, I think that Password Grant is a good idea:

  1. Because it's a first party grant and therefore we can assume the Drupal admin can configure the client application. Besides we can avoid the complexity added by the redirection flow of the Auth code and the Implicit grants.
  2. Because it's a one to one match to the user system native in Drupal.
  3. Because It works well to authenticate requests for a given end user.

After that is committed, adding the Refresh Grant will be just a small plugin class (grants are plugins).

dawehner’s picture

When I understand it correctly this is the most common uscase of running Drupal headless. Not as 3rd party app, nor as dedicated web app accessing your data over the wire, but rather as 1st party client side application.

Given that supporting just the password one sounds totally sensible.

e0ipso’s picture

Would it be fair to say that we have achieved:

  1. Consensus about the principle that we want to add oauth2 authentication to Drupal 8 core as an experimental module.
  2. After that basic consensus: we need to agree on which types of grants make sense for Drupal core to support. (Any grant types we agree don't make sense for core can be supported by a oauth2_advanced module in Drupal 8 contrib.)

When consensus has been reached, we should move this to RTBC.

Wim Leers’s picture

Status: Active » Reviewed & tested by the community

I agree, I think we've reached consensus. The password grant is the MVP. #27 + #28 + #29 agree. A week since #29 without additional pro/con messages suggests few people actually have strong enough opinions to leave a comment.

So, moving to RTBC.

hampercm’s picture

+1 for Password Grant. I'd also like to see Refresh Grant, as it enables following the OAuth2 recommendation of short access token lifetimes.

Wim Leers’s picture

Status: Reviewed & tested by the community » Postponed