Skip to content

Commit

Permalink
Allow independent OIDC config by provider
Browse files Browse the repository at this point in the history
Allow OIDC provider settings to be configured independently for each
provider.

This corrects an issue where these settings applied to every configured
OIDC provider.

OIDC app.yml settings now configurable per provider:
- send_oidc_logout
- enable_refresh_token_use
- server_cert
- set_groups_from_attributes
- user_groups
- scopes
- roles_source
- roles_path
- user_matching_source
- auto_create_atom_user
  • Loading branch information
sbreker committed Jul 17, 2024
1 parent bd0952d commit 7fb40d2
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<li><?php echo link_to(__('Delete'), [$resource, 'module' => 'user', 'action' => 'delete'], ['class' => 'btn atom-btn-outline-danger']); ?></li>
<?php } ?>

<?php if (false === sfConfig::get('app_oidc_auto_create_atom_user', true)) { ?>
<?php if (false === sfContext::getinstance()->user->getProviderConfigValue('auto_create_atom_user', true)) { ?>
<?php if (QubitAcl::check($resource, 'create')) { ?>
<li><?php echo link_to(__('Add new'), ['module' => 'user', 'action' => 'add'], ['class' => 'btn atom-btn-outline-light']); ?></li>
<?php } ?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<div id="basic-collapse" class="accordion-collapse collapse show" aria-labelledby="basic-heading">
<div class="accordion-body">

<?php if (false === sfConfig::get('app_oidc_auto_create_atom_user', true)) { ?>
<?php if (false === sfContext::getinstance()->user->getProviderConfigValue('auto_create_atom_user', true)) { ?>
<?php echo render_field($form->username); ?>
<?php echo render_field($form->email, null, ['type' => 'email']); ?>
<?php } ?>
Expand Down Expand Up @@ -79,7 +79,7 @@
<li><input class="btn atom-btn-outline-success" type="submit" value="<?php echo __('Save'); ?>"></li>
<?php } else { ?>
<li><?php echo link_to(__('Cancel'), ['module' => 'user', 'action' => 'list'], ['class' => 'btn atom-btn-outline-light', 'role' => 'button']); ?></li>
<?php if (false === sfConfig::get('app_oidc_auto_create_atom_user', true)) { ?>
<?php if (false === sfContext::getinstance()->user->getProviderConfigValue('auto_create_atom_user', true)) { ?>
<li><input class="btn atom-btn-outline-success" type="submit" value="<?php echo __('Create'); ?>"></li>
<?php } ?>
<?php } ?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@

<?php echo get_partial('default/pager', ['pager' => $pager]); ?>

<?php if (false === sfConfig::get('app_oidc_auto_create_atom_user', true)) { ?>
<?php if (false === sfContext::getinstance()->user->getProviderConfigValue('auto_create_atom_user', true)) { ?>
<section class="actions mb-3">
<?php echo link_to(__('Add new'), ['module' => 'user', 'action' => 'add'], ['class' => 'btn atom-btn-outline-light']); ?>
</section>
Expand Down
187 changes: 108 additions & 79 deletions plugins/arOidcPlugin/config/app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,118 @@ all:
client_id: 'artefactual-atom'
client_secret: 'example-secret'

# Set to true if OIDC endpoint supports logout.
# Setting examples for tested OpenID providers:
# --------
# Keycloak via Dex:
# send_oidc_logout: false
# Keycloak direct:
# send_oidc_logout: true
send_oidc_logout: true

# Set to true if OIDC endpoint is configured to send refresh tokens.
enable_refresh_token_use: true

# OIDC server SSL certificate location for server validation.
# Accepts a filepath or false (to disable, e.g. for development).
# Examples
# --------
# Relative path to sf_root_dir: 'data/oidc/cert/mycert.pem'
# Absolute path: '/usr/var/certif/xxx.pem'
# Disable server validation: false
server_cert: false

# Settings for parsing OIDC groups into AtoM group membership.
# Set set_groups_from_attributes to true to enable.
set_groups_from_attributes: true
user_groups:
administrator:
attribute_value: 'atom-admin'
group_id: 100
editor:
attribute_value: 'atom-editor'
group_id: 101
contributor:
attribute_value: 'atom-contributor'
group_id: 102
translator:
attribute_value: 'atom-translator'
group_id: 103

scopes:
- 'openid'
# Use with Dex
# - 'offline_access'
- 'profile'
- 'email'
# Use with Dex
# - 'groups'

# Identify token which contains role claims. Options are 'access-token',
# 'id-token', 'verified-claims', or 'user-info'.
# 'set_groups_from_attributes' must be 'true' to enable.
roles_source: 'access-token'

# Identify the location of role claims within the token identified in
# `roles_source` above. This is an array containing the node path to
# locate the roles array in the OIDC token. By default this is found
# in Keycloak's access token under 'realm_access'/'roles'.
roles_path:
- 'realm_access'
- 'roles'

# Identify how IAM users are matched to users in AtoM. Two values are allowed:
# user_matching_source: oidc-email
# user_matching_source: oidc-username
# Using oidc-username will work without additional scopes being requested.
#
# Using oidc-email requires the 'email' scope to be set above in the
# 'scopes' setting. 'email' is an optional user setup field in Keycloak but
# MUST be set if matching to pre-existing AtoM user accounts is going to work.
user_matching_source: 'oidc-email'

# Activate or disable the automatic creation of AtoM user records from OIDC
# endpoint details. Allowed settings are:
#
# true (default): AtoM will automatically create a user record on first login.
#
# false: AtoM will not automatically create a user record on first login - AtoM
# user must be created in advance to successfully authenticate in AtoM.
auto_create_atom_user: true

# The following is an example secondary provider called 'sample_provider'. If
# uncommented, a second OIDC provider in the 'sample' Keycloak realm will be available.
#sample_provider:
#url: 'https://keycloak:8443/realms/sample'
#client_id: 'sample-atom'
#client_secret: 'example-secret'
#send_oidc_logout: true
#enable_refresh_token_use: true
#server_cert: false
#set_groups_from_attributes: true
#user_groups:
# administrator:
# attribute_value: 'atom-admin'
# group_id: 100
# editor:
# attribute_value: 'atom-editor'
# group_id: 101
# contributor:
# attribute_value: 'atom-contributor'
# group_id: 102
# translator:
# attribute_value: 'atom-translator'
# group_id: 103
#scopes:
# - 'openid'
# - 'profile'
# - 'email'
#roles_source: 'access-token'
#roles_path:
# - 'realm_access'
# - 'roles'
#user_matching_source: 'oidc-email'
#auto_create_atom_user: true

# Identifies the primary OIDC provider and corresponds to an entry in 'providers' above.
# The default provider name is 'primary'. If this setting is not defined, AtoM will default
Expand All @@ -46,89 +154,10 @@ all:
# NOTE: Always configure using SSL in production.
redirect_url: 'http://127.0.0.1:63001/index.php/oidc/login'

# Set to true if OIDC endpoint supports logout.
# Setting examples for tested OpenID providers:
# --------
# Keycloak via Dex:
# send_oidc_logout: false
# Keycloak direct:
# send_oidc_logout: true
send_oidc_logout: true

# OIDC logout requires a URL to redirect to. Use this setting to
# specify a page to redirect the user to on logout when
# 'send_oidc_logout' is 'true'. Localhost port 63001 (127.0.0.1:63001)
# is used as a placeholder and should be replaced with your AtoM site's
# public IP and port.
# NOTE: Always configure using SSL in production.
logout_redirect_url: 'http://127.0.0.1:63001'

# Set to true if OIDC endpoint is configured to send refresh tokens.
enable_refresh_token_use: true

# OIDC server SSL certificate location for server validation.
# Accepts a filepath or false (to disable, e.g. for development).
# Examples
# --------
# Relative path to sf_root_dir: 'data/oidc/cert/mycert.pem'
# Absolute path: '/usr/var/certif/xxx.pem'
# Disable server validation: false
server_cert: false

scopes:
- 'openid'
# Use with Dex
# - 'offline_access'
- 'profile'
- 'email'
# Use with Dex
# - 'groups'

# Settings for parsing OIDC groups into AtoM group membership.
# Set set_groups_from_attributes to true to enable.
set_groups_from_attributes: true
user_groups:
administrator:
attribute_value: 'atom-admin'
group_id: 100
editor:
attribute_value: 'atom-editor'
group_id: 101
contributor:
attribute_value: 'atom-contributor'
group_id: 102
translator:
attribute_value: 'atom-translator'
group_id: 103

# Identify token which contains role claims. Options are 'access-token',
# 'id-token', 'verified-claims', or 'user-info'.
# 'set_groups_from_attributes' must be 'true' to enable.
roles_source: 'access-token'

# Identify the location of role claims within the token identified in
# `roles_source` above. This is an array containing the node path to
# locate the roles array in the OIDC token. By default this is found
# in Keycloak's access token under 'realm_access'/'roles'.
roles_path:
- 'realm_access'
- 'roles'

# Identify how IAM users are matched to users in AtoM. Two values are allowed:
# user_matching_source: oidc-email
# user_matching_source: oidc-username
# Using oidc-username will work without additional scopes being requested.
#
# Using oidc-email requires the 'email' scope to be set above in the
# 'scopes' setting. 'email' is an optional user setup field in Keycloak but
# MUST be set if matching to pre-existing AtoM user accounts is going to work.
user_matching_source: 'oidc-email'

# Activate or disable the automatic creation of AtoM user records from OIDC
# endpoint details. Allowed settings are:
#
# true (default): AtoM will automatically create a user record on first login.
#
# false: AtoM will not automatically create a user record on first login - AtoM
# user must be created in advance to successfully authenticate in AtoM.
auto_create_atom_user: true
24 changes: 0 additions & 24 deletions plugins/arOidcPlugin/lib/arOidc.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,13 @@ public static function getOidcInstance()

$oidc = new OpenIDConnectClient();

// Validate requested scopes.
$scopesArray = sfConfig::get('app_oidc_scopes', []);
$validScopes = self::validateScopes($scopesArray);
// Add scopes only if the array is not empty
if (!empty($validScopes)) {
$oidc->addScope($validScopes);
} else {
throw new Exception('No valid scopes found in app_oidc_scopes.');
}

// Validate redirect URL.
$redirectUrl = sfConfig::get('app_oidc_redirect_url', '');
if (empty($redirectUrl)) {
throw new Exception('Invalid OIDC redirect URL. Please review the app_oidc_redirect_url parameter in plugin app.yml.');
}
$oidc->setRedirectURL($redirectUrl);

// Validate the server SSL certificate according to configuration.
$certPath = sfConfig::get('app_oidc_server_cert', false);
if (0 === !strpos($certPath, '/')) {
$certPath = sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.$certPath;
}

if (file_exists($certPath)) {
$oidc->setCertPath($certPath);
} elseif (false === $certPath) {
// OIDC server SSL certificate disabled.
} else {
throw new Exception('Invalid SSL certificate settings. Please review the app_oidc_server_cert parameter in plugin app.yml.');
}

self::$oidcIsInitialized = true;

return $oidc;
Expand Down
Loading

0 comments on commit 7fb40d2

Please sign in to comment.