Feature #24808

OAuth2 support for Redmine API Apps (OAuth2 Provider)

Added by Jan from Planio www.plan.io about 1 month ago. Updated 13 days ago.

Status:Needs feedbackStart date:
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:REST API
Target version:-
Resolution:

Description

I think, we should make Redmine an OAuth2 provider, so that client apps using Redmine's API can ask users to authenticate rather than asking for an API key. Another goal would be to limit access to API client apps, so that not all apps gain access to the full scope of data a user has access to.

I'm working on this currently and I will hopefully be able to submit a patch soon. Here's a first screenshot:

redmine_oauth2_provider.png (330 KB) Jan from Planio www.plan.io, 2017-01-11 11:54

my_account.png (80.6 KB) Jan from Planio www.plan.io, 2017-01-18 17:35

authorized_apps.png (206 KB) Jan from Planio www.plan.io, 2017-01-18 17:35

auth_prompt.png (218 KB) Jan from Planio www.plan.io, 2017-01-18 17:35

apps.png (261 KB) Jan from Planio www.plan.io, 2017-01-18 17:35

0001-Use-named-routes-for-search-in-base-layout.patch Magnifier (2.83 KB) Jan from Planio www.plan.io, 2017-01-18 17:46

0002-Prevent-hash-type-URLs-from-being-namespaced-in-Menu.patch Magnifier (2.03 KB) Jan from Planio www.plan.io, 2017-01-18 17:46

0004-Redmine-style-UI-for-Doorkeeper-OAuth2-provider.patch Magnifier (15.7 KB) Jan from Planio www.plan.io, 2017-01-18 17:46

0005-Add-optional-scope-parameter-to-Role-allowed_to.patch Magnifier (4.27 KB) Jan from Planio www.plan.io, 2017-01-18 17:46

0006-Use-Redmine-s-permissions-as-OAuth2-scopes.patch Magnifier (7.87 KB) Jan from Planio www.plan.io, 2017-01-18 17:46

0003-Add-OAuth2-provider-capability-using-doorkeeper-gem.patch Magnifier (9.81 KB) Jan from Planio www.plan.io, 2017-01-29 16:23

History

#1 Updated by Jan from Planio www.plan.io about 1 month ago

The attached patch series implements full OAuth2 provider support for Redmine.

Background

OAuth2 is a widely adopted protocol for granting access to API client applications. More information can be found here:

Screenshots

Here are a few screenshots that show how it looks like:


Admins are able to create/modify/delete OAuth2 client apps from the user interface.


OAuth2 App credentials are generated and can then be used in API clients.


In order for an App to gain access to Redmine, it must ask the user for permission.


Regular users are able to see which apps currently have access to their data from their My Account area.


Regular users are able to revoke access to individual apps.

Live Demo

We are providing a live demo server and client via these links:

https://server.redmine-oauth.planio.org

Username/Password is admin:oauth2. The content on this server will be reset every 60 minutes. Feel free to create your own OAuth2 applications via the Admin section, but please don't modify/delete the "Sinatra Client App".

https://client.redmine-oauth.planio.org

You can use this app to try out the authentication/authorization flow. Feel free to create your own user accounts on the Redmine server for this.

The /issues API will only work if the view_issues scope is requested. If only the standard scopes are requested, you will see an error here (on purpose).

Feel free to download the client app code from our Planio repository to try out everything locally.

