mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-24 04:57:00 +01:00
283 lines
19 KiB
HTML
283 lines
19 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 content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
<meta name="description" content="">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
<link rel="icon" href="favicon.svg">
|
|
<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>
|
|
<!-- Provide site root to javascript -->
|
|
<script type="text/javascript">
|
|
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 type="text/javascript">
|
|
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 type="text/javascript">
|
|
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 type="text/javascript">
|
|
var html = document.querySelector('html');
|
|
var sidebar = 'hidden';
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
}
|
|
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="server_configuration.html"><strong aria-hidden="true">2.1.</strong> Server Configuration</a></li><li class="chapter-item expanded "><a href="security_hardening.html"><strong aria-hidden="true">2.2.</strong> Security Hardening</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 "><a href="accounts_and_groups.html"><strong aria-hidden="true">4.</strong> Accounts and Groups</a></li><li class="chapter-item expanded "><a href="administrivia.html"><strong aria-hidden="true">5.</strong> Administrative Tasks</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="monitoring.html"><strong aria-hidden="true">5.1.</strong> Monitoring the platform</a></li><li class="chapter-item expanded "><a href="password_quality.html"><strong aria-hidden="true">5.2.</strong> Password Quality and Badlisting</a></li><li class="chapter-item expanded "><a href="posix_accounts.html"><strong aria-hidden="true">5.3.</strong> POSIX Accounts and Groups</a></li><li class="chapter-item expanded "><a href="ssh_key_dist.html"><strong aria-hidden="true">5.4.</strong> SSH Key Distribution</a></li><li class="chapter-item expanded "><a href="recycle_bin.html"><strong aria-hidden="true">5.5.</strong> The Recycle Bin</a></li></ol></li><li class="chapter-item expanded "><a href="oauth2.html" class="active"><strong aria-hidden="true">6.</strong> Oauth2</a></li><li class="chapter-item expanded "><a href="pam_and_nsswitch.html"><strong aria-hidden="true">7.</strong> PAM and nsswitch</a></li><li class="chapter-item expanded "><a href="radius.html"><strong aria-hidden="true">8.</strong> RADIUS</a></li><li class="chapter-item expanded "><a href="ldap.html"><strong aria-hidden="true">9.</strong> LDAP</a></li><li class="chapter-item expanded "><a href="why_tls.html"><strong aria-hidden="true">10.</strong> Why TLS?</a></li><li class="chapter-item expanded "><a href="DEVELOPER_README.html"><strong aria-hidden="true">11.</strong> Developer Guide</a></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 (default)</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>
|
|
</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 type="text/javascript">
|
|
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 "single sign on". It's key to note
|
|
oauth is authorisation, not authentication, as the protocol in it's default forms
|
|
do not provide identity or authentication information, only 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 users 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 refered to as "claims". 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 it's 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 "needs protecting" 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 rfc7662 token introspection or does it rely on openid connect for identity information?
|
|
Does the resource server support PKCE S256 or not?</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>
|
|
</ul>
|
|
<p>Kanidm will expose it's oauth2 apis at the urls:</p>
|
|
<ul>
|
|
<li>auth url: https://idm.example.com/ui/oauth2</li>
|
|
<li>token url: https://idm.example.com/oauth2/token</li>
|
|
<li>token inspect url: https://idm.example.com/oauth2/inspect</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 "admin" scope from kanidm for authorisation. But when
|
|
a user wants to login, it may only request "acces" as a scope from kanidm.</p>
|
|
<p>As each resource server may have it's 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 are implicit scopes. These are scopes granted to all accounts that Kanidm holds.</p>
|
|
<p>The second 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 must be available in the final scope set
|
|
that is granted to the account. This final scope set can be built from implicit and mapped
|
|
scopes.</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 "system_admins" or "idm_hp_oauth2_manage_priv" are able to create or
|
|
manage oauth2 resource server integrations.</p>
|
|
<p>You can create a new resource server with:</p>
|
|
<pre><code>kanidm system oauth2 create <name> <displayname> <origin>
|
|
kanidm system oauth2 create nextcloud "Nextcloud Production" https://nextcloud.example.com
|
|
</code></pre>
|
|
<p>If you wish to create implicit scopes you can set these with:</p>
|
|
<pre><code>kanidm system oauth2 set_implicit_scopes <name> [scopes]...
|
|
kanidm system oauth2 set_implicit_scopes nextcloud login read_user
|
|
</code></pre>
|
|
<p>You can create a scope map with:</p>
|
|
<pre><code>kanidm system oauth2 create_scope_map <name> <kanidm_group_name> [scopes]...
|
|
kanidm system oauth2 create_scope_map nextcloud nextcloud_admins admin
|
|
</code></pre>
|
|
<p>Once created you can view the details of the resource server.</p>
|
|
<pre><code>kanidm system oauth2 get nextcloud
|
|
---
|
|
class: oauth2_resource_server
|
|
class: oauth2_resource_server_basic
|
|
class: object
|
|
displayname: Nextcloud Production
|
|
oauth2_rs_basic_secret: <secret>
|
|
oauth2_rs_name: nextcloud
|
|
oauth2_rs_origin: https://nextcloud.example.com
|
|
oauth2_rs_token_key: hidden
|
|
</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 "oauth2_rs_name" from
|
|
kanidm, and the password to be the value shown in "oauth2_rs_basic_secret". 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>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>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
<a rel="prev" href="recycle_bin.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="pam_and_nsswitch.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="recycle_bin.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="pam_and_nsswitch.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 type="text/javascript">
|
|
window.playground_copyable = true;
|
|
</script>
|
|
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
</body>
|
|
</html>
|