owncloud / openidconnect

OpenId Connect (OIDC) Integration for ownCloud
GNU General Public License v2.0
6 stars 3 forks source link
openid owncloud owncloud-app

OpenId Connect for ownCloud

Quality Gate Status Security Rating Coverage

Configuration

General

A distributed memcache setup is required to properly operate this app - like Redis or memcached. For development purpose APCu is reasonable as well. Please follow the documentation on how to set up caching.

Setup

The OpenId integration is established by either entering the parameters below to the ownCloud configuration file or saving them to the app config database table.

provider-url, client-id and _client-secret- are to be taken from the OpenId Provider setup. loginButtonName can be chosen freely depending on the installation.

Settings in database

If you run a clustered setup, the following method is preferred because it is stateless. The OpenID Connect app checks for settings in the database first. If none is found, it falls back to the settings stored in config.php. If a malformed JSON string is found, an error is logged. You have to store your settings as a JSON formatted string in the ownCloud database table oc_appconfig with the following keys:

Key Value
appid 'openidconnect'
configkey 'openid-connect'
configvalue JSON-String

The key->value pairs are the same as when storing them to the config.php file. The preferred method is using the occ command:

occ config:app:set openidconnect openid-connect \
--value='{"provider-url":"https://idp.example.net","client-id":"fc9b5c78-ec73-47bf-befc-59d4fe780f6f","client-secret":"e3e5b04a-3c3c-4f4d-b16c-2a6e9fdd3cd1","loginButtonName":"Login via OpenId Connect"}'

This task can also be done by opening the database console for your ownCloud database and enter the following example command. Use the database commands UPDATE or DELETE to change or delete this keys (not recommended).

INSERT INTO oc_appconfig (
  appid,
  configkey,
  configvalue
) VALUES (
  'openidconnect',
  'openid-connect',
  '{"provider-url":"https://idp.example.net","client-id":"fc9b5c78-ec73-47bf-befc-59d4fe780f6f","client-secret":"e3e5b04a-3c3c-4f4d-b16c-2a6e9fdd3cd1","loginButtonName":"Login via OpenId Connect"}'
);

Note: The app checks for settings in the database first. If none is found it falls back to the config.php. If a malformed JSON string is found an error is thrown to the logger instance.

Settings in config.php

<?php
$CONFIG = [
  'openid-connect' => [
    'provider-url' => 'https://idp.example.net',
    'client-id' => 'fc9b5c78-ec73-47bf-befc-59d4fe780f6f',
    'client-secret' => 'e3e5b04a-3c3c-4f4d-b16c-2a6e9fdd3cd1',
    'loginButtonName' => 'OpenId Connect',
  ],
];

The above configuration assumes that the OpenId Provider is supporting service discovery. If not the endpoint configuration has to be done manually as follows:

<?php
$CONFIG = [
  'openid-connect' => [
    'provider-url' => 'https://idp.example.net',
    'client-id' => 'fc9b5c78-ec73-47bf-befc-59d4fe780f6f',
    'client-secret' => 'e3e5b04a-3c3c-4f4d-b16c-2a6e9fdd3cd1',
    'loginButtonName' => 'OpenId Connect',
    'post_logout_redirect_uri' => '...',
    'provider-params' => [
      'authorization_endpoint' => '...',
      'token_endpoint' => '...',
      'token_endpoint_auth_methods_supported' => '...',
      'userinfo_endpoint' => '...',
      'registration_endpoint' => '...',
      'end_session_endpoint' => '...',
      'jwks_uri' => '...',
    ],
  ],
];

Setup auto provisioning mode

The auto provisioning mode will create a user based on the provided user information as returned by the OpenID Connect provider. The config parameters 'mode' and 'search-attribute' will be used to create a unique user so that the lookup mechanism can find the user again.