The patch series

  • 0001 changes the base layout to use named routes. The old hash-style routes (e.g. {controller => 'search', :action => 'index'}) would get namespaced when the layout is used in a namespaced controller in a plugin or engine which is the case with the Doorkeeper gem introduced later.
  • 0002 changes the MenuManager in a similar way and prevents the rendered menu links from getting namespaced in the above scenario.
  • 0003 adds the Doorkeeper Gem and integrates it with Redmine in the relevant places. You could apply patches 0001-0003 only to get functioning OAuth2 provider support already. In detail, what happens is:
    • Gemfile - Gem is added in
    • app/controllers/application_controller.rb - Doorkeeper is used as a new optional authentication mechanism that is tried when regular Redmine API auth fails
    • app/views/my/account.html.erb - Link to Doorkeeper's views for managing a user's authorized apps
    • config/initializers/doorkeeper.rb - Configure Doorkeeper so that it ties in with Redmine's user and admin authentication
    • config/routes.rb - Add Doorkeeper specific routes and root_url which is needed by it
    • db/migrate/20170107092155_create_doorkeeper_tables.rb - Migrations to add Doorkeeper tables
    • lib/redmine.rb - Link to Doorkeeper's views for managing available apps within the admin section
    • public/stylesheets/application.css - Icon for Apps
    • test/unit/lib/redmine/i18n_test.rb - Fix locale counting in tests because doorkeeper-i18n introduces languages unknown to Redmine
  • 0004 - integrates Doorkeeper further by overriding all views with Redmine compatible markup and makes use of Redmine's deny_access and require_login methods which become available once the Doorkeeper controllers are set to inherit from Redmine's ApplicationController
  • 0005 - changes Role#allowed_to? so that it can accept an optional scope parameter which can be an array of permission symbols that will be used as a logical AND filter.
  • 0006 - Allows OAuth2 client apps to use Redmine permissions as Scopes in the sense of OAuth2. This way, admins and application developers can limit the abilities of client apps. An app will generally have at most the permissions defined by the App definition or as reqested by the app during the auhtorization step. Of course, the app will never have more permissions than the user is has requested authorization for would have in a normal interactive scenario.

Considerations

Why use Doorkeeper?

Implementing OAuth2 "by hand" seemed like re-inventing the wheel. Building and maintaining such security-critical code is both error-prone and non-trivial. The Doorkeeper Gem is the de-facto standard solution for implementing an OAuth2 provider in Rails. It's tried and tested, well-maintained and used by many high profile apps and services.

Integrating it with Redmine required only minor changes to Redmine's code base itself which should hopefully make maintenance of this functionality quite easy.

Why can only admins create apps?

The decision that only Redmine admins can add new API client applications is debatable, but it felt like the easiest solution for this first version. Allowing regular users to create apps would have required more overridden Doorkeeper controllers, new Redmine permissions (e.g. add_apps, view_apps, destroy_apps, etc.)

In addition to that, enabling/diasbling things like the REST API, JSONP support, etc. is currently also only available to admins, so I thought it would be consistent.

Some translations are missing! Where are the I18n keys?

At the moment, I've included them via the doorkeeper-i18n Gem. Technically, we could pull the locales in to Redmine's code base. However, – in the spirit of open source – I'd advcate in favor of keeping them in the external Gem and working with the Doorkeeper maintainers to improve them if needed. I've fixed two issues with the locales already via pull requests and they were accepted rather quickly.

That's it for now. I am looking forward to your feedback!

#2 Updated by Marius BALTEANU 26 days ago

IMO, I think that the OAuth2.0 provider will be a great addition to Redmine and a feature that we'll use for sure at our future integrations with other apps.

What I like very much is the separation between the users and applications. Now we've some users named like "<application_name>-Generic User" used to authenticate the API calls. Having the possibility to define them as apps and manage their permissions from a different screen is very useful.

#3 Updated by Jan from Planio www.plan.io 26 days ago

  • Description updated (diff)

#4 Updated by Jan from Planio www.plan.io 23 days ago

  • File deleted (0003-Add-OAuth2-provider-capability-using-doorkeeper-gem.patch)

#5 Updated by Jan from Planio www.plan.io 23 days ago

  • File 0003-Add-OAuth2-provider-capability-using-doorkeeper-gem.patch added

Slightly updated version of 0003, using wider columns for scopes

#6 Updated by Jan from Planio www.plan.io 22 days ago

  • File deleted (0003-Add-OAuth2-provider-capability-using-doorkeeper-gem.patch)

#8 Updated by Akipii Oga 13 days ago

+1

Also available in: Atom PDF