kanidm/docs/v1.1.0-alpha/integrations/oauth2.html
2023-03-27 02:04:43 +00:00

486 lines
33 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Oauth2 - Kanidm Administration</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var html = document.querySelector('html');
var sidebar = null;
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="../intro.html"><strong aria-hidden="true">1.</strong> Introduction to Kanidm</a></li><li class="chapter-item expanded "><a href="../installing_the_server.html"><strong aria-hidden="true">2.</strong> Installing the Server</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../choosing_a_domain_name.html"><strong aria-hidden="true">2.1.</strong> Choosing a Domain Name</a></li><li class="chapter-item expanded "><a href="../prepare_the_server.html"><strong aria-hidden="true">2.2.</strong> Preparing for your Deployment</a></li><li class="chapter-item expanded "><a href="../server_configuration.html"><strong aria-hidden="true">2.3.</strong> Server Configuration and Install</a></li><li class="chapter-item expanded "><a href="../security_hardening.html"><strong aria-hidden="true">2.4.</strong> Platform Security Hardening</a></li><li class="chapter-item expanded "><a href="../server_update.html"><strong aria-hidden="true">2.5.</strong> Server Updates</a></li></ol></li><li class="chapter-item expanded "><a href="../client_tools.html"><strong aria-hidden="true">3.</strong> Client Tools</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../installing_client_tools.html"><strong aria-hidden="true">3.1.</strong> Installing client tools</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">Administration</li><li class="chapter-item expanded "><a href="../administrivia.html"><strong aria-hidden="true">4.</strong> Administration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../accounts_and_groups.html"><strong aria-hidden="true">4.1.</strong> Accounts and Groups</a></li><li class="chapter-item expanded "><a href="../authentication.html"><strong aria-hidden="true">4.2.</strong> Authentication and Credentials</a></li><li class="chapter-item expanded "><a href="../posix_accounts.html"><strong aria-hidden="true">4.3.</strong> POSIX Accounts and Groups</a></li><li class="chapter-item expanded "><a href="../backup_restore.html"><strong aria-hidden="true">4.4.</strong> Backup and Restore</a></li><li class="chapter-item expanded "><a href="../database_maint.html"><strong aria-hidden="true">4.5.</strong> Database Maintenance</a></li><li class="chapter-item expanded "><a href="../domain_rename.html"><strong aria-hidden="true">4.6.</strong> Domain Rename</a></li><li class="chapter-item expanded "><a href="../monitoring.html"><strong aria-hidden="true">4.7.</strong> Monitoring the platform</a></li><li class="chapter-item expanded "><a href="../password_quality.html"><strong aria-hidden="true">4.8.</strong> Password Quality and Badlisting</a></li><li class="chapter-item expanded "><a href="../recycle_bin.html"><strong aria-hidden="true">4.9.</strong> The Recycle Bin</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">Services</li><li class="chapter-item expanded "><a href="../integrations/pam_and_nsswitch.html"><strong aria-hidden="true">5.</strong> PAM and nsswitch</a></li><li class="chapter-item expanded "><a href="../ssh_key_dist.html"><strong aria-hidden="true">6.</strong> SSH Key Distribution</a></li><li class="chapter-item expanded "><a href="../integrations/oauth2.html" class="active"><strong aria-hidden="true">7.</strong> Oauth2</a></li><li class="chapter-item expanded "><a href="../integrations/ldap.html"><strong aria-hidden="true">8.</strong> LDAP</a></li><li class="chapter-item expanded "><a href="../integrations/radius.html"><strong aria-hidden="true">9.</strong> RADIUS</a></li><li class="chapter-item expanded affix "><li class="part-title">Synchronisation</li><li class="chapter-item expanded "><a href="../sync/concepts.html"><strong aria-hidden="true">10.</strong> Concepts</a></li><li class="chapter-item expanded "><a href="../sync/freeipa.html"><strong aria-hidden="true">11.</strong> FreeIPA</a></li><li class="chapter-item expanded affix "><li class="part-title">Integration Examples</li><li class="chapter-item expanded "><a href="../examples/k8s_ingress_example.html"><strong aria-hidden="true">12.</strong> Kubernetes Ingress</a></li><li class="chapter-item expanded "><a href="../integrations/traefik.html"><strong aria-hidden="true">13.</strong> Traefik</a></li><li class="chapter-item expanded affix "><li class="part-title">Support</li><li class="chapter-item expanded "><a href="../troubleshooting.html"><strong aria-hidden="true">14.</strong> Troubleshooting</a></li><li class="chapter-item expanded "><a href="../frequently_asked_questions.html"><strong aria-hidden="true">15.</strong> Frequently Asked Questions</a></li><li class="chapter-item expanded "><a href="../glossary.html"><strong aria-hidden="true">16.</strong> Glossary of Technical Terms</a></li><li class="chapter-item expanded affix "><li class="part-title">For Developers</li><li class="chapter-item expanded "><a href="../DEVELOPER_README.html"><strong aria-hidden="true">17.</strong> Developer Guide</a></li><li class="chapter-item expanded "><a href="../developers/faq.html"><strong aria-hidden="true">18.</strong> FAQ</a></li><li class="chapter-item expanded "><div><strong aria-hidden="true">19.</strong> Design Documents</div></li><li><ol class="section"><li class="chapter-item expanded "><a href="../developers/designs/access_profiles_rework_2022.html"><strong aria-hidden="true">19.1.</strong> Access Profiles 2022</a></li><li class="chapter-item expanded "><a href="../developers/designs/access_profiles_and_security.html"><strong aria-hidden="true">19.2.</strong> Access Profiles Original</a></li><li class="chapter-item expanded "><a href="../developers/designs/rest_interface.html"><strong aria-hidden="true">19.3.</strong> REST Interface</a></li><li class="chapter-item expanded "><a href="../developers/designs/elevated_priv_mode.html"><strong aria-hidden="true">19.4.</strong> Elevated Priv Mode</a></li></ol></li><li class="chapter-item expanded "><a href="../developers/python.html"><strong aria-hidden="true">20.</strong> Python Module</a></li><li class="chapter-item expanded "><a href="../developers/radius.html"><strong aria-hidden="true">21.</strong> RADIUS Integration</a></li><li class="chapter-item expanded "><a href="../packaging.html"><strong aria-hidden="true">22.</strong> Packaging</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../packaging_debs.html"><strong aria-hidden="true">22.1.</strong> Debian/Ubuntu</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Kanidm Administration</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/kanidm/kanidm" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/kanidm/kanidm/edit/master/book/src/integrations/oauth2.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="oauth2"><a class="header" href="#oauth2">OAuth2</a></h1>
<p>OAuth is a web authorisation protocol that allows &quot;single sign on&quot;. It's key to note OAuth only
provides authorisation, as the protocol in its default forms do not provide identity or
authentication information. All that Oauth2 provides is information that an entity is authorised for
the requested resources.</p>
<p>OAuth can tie into extensions allowing an identity provider to reveal information about authorised
sessions. This extends OAuth from an authorisation only system to a system capable of identity and
authorisation. Two primary methods of this exist today: RFC7662 token introspection, and OpenID
connect.</p>
<h2 id="how-does-oauth2-work"><a class="header" href="#how-does-oauth2-work">How Does OAuth2 Work?</a></h2>
<p>A user wishes to access a service (resource, resource server). The resource server does not have an
active session for the client, so it redirects to the authorisation server (Kanidm) to determine if
the client should be allowed to proceed, and has the appropriate permissions (scopes) for the
requested resources.</p>
<p>The authorisation server checks the current session of the user and may present a login flow if
required. Given the identity of the user known to the authorisation sever, and the requested scopes,
the authorisation server makes a decision if it allows the authorisation to proceed. The user is
then prompted to consent to the authorisation from the authorisation server to the resource server
as some identity information may be revealed by granting this consent.</p>
<p>If successful and consent given, the user is redirected back to the resource server with an
authorisation code. The resource server then contacts the authorisation server directly with this
code and exchanges it for a valid token that may be provided to the user's browser.</p>
<p>The resource server may then optionally contact the token introspection endpoint of the
authorisation server about the provided OAuth token, which yields extra metadata about the identity
that holds the token from the authorisation. This metadata may include identity information, but
also may include extended metadata, sometimes referred to as &quot;claims&quot;. Claims are information bound
to a token based on properties of the session that may allow the resource server to make extended
authorisation decisions without the need to contact the authorisation server to arbitrate.</p>
<p>It's important to note that OAuth2 at its core is an authorisation system which has layered
identity-providing elements on top.</p>
<h3 id="resource-server"><a class="header" href="#resource-server">Resource Server</a></h3>
<p>This is the server that a user wants to access. Common examples could be Nextcloud, a wiki, or
something else. This is the system that &quot;needs protecting&quot; and wants to delegate authorisation
decisions to Kanidm.</p>
<p>It's important for you to know <em>how</em> your resource server supports OAuth2. For example, does it
support RFC 7662 token introspection or does it rely on OpenID connect for identity information?
Does the resource server support PKCE S256?</p>
<p>In general Kanidm requires that your resource server supports:</p>
<ul>
<li>HTTP basic authentication to the authorisation server</li>
<li>PKCE S256 code verification to prevent certain token attack classes</li>
<li>OIDC only - JWT ES256 for token signatures</li>
</ul>
<p>Kanidm will expose its OAuth2 APIs at the following URLs:</p>
<ul>
<li>user auth url: <code>https://idm.example.com/ui/oauth2</code></li>
<li>api auth url: <code>https://idm.example.com/oauth2/authorise</code></li>
<li>token url: <code>https://idm.example.com/oauth2/token</code></li>
<li>rfc7662 token introspection url: <code>https://idm.example.com/oauth2/token/introspect</code></li>
<li>rfc7009 token revoke url: <code>https://idm.example.com/oauth2/token/revoke</code></li>
</ul>
<p>OpenID Connect discovery - you need to substitute your OAuth2 client id in the following urls:</p>
<ul>
<li>OpenID connect issuer uri: <code>https://idm.example.com/oauth2/openid/:client\_id:/</code></li>
<li>OpenID connect discovery:
<code>https://idm.example.com/oauth2/openid/:client\_id:/.well-known/openid-configuration</code></li>
</ul>
<p>For manual OpenID configuration:</p>
<ul>
<li>OpenID connect userinfo: <code>https://idm.example.com/oauth2/openid/:client\_id:/userinfo</code></li>
<li>token signing public key: <code>https://idm.example.com/oauth2/openid/:client\_id:/public\_key.jwk</code></li>
</ul>
<h3 id="scope-relationships"><a class="header" href="#scope-relationships">Scope Relationships</a></h3>
<p>For an authorisation to proceed, the resource server will request a list of scopes, which are unique
to that resource server. For example, when a user wishes to login to the admin panel of the resource
server, it may request the &quot;admin&quot; scope from Kanidm for authorisation. But when a user wants to
login, it may only request &quot;access&quot; as a scope from Kanidm.</p>
<p>As each resource server may have its own scopes and understanding of these, Kanidm isolates scopes
to each resource server connected to Kanidm. Kanidm has two methods of granting scopes to accounts
(users).</p>
<p>The first is scope mappings. These provide a set of scopes if a user is a member of a specific group
within Kanidm. This allows you to create a relationship between the scopes of a resource server, and
the groups/roles in Kanidm which can be specific to that resource server.</p>
<p>For an authorisation to proceed, all scopes requested by the resource server must be available in
the final scope set that is granted to the account.</p>
<p>The second is supplemental scope mappings. These function the same as scope maps where membership of
a group provides a set of scopes to the account. However these scopes are NOT consulted during
authorisation decisions made by Kanidm. These scopes exists to allow optional properties to be
provided (such as personal information about a subset of accounts to be revealed) or so that the
resource server may make it's own authorisation decisions based on the provided scopes.</p>
<p>This use of scopes is the primary means to control who can access what resources. These access
decisions can take place either on Kanidm or the resource server.</p>
<p>For example, if you have a resource server that always requests a scope of &quot;read&quot;, then users with
scope maps that supply the read scope will be allowed by Kanidm to proceed to the resource server.
Kanidm can then provide the supplementary scopes into provided tokens, so that the resource server
can use these to choose if it wishes to display UI elements. If a user has a supplemental &quot;admin&quot;
scope, then that user may be able to access an administration panel of the resource server. In this
way Kanidm is still providing the authorisation information, but the control is then exercised by
the resource server.</p>
<h2 id="configuration"><a class="header" href="#configuration">Configuration</a></h2>
<h3 id="create-the-kanidm-configuration"><a class="header" href="#create-the-kanidm-configuration">Create the Kanidm Configuration</a></h3>
<p>After you have understood your resource server requirements you first need to configure Kanidm. By
default members of &quot;system_admins&quot; or &quot;idm_hp_oauth2_manage_priv&quot; are able to create or manage
OAuth2 resource server integrations.</p>
<p>You can create a new resource server with:</p>
<pre><code class="language-bash">kanidm system oauth2 create &lt;name&gt; &lt;displayname&gt; &lt;origin&gt;
kanidm system oauth2 create nextcloud &quot;Nextcloud Production&quot; https://nextcloud.example.com
</code></pre>
<p>You can create a scope map with:</p>
<pre><code class="language-bash">kanidm system oauth2 update-scope-map &lt;name&gt; &lt;kanidm_group_name&gt; [scopes]...
kanidm system oauth2 update-scope-map nextcloud nextcloud_admins admin
</code></pre>
<!-- deno-fmt-ignore-start -->
<table>
<tr>
<td rowspan=2><img src="../images/kani-warning.png" alt="Kani Warning" /></td>
<td><strong>WARNING</strong></td>
</tr>
<tr>
<td>If you are creating an OpenID Connect (OIDC) resource server you <b>MUST</b> provide a scope map named <code>openid</code>. Without this, OpenID clients <b>WILL NOT WORK</b>!</td>
</tr>
</table>
<!-- deno-fmt-ignore-end -->
<blockquote>
<p><strong>HINT</strong> OpenID connect allows a number of scopes that affect the content of the resulting
authorisation token. If one of the following scopes are requested by the OpenID client, then the
associated claims may be added to the authorisation token. It is not guaranteed that all of the
associated claims will be added.</p>
<ul>
<li>profile - (name, family_name, given_name, middle_name, nickname, preferred_username,
profile, picture, website, gender, birthdate, zoneinfo, locale, and updated_at)</li>
<li>email - (email, email_verified)</li>
<li>address - (address)</li>
<li>phone - (phone_number, phone_number_verified)</li>
</ul>
</blockquote>
<p>You can create a supplemental scope map with:</p>
<pre><code class="language-bash">kanidm system oauth2 update-sup-scope-map &lt;name&gt; &lt;kanidm_group_name&gt; [scopes]...
kanidm system oauth2 update-sup-scope-map nextcloud nextcloud_admins admin
</code></pre>
<p>Once created you can view the details of the resource server.</p>
<pre><code class="language-bash">kanidm system oauth2 get nextcloud
---
class: oauth2_resource_server
class: oauth2_resource_server_basic
class: object
displayname: Nextcloud Production
oauth2_rs_basic_secret: hidden
oauth2_rs_name: nextcloud
oauth2_rs_origin: https://nextcloud.example.com
oauth2_rs_token_key: hidden
</code></pre>
<p>You can see &quot;oauth2_rs_basic_secret&quot; with:</p>
<pre><code class="language-bash">kanidm system oauth2 show-basic-secret nextcloud
---
&lt;secret&gt;
</code></pre>
<h3 id="configure-the-resource-server"><a class="header" href="#configure-the-resource-server">Configure the Resource Server</a></h3>
<p>On your resource server, you should configure the client ID as the &quot;oauth2_rs_name&quot; from Kanidm,
and the password to be the value shown in &quot;oauth2_rs_basic_secret&quot;. Ensure that the code
challenge/verification method is set to S256.</p>
<p>You should now be able to test authorisation.</p>
<h2 id="resetting-resource-server-security-material"><a class="header" href="#resetting-resource-server-security-material">Resetting Resource Server Security Material</a></h2>
<p>In the case of disclosure of the basic secret, or some other security event where you may wish to
invalidate a resource servers active sessions/tokens, you can reset the secret material of the
server with:</p>
<pre><code class="language-bash">kanidm system oauth2 reset-secrets
</code></pre>
<p>Each resource server has unique signing keys and access secrets, so this is limited to each resource
server.</p>
<h2 id="extended-options-for-legacy-clients"><a class="header" href="#extended-options-for-legacy-clients">Extended Options for Legacy Clients</a></h2>
<p>Not all resource servers support modern standards like PKCE or ECDSA. In these situations it may be
necessary to disable these on a per-resource server basis. Disabling these on one resource server
will not affect others.</p>
<!-- deno-fmt-ignore-start -->
<table>
<tr>
<td rowspan=2><img src="../images/kani-warning.png" alt="Kani Warning" /></td>
<td><strong>WARNING text=Changing these settings MAY have serious consequences on the security of your resource server. You should avoid changing these if at all possible!</strong></td>
</tr>
<tr>
<td></td>
</tr>
</table>
<!-- deno-fmt-ignore-end -->
<p>To disable PKCE for a resource server:</p>
<pre><code class="language-bash">kanidm system oauth2 warning-insecure-client-disable-pkce &lt;resource server name&gt;
</code></pre>
<p>To enable legacy cryptograhy (RSA PKCS1-5 SHA256):</p>
<pre><code class="language-bash">kanidm system oauth2 warning-enable-legacy-crypto &lt;resource server name&gt;
</code></pre>
<h2 id="example-integrations"><a class="header" href="#example-integrations">Example Integrations</a></h2>
<h3 id="apache-mod_auth_openidc"><a class="header" href="#apache-mod_auth_openidc">Apache mod_auth_openidc</a></h3>
<p>Add the following to a <code>mod_auth_openidc.conf</code>. It should be included in a <code>mods_enabled</code> folder or
with an appropriate include.</p>
<pre><code class="language-conf">OIDCRedirectURI /protected/redirect_uri
OIDCCryptoPassphrase &lt;random password here&gt;
OIDCProviderMetadataURL https://kanidm.example.com/oauth2/openid/&lt;resource server name&gt;/.well-known/openid-configuration
OIDCScope &quot;openid&quot;
OIDCUserInfoTokenMethod authz_header
OIDCClientID &lt;resource server name&gt;
OIDCClientSecret &lt;resource server password&gt;
OIDCPKCEMethod S256
OIDCCookieSameSite On
# Set the `REMOTE_USER` field to the `preferred_username` instead of the UUID.
# Remember that the username can change, but this can help with systems like Nagios which use this as a display name.
# OIDCRemoteUserClaim preferred_username
</code></pre>
<p>Other scopes can be added as required to the <code>OIDCScope</code> line, eg:
<code>OIDCScope &quot;openid scope2 scope3&quot;</code></p>
<p>In the virtual host, to protect a location:</p>
<pre><code class="language-apache">&lt;Location /&gt;
AuthType openid-connect
Require valid-user
&lt;/Location&gt;
</code></pre>
<h3 id="nextcloud"><a class="header" href="#nextcloud">Nextcloud</a></h3>
<p>Install the module <a href="https://apps.nextcloud.com/apps/user_oidc">from the nextcloud market place</a> - it
can also be found in the Apps section of your deployment as &quot;OpenID Connect user backend&quot;.</p>
<p>In Nextcloud's config.php you need to allow connection to remote servers:</p>
<pre><code class="language-php">'allow_local_remote_servers' =&gt; true,
</code></pre>
<p>You may optionally choose to add:</p>
<pre><code class="language-php">'allow_user_to_change_display_name' =&gt; false,
'lost_password_link' =&gt; 'disabled',
</code></pre>
<p>If you forget this, you may see the following error in logs:</p>
<pre><code class="language-bash">Host 172.24.11.129 was not connected to because it violates local access rules
</code></pre>
<p>This module does not support PKCE or ES256. You will need to run:</p>
<pre><code class="language-bash">kanidm system oauth2 warning_insecure_client_disable_pkce &lt;resource server name&gt;
kanidm system oauth2 warning_enable_legacy_crypto &lt;resource server name&gt;
</code></pre>
<p>In the settings menu, configure the discovery URL and client ID and secret.</p>
<p>You can choose to disable other login methods with:</p>
<pre><code class="language-bash">php occ config:app:set --value=0 user_oidc allow_multiple_user_backends
</code></pre>
<p>You can login directly by appending <code>?direct=1</code> to your login page. You can re-enable other backends
by setting the value to <code>1</code></p>
<h3 id="velociraptor"><a class="header" href="#velociraptor">Velociraptor</a></h3>
<p>Velociraptor supports OIDC. To configure it select &quot;Authenticate with SSO&quot; then &quot;OIDC&quot; during the
interactive configuration generator. Alternately, you can set the following keys in
server.config.yaml:</p>
<pre><code class="language-yaml">GUI:
authenticator:
type: OIDC
oidc_issuer: https://idm.example.com/oauth2/openid/:client\_id:/
oauth_client_id: &lt;resource server name/&gt;
oauth_client_secret: &lt;resource server secret&gt;
</code></pre>
<p>Velociraptor does not support PKCE. You will need to run the following:</p>
<pre><code class="language-bash">kanidm system oauth2 warning_insecure_client_disable_pkce &lt;resource server name&gt;
</code></pre>
<p>Initial users are mapped via their email in the Velociraptor server.config.yaml config:</p>
<pre><code class="language-yaml">GUI:
initial_users:
- name: &lt;email address&gt;
</code></pre>
<p>Accounts require the <code>openid</code> and <code>email</code> scopes to be authenticated. It is recommended you limit
these to a group with a scope map due to Velociraptors high impact.</p>
<pre><code class="language-bash"># kanidm group create velociraptor_users
# kanidm group add_members velociraptor_users ...
kanidm system oauth2 create_scope_map &lt;resource server name&gt; velociraptor_users openid email
</code></pre>
<h3 id="vouch-proxy"><a class="header" href="#vouch-proxy">Vouch Proxy</a></h3>
<blockquote>
<p><strong>WARNING</strong> Vouch proxy requires a unique identifier but does not use the proper scope, &quot;sub&quot;. It
uses the fields &quot;username&quot; or &quot;email&quot; as primary identifiers instead. As a result, this can cause
user or deployment issues, at worst security bypasses. You should avoid Vouch Proxy if possible
due to these issues.</p>
<ul>
<li><a href="https://github.com/vouch/vouch-proxy/issues/309">https://github.com/vouch/vouch-proxy/issues/309</a></li>
<li><a href="https://github.com/vouch/vouch-proxy/issues/310">https://github.com/vouch/vouch-proxy/issues/310</a></li>
</ul>
</blockquote>
<p>Note: <strong>You need to run at least the version 0.37.0</strong></p>
<p>Vouch Proxy supports multiple OAuth and OIDC login providers. To configure it you need to pass:</p>
<pre><code class="language-yaml">oauth:
auth_url: https://idm.wherekanidmruns.com/ui/oauth2
callback_url: https://login.wherevouchproxyruns.com/auth
client_id: &lt;oauth2_rs_name&gt; # Found in kanidm system oauth2 get XXXX (should be the same as XXXX)
client_secret: &lt;oauth2_rs_basic_secret&gt; # Found in kanidm system oauth2 get XXXX
code_challenge_method: S256
provider: oidc
scopes:
- email # Required due to vouch proxy reliance on mail as a primary identifier
token_url: https://idm.wherekanidmruns.com/oauth2/token
user_info_url: https://idm.wherekanidmruns.com/oauth2/openid/&lt;oauth2_rs_name&gt;/userinfo
</code></pre>
<p>The <code>email</code> scope needs to be passed and thus the mail attribute needs to exist on the account:</p>
<pre><code class="language-bash">kanidm person update &lt;ID&gt; --mail &quot;YYYY@somedomain.com&quot; --name idm_admin
</code></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../ssh_key_dist.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../integrations/ldap.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../ssh_key_dist.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../integrations/ldap.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>