<?php
$CONFIG = [
  'openid-connect' => [
    'auto-provision' => [
      // explicit enable the auto provisioning mode
      'enabled' => true,
      // documentation about standard claims: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
      // only relevant in userid mode,  defines the claim which holds the email of the user
      'email-claim' => 'email',
      // defines the claim which holds the display name of the user
      'display-name-claim' => 'given_name',
      // defines the claim which holds the picture of the user - must be a URL
      'picture-claim' => 'picture',
      // defines a list of groups to which the newly created user will be added automatically
      'groups' => ['admin', 'guests', 'employees'],
    ],
  ],
];

Setup auto-update of user account info

The provisioning auto-update mode will update user account info with current information provided by the OpenID Connect provider upon each log in.

$CONFIG = [
  'openid-connect' => [
    'auto-provision' => [
      'update' => [
        // enable the user info auto-update mode
        'enabled' => true,
      ],
    ],
  ],
];

All Configuration Values explained

Setup within the OpenId Provider

When registering ownCloud as OpenId Client use https://cloud.example.net/index.php/apps/openidconnect/redirect as redirect url .

In case OpenID Connect Front-Channel Logout 1.0 is supported please enter https://cloud.example.net/index.php/apps/openidconnect/logout as logout url within the client registration of the OpenId Provider. We require frontchannel_logout_session_required to be true.

Setup service discovery

In order to allow other clients to use OpenID Connect when talking to ownCloud please setup a redirect on the web server to point .well-known/openid-configuration to /index.php/apps/openidconnect/config

This is an .htaccess example

  RewriteRule ^\.well-known/openid-configuration /index.php/apps/openidconnect/config [P]

The Apache modules proxy and proxy_http need to be enabled. (Debian/Ubuntu: a2enmod proxy proxy_http)

How to setup an IdP for development and test purpose

There are various Open Source IdPs out there. The one with the most features implemented seems to be panva/node-oidc-provider. CAUTION: node-oidc-provider does not accept the redirect URLs we need for owncloud clients. For release testing, use kopano konnectd instead.

To set it up locally do the following:

  1. Clone panva/node-oidc-provider

  2. yarn install

  3. cd example

  4. Add client config into https://github.com/panva/node-oidc-provider/blob/master/example/support/configuration.js#L14

    module.exports.clients = [
     {
       client_id: 'ownCloud',
       client_secret: 'ownCloud',
       grant_types: ['refresh_token', 'authorization_code'],
       redirect_uris: ['http://localhost:8080/index.php/apps/openidconnect/redirect'],
       frontchannel_logout_uri: 'http://localhost:8080/index.php/apps/openidconnect/logout'
     }
    ];
    
    // Enable introspection
    module.exports.features: {
      devInteractions: { enabled: false },
      introspection: { enabled: true },
      deviceFlow: { enabled: true },
      revocation: { enabled: true },
      issAuthResp: { enabled: true },
    },
    
  5. Start the IdP via: node standalone.js

  6. Open in browser: http://localhost:3000/.well-known/openid-configuration

  7. ownCloud configuration looks as follows:

    $CONFIG = [
     'openid-connect' => [
         'provider-url' => 'http://localhost:3000',
         'client-id' => 'ownCloud',
         'client-secret' => 'ownCloud',
         'loginButtonName' => 'node-oidc-provider',
         'mode' => 'userid',
         'search-attribute' => 'sub',
         // do not verify tls host or peer
         'insecure' => true
     ],
    ];
    
  8. Clients can now use http://localhost:3000/.well-known/openid-configuration to obtain all information which is necessary to initiate the OpenId Connect flow. Use the granted access token in any request to ownCloud within a bearer authentication header.

  9. You can login with any credentials but you need to make sure that the user with the given user id exists. In a real world deployment the users will come from LDAP.

    • Keep in mind that by default, oidc app will search for the email attribute - which is hardcoded to johndoe@example.com ref
    • If you wish to map the login name on the oidc-provider with owncloud user ids, you can configure it as following:
    $CONFIG = [
      'openid-connect' => [
        'search-attribute' => 'sub',
        'mode' => 'userid',
      ]