<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dex – Documentation</title><link>https://dexidp.io/docs/</link><description>Recent content in Documentation on Dex</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Dex IdP Contributors</copyright><lastBuildDate>Tue, 07 Jan 2020 14:59:38 +0100</lastBuildDate><atom:link href="https://dexidp.io/docs/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs: Getting Started</title><link>https://dexidp.io/docs/getting-started/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/getting-started/</guid><description>
&lt;h2 id="container-image">Container image&lt;a class="heading-anchor" href="#container-image" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex is primarily distributed as a container image, published to the following locations:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/dexidp/dex/pkgs/container/dex">ghcr.io/dexidp/dex&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hub.docker.com/r/dexidp/dex/tags">docker.io/dexidp/dex&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>2 variants (&lt;code>alpine&lt;/code> and &lt;code>distroless&lt;/code>) of container images are provided
based on Alpine Linux and Distroless base images.&lt;/p>
&lt;p>A reference Kubernetes Helm chart for dex can be found at &lt;a href="https://charts.dexidp.io">charts.dexidp.io&lt;/a>.&lt;/p>
&lt;h2 id="building-the-dex-binary">Building the dex binary&lt;a class="heading-anchor" href="#building-the-dex-binary" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>To build dex from source code, install a working Go environment with version 1.19 or greater according to the &lt;a href="https://golang.org/doc/install">official documentation&lt;/a>.
Then clone the repository and use &lt;code>make&lt;/code> to compile the dex binary.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ git clone https://github.com/dexidp/dex.git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#e5c07b">cd&lt;/span> dex/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ make build
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex exclusively pulls configuration options from a config file. Use the &lt;a href="https://github.com/dexidp/dex/blob/master/examples/config-dev.yaml">example config&lt;/a> file found in the &lt;code>examples/&lt;/code> directory to start an instance of dex with a sqlite3 data store, and a set of predefined OAuth2 clients.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./bin/dex serve examples/config-dev.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;a href="https://github.com/dexidp/dex/blob/master/examples/config-dev.yaml">example config&lt;/a> file documents many of the configuration options through inline comments. For extra config options, look at that file.&lt;/p>
&lt;h3 id="templated-configuration">Templated configuration&lt;a class="heading-anchor" href="#templated-configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The default entrypoint for distributed container images utilize &lt;a href="https://github.com/hairyhenderson/gomplate">gomplate&lt;/a>
to pre-process configuration files (&lt;code>.tpl&lt;/code>, &lt;code>.tmpl&lt;/code>, &lt;code>.yaml&lt;/code>) passed as arguments.
This enables templating any field from the environment, for example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">secret&lt;/span>: &lt;span style="color:#98c379">&amp;#34;{{ .Env.MY_SECRET_ENV }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>See &lt;a href="https://docs.gomplate.ca/">gomplate docs&lt;/a> for templating syntax.&lt;/p>
&lt;h2 id="running-a-client">Running a client&lt;a class="heading-anchor" href="#running-a-client" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex operates like most other OAuth2 providers. Users are redirected from a client app to dex to login. Dex ships with an example client app (built with the &lt;code>make examples&lt;/code> command), for testing and demos.&lt;/p>
&lt;p>By default, the example client is configured with the same OAuth2 credentials defined in &lt;code>examples/config-dev.yaml&lt;/code> to talk to dex. Running the example app will cause it to query dex&amp;rsquo;s &lt;a href="https://openid.net/specs/openid-connect-discovery-1_0-17.html#ProviderMetadata">discovery endpoint&lt;/a> and determine the OAuth2 endpoints.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./bin/example-app
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Login to dex through the example app using the following steps.&lt;/p>
&lt;ol>
&lt;li>Navigate to the example app at http://localhost:5555/ in your browser.&lt;/li>
&lt;li>Hit &amp;ldquo;login&amp;rdquo; on the example app to be redirected to dex.&lt;/li>
&lt;li>Choose an option to authenticate:
&lt;ul>
&lt;li>&amp;ldquo;Login with Example&amp;rdquo; to use mocked user data.&lt;/li>
&lt;li>&amp;ldquo;Login with Email&amp;rdquo; to fill the form with static user credentials &lt;code>admin@example.com&lt;/code> and &lt;code>password&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Approve the example app&amp;rsquo;s request.&lt;/li>
&lt;li>See the resulting token the example app claims from dex.&lt;/li>
&lt;/ol>
&lt;h2 id="further-reading">Further reading&lt;a class="heading-anchor" href="#further-reading" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex is generally used as a building block to drive authentication for other apps. See &lt;a href="https://dexidp.io/docs//using-dex/">&lt;em>&amp;ldquo;Writing apps that use Dex&amp;rdquo;&lt;/em>&lt;/a> for an overview of instrumenting apps to work with dex.&lt;/p>
&lt;p>For a primer on using LDAP to back dex&amp;rsquo;s user store, see the OpenLDAP &lt;a href="https://dexidp.io/docs/connectors/ldap/#getting-started">&lt;em>&amp;ldquo;Getting started&amp;rdquo;&lt;/em>&lt;/a> example.&lt;/p>
&lt;p>Check out the Documentation directory for further reading on setting up different storages, interacting with the dex API, intros for OpenID Connect, and logging in through other identity providers such as Google, GitHub, or LDAP.&lt;/p></description></item><item><title>Docs: Tokens</title><link>https://dexidp.io/docs/configuration/tokens/</link><pubDate>Wed, 21 Oct 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/configuration/tokens/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>ID Tokens are an OAuth2 extension introduced by OpenID Connect and Dex&amp;rsquo;s primary feature. ID Tokens are &lt;a href="https://jwt.io/">JSON Web Tokens&lt;/a> (JWTs) signed by Dex and returned as part of the OAuth2 response that attest to the end user&amp;rsquo;s identity. An example JWT might look like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>eyJhbGciOiJSUzI1NiIsImtpZCI6IjlkNDQ3NDFmNzczYjkzOGNmNjVkZDMyNjY4NWI4NjE4MGMzMjRkOTkifQ.eyJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjU1NTYvZGV4Iiwic3ViIjoiQ2djeU16UXlOelE1RWdabmFYUm9kV0kiLCJhdWQiOiJleGFtcGxlLWFwcCIsImV4cCI6MTQ5Mjg4MjA0MiwiaWF0IjoxNDkyNzk1NjQyLCJhdF9oYXNoIjoiYmk5NmdPWFpTaHZsV1l0YWw5RXFpdyIsImVtYWlsIjoiZXJpYy5jaGlhbmdAY29yZW9zLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cHMiOlsiYWRtaW5zIiwiZGV2ZWxvcGVycyJdLCJuYW1lIjoiRXJpYyBDaGlhbmcifQ.OhROPq_0eP-zsQRjg87KZ4wGkjiQGnTi5QuG877AdJDb3R2ZCOk2Vkf5SdP8cPyb3VMqL32G4hLDayniiv8f1_ZXAde0sKrayfQ10XAXFgZl_P1yilkLdknxn6nbhDRVllpWcB12ki9vmAxklAr0B1C4kr5nI3-BZLrFcUR5sQbxwJj4oW1OuG6jJCNGHXGNTBTNEaM28eD-9nhfBeuBTzzO7BKwPsojjj4C9ogU4JQhGvm_l4yfVi0boSx8c0FX3JsiB0yLa1ZdJVWVl9m90XmbWRSD85pNDQHcWZP9hR6CMgbvGkZsgjG32qeRwUL_eNkNowSBNWLrGNPoON1gMg
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>ID Tokens contains standard claims assert which client app logged the user in, when the token expires, and the identity of the user.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;iss&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5556/dex&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;sub&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;CgcyMzQyNzQ5EgZnaXRodWI&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;aud&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;example-app&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;exp&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">1492882042&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;iat&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">1492795642&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;at_hash&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;bi96gOXZShvlWYtal9Eqiw&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;email&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;jane.doe@coreos.com&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;email_verified&amp;#34;&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;groups&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;admins&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;developers&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;Jane Doe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Because these tokens are signed by Dex and &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims">contain standard-based claims&lt;/a> other services can consume them as service-to-service credentials. Systems that can already consume OpenID Connect ID Tokens issued by Dex include:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens">Kubernetes&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html">AWS STS&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>For details on how to request or validate an ID Token, see &lt;a href="https://dexidp.io/docs/guides/using-dex/">“&lt;em>Writing apps that use Dex&lt;/em>.”&lt;/a>&lt;/p>
&lt;h2 id="refresh-tokens">Refresh tokens&lt;a class="heading-anchor" href="#refresh-tokens" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Refresh tokens are credentials used to obtain access tokens. Refresh tokens are issued to the client by the authorization server and are used to obtain
a new id token when the current id token becomes invalid or expires. Issuing a refresh token is optional and is provided by passing &lt;code>offline_access&lt;/code> scope to Dex server.&lt;/p>
&lt;p>&lt;strong>NOTE&lt;/strong>: Some connectors do not support &lt;code>offline_access&lt;/code> scope. You can find out which connectors support refresh tokens by looking into the &lt;a href="https://dexidp.io/docs/connectors/">&lt;em>connectors list&lt;/em>&lt;/a>.&lt;/p>
&lt;p>Example of a server response with refresh token:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;access_token&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;eyJhbGciOiJSUzI1N...&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;token_type&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;Bearer&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;refresh_token&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;lxzzsvasxho5exvwkfa5zhefl&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;expires_in&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">3600&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;id_token&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;eyJhbGciO...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NOTE&lt;/strong>: For every refresh of an id token, Dex issues a new refresh token. This security measure is called &lt;em>refresh token rotation&lt;/em>
and prevents someone stealing it. The idea is described in detail in the corresponding &lt;a href="https://tools.ietf.org/html/rfc6819#section-5.2.2.3">RFC&lt;/a>.&lt;/p>
&lt;h2 id="expiration-and-rotation-settings">Expiration and rotation settings&lt;a class="heading-anchor" href="#expiration-and-rotation-settings" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex has a section in the config file where you can specify expiration and rotation settings for id tokens and refresh tokens.
&lt;strong>NOTE&lt;/strong>: All duration options should be set in the format: number + time unit (s, m, h), e.g., &lt;code>10m&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>&lt;code>expiry&lt;/code> - section for various expiration settings, including token settings:
&lt;ul>
&lt;li>&lt;code>idTokens&lt;/code> - the lifetime of if tokens. It is preferable to use short-lived id tokens, e.g., 10 minutes.&lt;/li>
&lt;li>&lt;code>authRequests&lt;/code> - the time frame in which users can exchange a code for an access or id token.&lt;/li>
&lt;li>&lt;code>deviceRequests&lt;/code> - the time frame in which users can authorize a device to receive an access or id token.&lt;/li>
&lt;li>&lt;code>signingKeys&lt;/code> - the period of time after which the signing keys are rotated. It is recommended to rotate keys regularly. If the &lt;code>idTokens&lt;/code> lifetime exceeds, public parts of signing keys will be kept for validation for the extra time.&lt;/li>
&lt;li>&lt;code>refreshTokens&lt;/code> - section for various refresh token settings:
&lt;ul>
&lt;li>&lt;code>validIfNotUsedFor&lt;/code> - invalidate a refresh token if it is not used for a specified amount of time.&lt;/li>
&lt;li>&lt;code>absoluteLifetime&lt;/code> - a stricter variant of the previous option, absolute lifetime of a refresh token. It forces users to reauthenticate and obtain a new refresh token.&lt;/li>
&lt;li>&lt;code>disableRotation&lt;/code> - completely disables every-request rotation. The user will also have to specify one of the previous refresh token options to keep refresh tokens secure when toggling this.&lt;/li>
&lt;li>&lt;code>reuseInterval&lt;/code> - allows getting the same refresh token from refresh endpoint within a specified interval, but only if the user&amp;rsquo;s request contains the previous refresh token.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>NOTE&lt;/strong>: &lt;code>disableRotation&lt;/code> and &lt;code>reuseInterval&lt;/code> options help effectively deal with network lags, concurrent requests, and so on in tradeoff for security. Use them with caution.&lt;/p>
&lt;h2 id="token-signing-configuration">Token signing configuration&lt;a class="heading-anchor" href="#token-signing-configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex provides flexible token signing options through the &lt;code>signer&lt;/code> configuration section. You can choose between a local signer or integrate with Vault-compatible APIs for centralized key management.&lt;/p>
&lt;h3 id="local-signer">Local signer&lt;a class="heading-anchor" href="#local-signer" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The local signer uses keys managed by Dex&amp;rsquo;s storage backend with automatic rotation. This is the default option for simple deployments.&lt;/p>
&lt;ul>
&lt;li>&lt;code>type&lt;/code> - set to &lt;code>local&lt;/code> to use local signing&lt;/li>
&lt;li>&lt;code>config&lt;/code> - configuration section for local signer:
&lt;ul>
&lt;li>&lt;code>keysRotationPeriod&lt;/code> - (required) the period after which signing keys are rotated (e.g., &lt;code>6h&lt;/code>, &lt;code>24h&lt;/code>)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Supported signing algorithms (not configurable):&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>RS256&lt;/code> (RSA with SHA-256)&lt;/li>
&lt;/ul>
&lt;p>Example configuration:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">signer&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: local
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">keysRotationPeriod&lt;/span>: 6h
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="vault-compatible-signer">Vault-compatible signer&lt;a class="heading-anchor" href="#vault-compatible-signer" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>For enhanced security and centralized key management. This allows you to use HashiCorp Vault or OpenBao for signing operations without storing keys locally.&lt;/p>
&lt;ul>
&lt;li>&lt;code>type&lt;/code> - set to &lt;code>vault&lt;/code> to use Vault-compatible API&lt;/li>
&lt;li>&lt;code>config&lt;/code> - configuration section for Vault signer:
&lt;ul>
&lt;li>&lt;code>keyName&lt;/code> - (required) the key identifier in Vault/OpenBao to use for signing (e.g., &lt;code>dex/signing-key&lt;/code>)&lt;/li>
&lt;li>&lt;code>addr&lt;/code> - Vault/OpenBao server address (optional, can be set via &lt;code>VAULT_ADDR&lt;/code> environment variable)&lt;/li>
&lt;li>&lt;code>token&lt;/code> - authentication token for Vault/OpenBao (optional, can be set via &lt;code>VAULT_TOKEN&lt;/code> environment variable)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Supported signing algorithms:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>RS256&lt;/code> (RSA with SHA-256)&lt;/li>
&lt;li>&lt;code>ES256&lt;/code> (ECDSA with SHA-256)&lt;/li>
&lt;li>&lt;code>ES384&lt;/code> (ECDSA with SHA-384)&lt;/li>
&lt;li>&lt;code>ES512&lt;/code> (ECDSA with SHA-512)&lt;/li>
&lt;li>&lt;code>EdDSA&lt;/code> (Edwards-curve Digital Signature Algorithm)&lt;/li>
&lt;/ul>
&lt;p>The signing algorithm is determined by the key type configured in Vault/OpenBao&amp;rsquo;s Transit backend.&lt;/p>
&lt;div class="alert alert-primary" role="alert">
&lt;h4 class="alert-heading">Note&lt;/h4>
Only the &lt;code>keyName&lt;/code> parameter is required. The &lt;code>addr&lt;/code> and &lt;code>token&lt;/code> can be provided through environment variables, making it easier to manage sensitive credentials without exposing them in configuration files.
&lt;/div>
&lt;p>Example configuration:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">signer&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: vault
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">keyName&lt;/span>: dex/signing-key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">addr&lt;/span>: http://localhost:8200
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">token&lt;/span>: test-token
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Using environment variables:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">signer&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: vault
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">keyName&lt;/span>: dex/signing-key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>With environment variables set:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">VAULT_ADDR&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>https://vault.example.com:8200
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">VAULT_TOKEN&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>your-vault-token
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This approach ensures that signing keys never leave your Vault/OpenBao server, providing better security and auditability of key operations.&lt;/p>
&lt;div class="alert alert-primary" role="alert">
&lt;h4 class="alert-heading">Note&lt;/h4>
&lt;p>Dex supports Vault-compatible APIs through &lt;a href="https://pkg.go.dev/github.com/openbao/openbao/api/v2">OpenBao API v2 integration package&lt;/a>.&lt;/p>
&lt;p>Integration tests for Dex guarantee compatibility with Vault, but it may change in the future.&lt;/p>
&lt;/div></description></item><item><title>Docs: Writing Apps That Use Dex</title><link>https://dexidp.io/docs/guides/using-dex/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/guides/using-dex/</guid><description>
&lt;p>Once you have dex up and running, the next step is to write applications that use dex to drive authentication. Apps that interact with dex generally fall into one of two categories:&lt;/p>
&lt;ol>
&lt;li>Apps that request OpenID Connect ID tokens to authenticate users.
&lt;ul>
&lt;li>Used for authenticating an end user.&lt;/li>
&lt;li>Must be web based.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Apps that consume ID tokens from other apps.
&lt;ul>
&lt;li>Needs to verify that a client is acting on behalf of a user.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>The first category of apps are standard OAuth2 clients. Users show up at a website, and the application wants to authenticate those end users by pulling claims out of the ID token.&lt;/p>
&lt;p>The second category of apps consume ID tokens as credentials. This lets another service handle OAuth2 flows, then use the ID token retrieved from dex to act on the end user&amp;rsquo;s behalf with the app. An example of an app that falls into this category is the &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens">Kubernetes API server&lt;/a>.&lt;/p>
&lt;h2 id="requesting-an-id-token-from-dex">Requesting an ID token from dex&lt;a class="heading-anchor" href="#requesting-an-id-token-from-dex" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Apps that directly use dex to authenticate a user use OAuth2 code flows to request a token response. The exact steps taken are:&lt;/p>
&lt;ul>
&lt;li>User visits client app.&lt;/li>
&lt;li>Client app redirects user to dex with an OAuth2 request.&lt;/li>
&lt;li>Dex determines user&amp;rsquo;s identity.&lt;/li>
&lt;li>Dex redirects user to client with a code.&lt;/li>
&lt;li>Client exchanges code with dex for an id_token.&lt;/li>
&lt;/ul>
&lt;figure class="diagram">
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 220" role="img" aria-label="End-user uses a Client app; the Client app delegates authentication to Dex, which talks to an upstream Identity Provider and returns an id_token back to the Client app.">
&lt;style>
.stroke { fill: none; stroke: var(--text-secondary, #475569); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.box { fill: var(--bg-card, #FFFFFF); stroke: var(--border-strong, #94A3B8); stroke-width: 1.5; }
.box-dex { fill: var(--blue-tint-2, rgba(68,159,216,0.08)); stroke: var(--dex-blue, #449FD8); stroke-width: 1.8; }
.label { fill: var(--text-primary, #0F172A); font-family: var(--font-sans, -apple-system, Helvetica, sans-serif); font-size: 13px; font-weight: 600; text-anchor: middle; }
.label-dex { fill: var(--dex-blue, #449FD8); font-weight: 700; font-size: 15px; letter-spacing: -0.01em; }
.token { fill: var(--dex-red, #F04D5C); font-family: var(--font-mono, Menlo, monospace); font-size: 10px; font-weight: 600; text-anchor: middle; letter-spacing: 0.04em; }
.flow { fill: none; stroke: var(--text-secondary, #475569); stroke-width: 1.5; stroke-linecap: round; }
.flow-back { fill: none; stroke: var(--dex-red, #F04D5C); stroke-width: 1.5; stroke-dasharray: 4 3; stroke-linecap: round; }
.head { fill: var(--text-secondary, #475569); }
.head-back { fill: var(--dex-red, #F04D5C); }
&lt;/style>
&lt;defs>
&lt;marker id="mk" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
&lt;path class="head" d="M 0 0 L 10 5 L 0 10 z"/>
&lt;/marker>
&lt;marker id="mk-back" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
&lt;path class="head-back" d="M 0 0 L 10 5 L 0 10 z"/>
&lt;/marker>
&lt;/defs>
&lt;!-- ═══════ id_token return arrow on TOP ═══════ -->
&lt;path class="flow-back" d="M 260 45 L 260 20 L 100 20 L 100 45" marker-end="url(#mk-back)"/>
&lt;text class="token" x="180" y="14">id_token&lt;/text>
&lt;!-- ═══════ Client app box — typography only ═══════ -->
&lt;rect class="box" x="30" y="45" width="140" height="70" rx="3"/>
&lt;text class="label" x="100" y="86">Client App&lt;/text>
&lt;!-- ═══════ Dex box — the only box that carries an icon (brand glyph) ═══════ -->
&lt;rect class="box-dex" x="190" y="45" width="140" height="70" rx="3"/>
&lt;g transform="translate(247, 52) scale(0.22)">
&lt;path fill="var(--dex-blue, #449FD8)" d="M88.345,51.574c7.588-3.55,12.764-10.49,14.175-18.53C96.396,19.395,84.663,9.054,70.094,4.851
c4.923,7.133,7.272,15.583,6.771,24.17C83.311,34.466,87.716,42.55,88.345,51.574z M27.27,38.542
c-8.207-1.045-16.333,1.973-21.858,8.054C3.23,61.683,7.869,76.84,18.099,88.158c-0.527-8.64,1.856-17.306,6.831-24.483
C22.19,55.048,23.32,45.944,27.27,38.542z M33.01,76.928c-2.997,8.079-1.755,17.193,3.642,24.215
c12.155,4.943,26.051,5.146,38.643-0.035c-7.818-2.516-14.886-7.518-19.887-14.731C47.233,86.23,39.124,83.032,33.01,76.928z
M63.122,22.202C61.615,14.044,56.069,6.819,47.892,3.47C33.778,5.711,20.745,13.966,12.76,26.631
c8.115-2.487,16.74-2.178,24.529,0.639C44.816,22.008,54.043,20.144,63.122,22.202z M85.891,66.457
c-3.086,7.399-8.722,13.188-15.678,16.61c6.194,5.604,14.805,7.758,22.852,5.834c9.054-9.587,13.884-22.198,13.9-35.009
C101.549,60.198,94.131,64.67,85.891,66.457z"/>
&lt;circle fill="var(--dex-red, #F04D5C)" cx="56.035" cy="53.892" r="15.972"/>
&lt;/g>
&lt;text class="label label-dex" x="260" y="98">Dex&lt;/text>
&lt;!-- ═══════ Identity Provider box — typography only ═══════ -->
&lt;rect class="box" x="350" y="45" width="140" height="70" rx="3"/>
&lt;text class="label" x="420" y="86">Upstream IdP&lt;/text>
&lt;!-- ═══════ Forward flow arrows ═══════ -->
&lt;line class="flow" x1="170" y1="80" x2="188" y2="80" marker-end="url(#mk)"/>
&lt;line class="flow" x1="330" y1="80" x2="348" y2="80" marker-end="url(#mk)"/>
&lt;!-- ═══════ End-user stick figure below Client app ═══════ -->
&lt;g transform="translate(80, 144)">
&lt;circle class="stroke" cx="20" cy="8" r="7"/>
&lt;line class="stroke" x1="20" y1="15" x2="20" y2="42"/>
&lt;line class="stroke" x1="7" y1="26" x2="33" y2="26"/>
&lt;line class="stroke" x1="20" y1="42" x2="9" y2="58"/>
&lt;line class="stroke" x1="20" y1="42" x2="31" y2="58"/>
&lt;/g>
&lt;text class="label" x="100" y="215">End-user&lt;/text>
&lt;!-- User → Client app -->
&lt;line class="flow" x1="100" y1="140" x2="100" y2="118" marker-end="url(#mk)"/>
&lt;/svg>
&lt;/figure>
&lt;p>The dex repo contains a small &lt;a href="https://github.com/dexidp/dex/tree/master/examples/example-app">example app&lt;/a> as a working, self contained app that performs this flow.&lt;/p>
&lt;p>The rest of this section explores the code sections which help explain how to implement this logic in your own app.&lt;/p>
&lt;h3 id="configuring-your-app">Configuring your app&lt;a class="heading-anchor" href="#configuring-your-app" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The example app uses the following Go packages to perform the code flow:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://godoc.org/github.com/coreos/go-oidc">github.com/coreos/go-oidc&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://godoc.org/golang.org/x/oauth2">golang.org/x/oauth2&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>First, client details should be present in the dex configuration. For example, we could register an app with dex with the following section:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">id&lt;/span>: example-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: example-app-secret
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: &lt;span style="color:#98c379">&amp;#39;Example App&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Where the app will be running.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#39;http://127.0.0.1:5555/callback&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this case, the Go code would be configured as:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// Initialize a provider by specifying dex&amp;#39;s issuer URL.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#e06c75">provider&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">oidc&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">NewProvider&lt;/span>(&lt;span style="color:#e06c75">ctx&lt;/span>, &lt;span style="color:#98c379">&amp;#34;https://dex-issuer-url.com&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// handle error
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// Configure the OAuth2 config with the client values.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#e06c75">oauth2Config&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">oauth2&lt;/span>.&lt;span style="color:#e06c75">Config&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// client_id and client_secret of the client.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#e06c75">ClientID&lt;/span>: &lt;span style="color:#98c379">&amp;#34;example-app&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ClientSecret&lt;/span>: &lt;span style="color:#98c379">&amp;#34;example-app-secret&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// The redirectURL.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#e06c75">RedirectURL&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5555/callback&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// Discovery returns the OAuth2 endpoints.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#e06c75">Endpoint&lt;/span>: &lt;span style="color:#e06c75">provider&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Endpoint&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// &amp;#34;openid&amp;#34; is a required scope for OpenID Connect flows.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#7f848e">//
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#7f848e">// Other scopes, such as &amp;#34;groups&amp;#34; can be requested.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#e06c75">Scopes&lt;/span>: []&lt;span style="color:#e5c07b">string&lt;/span>{&lt;span style="color:#e06c75">oidc&lt;/span>.&lt;span style="color:#e06c75">ScopeOpenID&lt;/span>, &lt;span style="color:#98c379">&amp;#34;profile&amp;#34;&lt;/span>, &lt;span style="color:#98c379">&amp;#34;email&amp;#34;&lt;/span>, &lt;span style="color:#98c379">&amp;#34;groups&amp;#34;&lt;/span>},
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// Create an ID token parser.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#e06c75">idTokenVerifier&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">provider&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Verifier&lt;/span>(&lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">oidc&lt;/span>.&lt;span style="color:#e06c75">Config&lt;/span>{&lt;span style="color:#e06c75">ClientID&lt;/span>: &lt;span style="color:#98c379">&amp;#34;example-app&amp;#34;&lt;/span>})
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The HTTP server should then redirect unauthenticated users to dex to initialize the OAuth2 flow.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// handleRedirect is used to start an OAuth2 flow with the dex server.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#c678dd">func&lt;/span> &lt;span style="color:#61afef;font-weight:bold">handleRedirect&lt;/span>(&lt;span style="color:#e06c75">w&lt;/span> &lt;span style="color:#e06c75">http&lt;/span>.&lt;span style="color:#e06c75">ResponseWriter&lt;/span>, &lt;span style="color:#e06c75">r&lt;/span> &lt;span style="color:#56b6c2">*&lt;/span>&lt;span style="color:#e06c75">http&lt;/span>.&lt;span style="color:#e06c75">Request&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">state&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#61afef;font-weight:bold">newState&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">http&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Redirect&lt;/span>(&lt;span style="color:#e06c75">w&lt;/span>, &lt;span style="color:#e06c75">r&lt;/span>, &lt;span style="color:#e06c75">oauth2Config&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">AuthCodeURL&lt;/span>(&lt;span style="color:#e06c75">state&lt;/span>), &lt;span style="color:#e06c75">http&lt;/span>.&lt;span style="color:#e06c75">StatusFound&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>After dex verifies the user&amp;rsquo;s identity it redirects the user back to the client app with a code that can be exchanged for an ID token. The ID token can then be parsed by the verifier created above. This immediately&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">func&lt;/span> &lt;span style="color:#61afef;font-weight:bold">handleOAuth2Callback&lt;/span>(&lt;span style="color:#e06c75">w&lt;/span> &lt;span style="color:#e06c75">http&lt;/span>.&lt;span style="color:#e06c75">ResponseWriter&lt;/span>, &lt;span style="color:#e06c75">r&lt;/span> &lt;span style="color:#56b6c2">*&lt;/span>&lt;span style="color:#e06c75">http&lt;/span>.&lt;span style="color:#e06c75">Request&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">state&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">r&lt;/span>.&lt;span style="color:#e06c75">URL&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Query&lt;/span>().&lt;span style="color:#61afef;font-weight:bold">Get&lt;/span>(&lt;span style="color:#98c379">&amp;#34;state&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// Verify state.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">oauth2Token&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">oauth2Config&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Exchange&lt;/span>(&lt;span style="color:#e06c75">ctx&lt;/span>, &lt;span style="color:#e06c75">r&lt;/span>.&lt;span style="color:#e06c75">URL&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Query&lt;/span>().&lt;span style="color:#61afef;font-weight:bold">Get&lt;/span>(&lt;span style="color:#98c379">&amp;#34;code&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// handle error
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// Extract the ID Token from OAuth2 token.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#e06c75">rawIDToken&lt;/span>, &lt;span style="color:#e06c75">ok&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">oauth2Token&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Extra&lt;/span>(&lt;span style="color:#98c379">&amp;#34;id_token&amp;#34;&lt;/span>).(&lt;span style="color:#e5c07b">string&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> !&lt;span style="color:#e06c75">ok&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// handle missing token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// Parse and verify ID Token payload.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#e06c75">idToken&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">idTokenVerifier&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Verify&lt;/span>(&lt;span style="color:#e06c75">ctx&lt;/span>, &lt;span style="color:#e06c75">rawIDToken&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// handle error
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// Extract custom claims.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#c678dd">var&lt;/span> &lt;span style="color:#e06c75">claims&lt;/span> &lt;span style="color:#c678dd">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Email&lt;/span> &lt;span style="color:#e5c07b">string&lt;/span> &lt;span style="color:#98c379">`json:&amp;#34;email&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Verified&lt;/span> &lt;span style="color:#e5c07b">bool&lt;/span> &lt;span style="color:#98c379">`json:&amp;#34;email_verified&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Groups&lt;/span> []&lt;span style="color:#e5c07b">string&lt;/span> &lt;span style="color:#98c379">`json:&amp;#34;groups&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">idToken&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Claims&lt;/span>(&lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">claims&lt;/span>); &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// handle error
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="state-tokens">State tokens&lt;a class="heading-anchor" href="#state-tokens" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The state parameter is an arbitrary string that dex will always return with the callback. It plays a security role, preventing certain kinds of OAuth2 attacks. Specifically it can be used by clients to ensure:&lt;/p>
&lt;ul>
&lt;li>The user who started the flow is the one who finished it, by linking the user&amp;rsquo;s session with the state token. For example, by setting the state as an HTTP cookie, then comparing it when the user returns to the app.&lt;/li>
&lt;li>The request hasn&amp;rsquo;t been replayed. This could be accomplished by associating some nonce in the state.&lt;/li>
&lt;/ul>
&lt;p>A more thorough discussion of these kinds of best practices can be found in the &lt;a href="https://tools.ietf.org/html/rfc6819">&lt;em>&amp;ldquo;OAuth 2.0 Threat Model and Security Considerations&amp;rdquo;&lt;/em>&lt;/a> RFC.&lt;/p>
&lt;h2 id="consuming-id-tokens">Consuming ID tokens&lt;a class="heading-anchor" href="#consuming-id-tokens" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Apps can also choose to consume ID tokens, letting other trusted clients handle the web flows for login. Clients pass along the ID tokens they receive from dex, usually as a bearer token, letting them act as the user to the backend service.&lt;/p>
&lt;figure class="diagram">
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 310" role="img" aria-label="End-user uses a Client app; the Client app delegates authentication to Dex, which talks to an upstream Identity Provider. Dex issues an id_token back to the Client app, which in turn forwards it to a Backend service as a bearer credential.">
&lt;style>
.stroke { fill: none; stroke: var(--text-secondary, #475569); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.box { fill: var(--bg-card, #FFFFFF); stroke: var(--border-strong, #94A3B8); stroke-width: 1.5; }
.box-dex { fill: var(--blue-tint-2, rgba(68,159,216,0.08)); stroke: var(--dex-blue, #449FD8); stroke-width: 1.8; }
.label { fill: var(--text-primary, #0F172A); font-family: var(--font-sans, -apple-system, Helvetica, sans-serif); font-size: 13px; font-weight: 600; text-anchor: middle; }
.label-dex { fill: var(--dex-blue, #449FD8); font-weight: 700; font-size: 15px; letter-spacing: -0.01em; }
.token { fill: var(--dex-red, #F04D5C); font-family: var(--font-mono, Menlo, monospace); font-size: 10px; font-weight: 600; text-anchor: middle; letter-spacing: 0.04em; }
.flow { fill: none; stroke: var(--text-secondary, #475569); stroke-width: 1.5; stroke-linecap: round; }
.flow-back { fill: none; stroke: var(--dex-red, #F04D5C); stroke-width: 1.5; stroke-dasharray: 4 3; stroke-linecap: round; }
.head { fill: var(--text-secondary, #475569); }
.head-back { fill: var(--dex-red, #F04D5C); }
&lt;/style>
&lt;defs>
&lt;marker id="mk" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
&lt;path class="head" d="M 0 0 L 10 5 L 0 10 z"/>
&lt;/marker>
&lt;marker id="mk-back" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
&lt;path class="head-back" d="M 0 0 L 10 5 L 0 10 z"/>
&lt;/marker>
&lt;/defs>
&lt;!-- ═══════ Backend service box — typography only ═══════ -->
&lt;rect class="box" x="30" y="25" width="140" height="50" rx="3"/>
&lt;text class="label" x="100" y="56">Backend Service&lt;/text>
&lt;!-- Client → Backend: id_token (red dashed upward).
Offset 20px LEFT of centre so it doesn't collide with the
Dex → Client return arrow. The arrow is deliberately split in two
segments with the label sitting in the gap, read-directly-on-arrow. -->
&lt;line class="flow-back" x1="80" y1="135" x2="80" y2="117"/>
&lt;line class="flow-back" x1="80" y1="103" x2="80" y2="78" marker-end="url(#mk-back)"/>
&lt;text class="token" x="80" y="110" dominant-baseline="middle">id_token&lt;/text>
&lt;!-- ═══════ id_token return Dex → Client app (on TOP of main row).
Lands 20px RIGHT of Client-app centre to stay clear of the
Client → Backend arrow. ═══════ -->
&lt;path class="flow-back" d="M 260 135 L 260 110 L 120 110 L 120 135" marker-end="url(#mk-back)"/>
&lt;text class="token" x="190" y="104">id_token&lt;/text>
&lt;!-- ═══════ Client app box ═══════ -->
&lt;rect class="box" x="30" y="135" width="140" height="70" rx="3"/>
&lt;text class="label" x="100" y="176">Client App&lt;/text>
&lt;!-- ═══════ Dex box — only icon: brand glyph ═══════ -->
&lt;rect class="box-dex" x="190" y="135" width="140" height="70" rx="3"/>
&lt;g transform="translate(247, 142) scale(0.22)">
&lt;path fill="var(--dex-blue, #449FD8)" d="M88.345,51.574c7.588-3.55,12.764-10.49,14.175-18.53C96.396,19.395,84.663,9.054,70.094,4.851
c4.923,7.133,7.272,15.583,6.771,24.17C83.311,34.466,87.716,42.55,88.345,51.574z M27.27,38.542
c-8.207-1.045-16.333,1.973-21.858,8.054C3.23,61.683,7.869,76.84,18.099,88.158c-0.527-8.64,1.856-17.306,6.831-24.483
C22.19,55.048,23.32,45.944,27.27,38.542z M33.01,76.928c-2.997,8.079-1.755,17.193,3.642,24.215
c12.155,4.943,26.051,5.146,38.643-0.035c-7.818-2.516-14.886-7.518-19.887-14.731C47.233,86.23,39.124,83.032,33.01,76.928z
M63.122,22.202C61.615,14.044,56.069,6.819,47.892,3.47C33.778,5.711,20.745,13.966,12.76,26.631
c8.115-2.487,16.74-2.178,24.529,0.639C44.816,22.008,54.043,20.144,63.122,22.202z M85.891,66.457
c-3.086,7.399-8.722,13.188-15.678,16.61c6.194,5.604,14.805,7.758,22.852,5.834c9.054-9.587,13.884-22.198,13.9-35.009
C101.549,60.198,94.131,64.67,85.891,66.457z"/>
&lt;circle fill="var(--dex-red, #F04D5C)" cx="56.035" cy="53.892" r="15.972"/>
&lt;/g>
&lt;text class="label label-dex" x="260" y="188">Dex&lt;/text>
&lt;!-- ═══════ Identity Provider box ═══════ -->
&lt;rect class="box" x="350" y="135" width="140" height="70" rx="3"/>
&lt;text class="label" x="420" y="176">Upstream IdP&lt;/text>
&lt;!-- Forward flow arrows -->
&lt;line class="flow" x1="170" y1="170" x2="188" y2="170" marker-end="url(#mk)"/>
&lt;line class="flow" x1="330" y1="170" x2="348" y2="170" marker-end="url(#mk)"/>
&lt;!-- ═══════ End-user stick figure below Client app ═══════ -->
&lt;g transform="translate(80, 234)">
&lt;circle class="stroke" cx="20" cy="8" r="7"/>
&lt;line class="stroke" x1="20" y1="15" x2="20" y2="42"/>
&lt;line class="stroke" x1="7" y1="26" x2="33" y2="26"/>
&lt;line class="stroke" x1="20" y1="42" x2="9" y2="58"/>
&lt;line class="stroke" x1="20" y1="42" x2="31" y2="58"/>
&lt;/g>
&lt;text class="label" x="100" y="305">End-user&lt;/text>
&lt;!-- User → Client app -->
&lt;line class="flow" x1="100" y1="230" x2="100" y2="208" marker-end="url(#mk)"/>
&lt;/svg>
&lt;/figure>
&lt;p>To accept ID tokens as user credentials, an app would construct an OpenID Connect verifier similarly to the above example. The verifier validates the ID token&amp;rsquo;s signature, ensures it hasn&amp;rsquo;t expired, etc. An important part of this code is that the verifier only trusts the example app&amp;rsquo;s client. This ensures the example app is the one who&amp;rsquo;s using the ID token, and not another, untrusted client.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// Initialize a provider by specifying dex&amp;#39;s issuer URL.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#e06c75">provider&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">oidc&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">NewProvider&lt;/span>(&lt;span style="color:#e06c75">ctx&lt;/span>, &lt;span style="color:#98c379">&amp;#34;https://dex-issuer-url.com&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// handle error
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// Create an ID token parser, but only trust ID tokens issued to &amp;#34;example-app&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#e06c75">idTokenVerifier&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">provider&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Verifier&lt;/span>(&lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">oidc&lt;/span>.&lt;span style="color:#e06c75">Config&lt;/span>{&lt;span style="color:#e06c75">ClientID&lt;/span>: &lt;span style="color:#98c379">&amp;#34;example-app&amp;#34;&lt;/span>})
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The verifier can then be used to pull user info out of tokens:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">type&lt;/span> &lt;span style="color:#e06c75">user&lt;/span> &lt;span style="color:#c678dd">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">email&lt;/span> &lt;span style="color:#e5c07b">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span> []&lt;span style="color:#e5c07b">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">// authorize verifies a bearer token and pulls user information form the claims.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>&lt;span style="color:#c678dd">func&lt;/span> &lt;span style="color:#61afef;font-weight:bold">authorize&lt;/span>(&lt;span style="color:#e06c75">ctx&lt;/span> &lt;span style="color:#e06c75">context&lt;/span>.&lt;span style="color:#e06c75">Context&lt;/span>, &lt;span style="color:#e06c75">bearerToken&lt;/span> &lt;span style="color:#e5c07b">string&lt;/span>) (&lt;span style="color:#56b6c2">*&lt;/span>&lt;span style="color:#e06c75">user&lt;/span>, &lt;span style="color:#e5c07b">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">idToken&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">idTokenVerifier&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Verify&lt;/span>(&lt;span style="color:#e06c75">ctx&lt;/span>, &lt;span style="color:#e06c75">bearerToken&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span>, &lt;span style="color:#e06c75">fmt&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Errorf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;could not verify bearer token: %v&amp;#34;&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// Extract custom claims.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span> &lt;span style="color:#c678dd">var&lt;/span> &lt;span style="color:#e06c75">claims&lt;/span> &lt;span style="color:#c678dd">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Email&lt;/span> &lt;span style="color:#e5c07b">string&lt;/span> &lt;span style="color:#98c379">`json:&amp;#34;email&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Verified&lt;/span> &lt;span style="color:#e5c07b">bool&lt;/span> &lt;span style="color:#98c379">`json:&amp;#34;email_verified&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Groups&lt;/span> []&lt;span style="color:#e5c07b">string&lt;/span> &lt;span style="color:#98c379">`json:&amp;#34;groups&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">idToken&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Claims&lt;/span>(&lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">claims&lt;/span>); &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span>, &lt;span style="color:#e06c75">fmt&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Errorf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;failed to parse claims: %v&amp;#34;&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> !&lt;span style="color:#e06c75">claims&lt;/span>.&lt;span style="color:#e06c75">Verified&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span>, &lt;span style="color:#e06c75">fmt&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Errorf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;email (%q) in returned claims was not verified&amp;#34;&lt;/span>, &lt;span style="color:#e06c75">claims&lt;/span>.&lt;span style="color:#e06c75">Email&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">user&lt;/span>{&lt;span style="color:#e06c75">claims&lt;/span>.&lt;span style="color:#e06c75">Email&lt;/span>, &lt;span style="color:#e06c75">claims&lt;/span>.&lt;span style="color:#e06c75">Groups&lt;/span>}, &lt;span style="color:#e5c07b">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: An Overview of OpenID Connect</title><link>https://dexidp.io/docs/openid-connect/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/openid-connect/</guid><description>
&lt;p>This document attempts to provide a general overview of the &lt;a href="https://openid.net/connect/">OpenID Connect protocol&lt;/a>, a flavor of OAuth2 that dex implements. While this document isn&amp;rsquo;t complete, we hope it provides enough information to get users up and running.&lt;/p>
&lt;p>For an overview of custom claims, scopes, and client features implemented by dex, see &lt;a href="https://dexidp.io/docs/configuration/custom-scopes-claims-clients/">this document&lt;/a>.&lt;/p>
&lt;h2 id="oauth2">OAuth2&lt;a class="heading-anchor" href="#oauth2" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>OAuth2 should be familiar to anyone who&amp;rsquo;s used something similar to a &amp;ldquo;Login
with Google&amp;rdquo; button. In these cases an application has chosen to let an
outside provider, in this case Google, attest to your identity instead of
having you set a username and password with the app itself.&lt;/p>
&lt;p>The general flow for server side apps is:&lt;/p>
&lt;ol>
&lt;li>A new user visits an application.&lt;/li>
&lt;li>The application redirects the user to Google.&lt;/li>
&lt;li>The user logs into Google, then is asked if it&amp;rsquo;s okay to let the
application view the user&amp;rsquo;s profile, post on their behalf, etc.&lt;/li>
&lt;li>If the user clicks okay, Google redirects the user back to the application
with a code.&lt;/li>
&lt;li>The application redeems that code with provider for a token that can be used
to access the authorized actions, such as viewing a users profile or posting on
their wall.&lt;/li>
&lt;/ol>
&lt;p>In these cases, dex is acting as Google (called the &amp;ldquo;provider&amp;rdquo; in OpenID
Connect) while clients apps redirect to it for the end user&amp;rsquo;s identity.&lt;/p>
&lt;h2 id="id-tokens">ID Tokens&lt;a class="heading-anchor" href="#id-tokens" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Unfortunately the access token applications get from OAuth2 providers is
completely opaque to the client and unique to the provider. The token you
receive from Google will be completely different from the one you&amp;rsquo;d get from
Twitter or GitHub.&lt;/p>
&lt;p>OpenID Connect&amp;rsquo;s primary extension of OAuth2 is an additional token returned in
the token response called the ID Token. This token is a &lt;a href="https://tools.ietf.org/html/rfc7519">JSON Web Token&lt;/a> signed by the OpenID Connect server, with
well known fields for user ID, name, email, etc. A typical token response from
an OpenID Connect looks like (with less whitespace):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>HTTP/&lt;span style="color:#d19a66">1.1&lt;/span> &lt;span style="color:#d19a66">200&lt;/span> OK
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Content-Type: application/json
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Cache-Control: no-store
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Pragma: no-cache
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;access_token&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;SlAV32hkKG&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;token_type&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;Bearer&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;refresh_token&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;8xLOxBtZp8&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;expires_in&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">3600&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;id_token&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6qJp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJNqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7TpdQyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoSK5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That ID Token is a JWT with three base64&amp;rsquo;d fields separated by dots. The first
is a header, the second is a payload, and the third is a signature of the first
two fields. When parsed we can see the payload of this value is.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;iss&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://server.example.com&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;sub&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;248289761001&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;aud&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;s6BhdRkqt3&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;nonce&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;n-0S6_WzA2Mj&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;exp&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">1311281970&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;iat&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">1311280970&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This has a few interesting fields such as&lt;/p>
&lt;ul>
&lt;li>The server that issued this token (&lt;code>iss&lt;/code>).&lt;/li>
&lt;li>The token&amp;rsquo;s subject (&lt;code>sub&lt;/code>). In this case a unique ID of the end user.&lt;/li>
&lt;li>The token&amp;rsquo;s audience (&lt;code>aud&lt;/code>). The ID of the OAuth2 client this was issued for.&lt;/li>
&lt;/ul>
&lt;p>A real world token would have additional claims like the user&amp;rsquo;s name, email, groups, etc.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;iss&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;https://dex.example.com/&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;sub&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;R29vZCBqb2IhIEdpdmUgdXMgYSBzdGFyIG9uIGdpdGh1Yg&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;aud&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;kubernetes&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;kubeconfig-generator&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;exp&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">1712945837&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;iat&amp;#34;&lt;/span>: &lt;span style="color:#d19a66">1712945237&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;azp&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;kubeconfig-generator&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;at_hash&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;OamCo8c60Zdj3dVho3Km5oxA&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;c_hash&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;HT04XtwtlUhfHvm7zf19qsGw&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;email&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;maksim.nabokikh@palark.com&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;email_verified&amp;#34;&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;groups&amp;#34;&lt;/span>: [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;administrators&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;developers&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;Maksim Nabokikh&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;preferred_username&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;maksim.nabokikh&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="discovery">Discovery&lt;a class="heading-anchor" href="#discovery" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>OpenID Connect servers have a discovery mechanism for OAuth2 endpoints, scopes
supported, and indications of various other OpenID Connect features.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ curl http://127.0.0.1:5556/dex/.well-known/openid-configuration
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;issuer&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5556&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;authorization_endpoint&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5556/auth&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;token_endpoint&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5556/token&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;jwks_uri&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5556/keys&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;response_types_supported&amp;#34;&lt;/span>: &lt;span style="color:#56b6c2">[&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;code&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">]&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;subject_types_supported&amp;#34;&lt;/span>: &lt;span style="color:#56b6c2">[&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;public&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">]&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;id_token_signing_alg_values_supported&amp;#34;&lt;/span>: &lt;span style="color:#56b6c2">[&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;RS256&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">]&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;scopes_supported&amp;#34;&lt;/span>: &lt;span style="color:#56b6c2">[&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;openid&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;email&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;profile&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Importantly, we&amp;rsquo;ve discovered the authorization endpoint, token endpoint, and
the location of the server&amp;rsquo;s public keys. OAuth2 clients should be able to use
the token and auth endpoints immediately, while a JOSE library can be used to
parse the keys. The keys endpoint returns a &lt;a href="https://tools.ietf.org/html/rfc7517">JSON Web Key&lt;/a> Set of public keys that will look
something like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ curl http://127.0.0.1:5556/dex/keys
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;keys&amp;#34;&lt;/span>: &lt;span style="color:#56b6c2">[&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;use&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;sig&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;kty&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;RSA&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;kid&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;5d19a0fde5547960f4edaa1e1e8293e5534169ba&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;alg&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;RS256&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;n&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;5TAXCxkAQqHEqO0InP81z5F59PUzCe5ZNaDsD1SXzFe54BtXKn_V2a3K-BUNVliqMKhC2LByWLuI-A5ZlA5kXkbRFT05G0rusiM0rbkN2uvRmRCia4QlywE02xJKzeZV3KH6PldYqV_Jd06q1NV3WNqtcHN6MhnwRBfvkEIm7qWdPZ_mVK7vayfEnOCFRa7EZqr-U_X84T0-50wWkHTa0AfnyVvSMK1eKL-4yc26OWkmjh5ALfQFtnsz30Y2TOJdXtEfn35Y_882dNBDYBxtJV4PaSjXCxhiaIuBHp5uRS1INyMXCx2ve22ASNx_ERorv6BlXQoMDqaML2bSiN9N8Q&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;e&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;AQAB&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#56b6c2">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Dex v2</title><link>https://dexidp.io/docs/archive/v2/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/archive/v2/</guid><description>
&lt;h2 id="streamlined-deployments">Streamlined deployments&lt;a class="heading-anchor" href="#streamlined-deployments" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Many of the changes between v1 and v2 were aimed at making dex easier to deploy and manage, perhaps the biggest pain point for dex v1. Dex is now a single, scalable binary with a sole source of configuration. Many components which previously had to be set through the API, such as OAuth2 clients and IDP connectors can now be specified statically. The new architecture lacks a singleton component eliminating deployment ordering. There are no more special development modes; instructions for running dex on a workstation translate with minimal changes to a production system.&lt;/p>
&lt;p>All of this results in a much simpler deployment story. Write a config file, run the dex binary, and that&amp;rsquo;s it.&lt;/p>
&lt;h2 id="more-storage-backends">More storage backends&lt;a class="heading-anchor" href="#more-storage-backends" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex&amp;rsquo;s internal storage interface has been improved to support multiple backing databases including Postgres, SQLite3, and the Kubernetes API through Third Party Resources. This allows dex to meet a more diverse set of use cases instead of insisting on one particular deployment pattern. For example, The Kubernetes API implementation, a &lt;a href="http://kubernetes.io/docs/api/">key value store&lt;/a>, allows dex to be run natively on top of a Kubernetes cluster with extremely little administrative overhead. Starting with support for multiple storage backends also should help ensure that the dex storage interface is actually pluggable, rather than being coupled too tightly with a single implementation.&lt;/p>
&lt;p>A more in depth discussion of existing storage options and how to add new ones can be found &lt;a href="https://dexidp.io/docs/configuration/storage/">here&lt;/a>.&lt;/p>
&lt;h2 id="additional-improvements">Additional improvements&lt;a class="heading-anchor" href="#additional-improvements" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The rewrite came with several, miscellaneous improvements including:&lt;/p>
&lt;ul>
&lt;li>More powerful connectors. For example the GitHub connector can now query for teams.&lt;/li>
&lt;li>Combined the two APIs into a single &lt;a href="https://dexidp.io/docs/configuration/api/">gRPC API&lt;/a> with no complex authorization rules.&lt;/li>
&lt;li>Expanded OAuth2 capabilities such as the implicit flow.&lt;/li>
&lt;li>Simplified codebase and improved testing.&lt;/li>
&lt;/ul>
&lt;h2 id="rethinking-registration">Rethinking registration&lt;a class="heading-anchor" href="#rethinking-registration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex v1 performed well when it could manage users. It provided features such as registration, email invites, password resets, administrative abilities, etc. However, login flows and APIs remain tightly coupled with concepts like registration and admin users even when v1 federated to an upstream identity provider (IDP) where it likely only had read only access to the actual user database.&lt;/p>
&lt;p>Many of v2&amp;rsquo;s use cases focus on federation to other IPDs rather than managing users itself. Because of this, options associated with registration, such as SMTP credentials, have been removed. We hope to add registration and user management back into the project through orthogonal applications using the &lt;a href="https://dexidp.io/docs/configuration/api/">gRPC API&lt;/a>, but in a way that doesn&amp;rsquo;t impact other use cases.&lt;/p>
&lt;h2 id="removed-features">Removed features&lt;a class="heading-anchor" href="#removed-features" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex v2 lacks certain features present in v1. For the most part &lt;em>we aim to add most of these features back into v2&lt;/em>, but in a way that installations have to &lt;em>opt in&lt;/em> to a feature instead of burdening every deployment with extra configuration.&lt;/p>
&lt;p>Notable missing features include:&lt;/p>
&lt;ul>
&lt;li>Registration flows.&lt;/li>
&lt;li>Local user management.&lt;/li>
&lt;li>SMTP configuration and email verification.&lt;/li>
&lt;li>Several of the login connectors that have yet to be ported.&lt;/li>
&lt;/ul>
&lt;h2 id="support-for-dex-v1">Support for dex v1&lt;a class="heading-anchor" href="#support-for-dex-v1" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex v1 will continue to live under the &lt;code>github.com/dexidp/dex&lt;/code> repo on a branch. Bug fixes and minor changes will continue to be accepted, but development of new features by the dex team will largely cease.&lt;/p></description></item><item><title>Docs: Scopes and Claims</title><link>https://dexidp.io/docs/configuration/custom-scopes-claims-clients/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/configuration/custom-scopes-claims-clients/</guid><description>
&lt;p>This document describes the set of OAuth2 and OpenID Connect features implemented by dex.&lt;/p>
&lt;h2 id="scopes">Scopes&lt;a class="heading-anchor" href="#scopes" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The following is the exhaustive list of scopes supported by dex:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">Name&lt;/th>
&lt;th style="text-align: left">Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;code>openid&lt;/code>&lt;/td>
&lt;td style="text-align: left">Required scope for all login requests.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>email&lt;/code>&lt;/td>
&lt;td style="text-align: left">ID token claims should include the end user&amp;rsquo;s email and if that email was verified by an upstream provider.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>profile&lt;/code>&lt;/td>
&lt;td style="text-align: left">ID token claims should include the username of the end user.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>groups&lt;/code>&lt;/td>
&lt;td style="text-align: left">ID token claims should include a list of groups the end user is a member of.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>federated:id&lt;/code>&lt;/td>
&lt;td style="text-align: left">ID token claims should include information from the ID provider. The token will contain the connector ID and the user ID assigned at the provider.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>offline_access&lt;/code>&lt;/td>
&lt;td style="text-align: left">Token response should include a refresh token. Doesn&amp;rsquo;t work in combinations with some connectors, notability the &lt;a href="https://dexidp.io/docs/connectors/saml/">SAML connector&lt;/a> ignores this scope.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>audience:server:client_id:( client-id )&lt;/code>&lt;/td>
&lt;td style="text-align: left">Dynamic scope indicating that the ID token should be issued on behalf of another client. See the &lt;em>&amp;ldquo;Cross-client trust and authorized party&amp;rdquo;&lt;/em> section below.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="custom-claims">Custom claims&lt;a class="heading-anchor" href="#custom-claims" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Beyond the &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#IDToken">required OpenID Connect claims&lt;/a>, and a handful of &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims">standard claims&lt;/a>, dex implements the following non-standard claims.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">Name&lt;/th>
&lt;th style="text-align: left">Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;code>groups&lt;/code>&lt;/td>
&lt;td style="text-align: left">A list of strings representing the groups a user is a member of.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>federated_claims&lt;/code>&lt;/td>
&lt;td style="text-align: left">The connector ID and the user ID assigned to the user at the provider.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>email&lt;/code>&lt;/td>
&lt;td style="text-align: left">The email of the user.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>email_verified&lt;/code>&lt;/td>
&lt;td style="text-align: left">If the upstream provider has verified the email.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>name&lt;/code>&lt;/td>
&lt;td style="text-align: left">User&amp;rsquo;s display name.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>preferred_username&lt;/code>&lt;/td>
&lt;td style="text-align: left">Shorthand name by which the End-User wishes to be referred to.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>The &lt;code>federated_claims&lt;/code> claim has the following format:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&amp;#34;federated_claims&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;connector_id&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;github&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;user_id&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;110272483197731336751&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="cross-client-trust-and-authorized-party">Cross-client trust and authorized party&lt;a class="heading-anchor" href="#cross-client-trust-and-authorized-party" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex has the ability to issue ID tokens to clients on behalf of other clients. In OpenID Connect terms, this means the ID token&amp;rsquo;s &lt;code>aud&lt;/code> (audience) claim being a different client ID than the client that performed the login.&lt;/p>
&lt;p>For example, this feature could be used to allow a web app to generate an ID token on behalf of a command line tool:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">id&lt;/span>: web-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#39;https://web-app.example.com/callback&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: &lt;span style="color:#98c379">&amp;#39;Web app&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: web-app-secret
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># It is also possible to fetch the secret from an injected environment variable&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># secretEnv: YOUR_INJECTED_SECRET&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">id&lt;/span>: cli-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#39;https://cli-app.example.com/callback&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: &lt;span style="color:#98c379">&amp;#39;Command line tool&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: cli-app-secret
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The command line tool lets the web app issue ID tokens on its behalf.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">trustedPeers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - web-app
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note that the command line tool must explicitly trust the web app using the &lt;code>trustedPeers&lt;/code> field. The web app can then use the following scope to request an ID token that&amp;rsquo;s issued for the command line tool.&lt;/p>
&lt;pre tabindex="0">&lt;code>audience:server:client_id:cli-app
&lt;/code>&lt;/pre>&lt;p>The ID token claims will then include the following audience and authorized party:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;aud&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;cli-app&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;azp&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;web-app&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;email&amp;#34;&lt;/span>: &lt;span style="color:#98c379">&amp;#34;foo@bar.com&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">// other claims...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e">&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="public-clients">Public clients&lt;a class="heading-anchor" href="#public-clients" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Public clients are inspired by Google&amp;rsquo;s &lt;a href="https://developers.google.com/api-client-library/python/auth/installed-app">&lt;em>&amp;ldquo;Installed Applications&amp;rdquo;&lt;/em>&lt;/a> and are meant to impose restrictions on applications that don&amp;rsquo;t intend to keep their client secret private. Clients can be declared as public using the &lt;code>public&lt;/code> config option.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">id&lt;/span>: cli-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">public&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: &lt;span style="color:#98c379">&amp;#39;CLI app&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If no &lt;code>redirectURIs&lt;/code> are specified, public clients only support redirects that begin with &amp;ldquo;http://localhost&amp;rdquo; or a special &amp;ldquo;out-of-browser&amp;rdquo; URL &amp;ldquo;urn:ietf:wg:oauth:2.0:oob&amp;rdquo;.
The latter triggers dex to display the OAuth2 code in the browser, prompting the end user to manually copy it to their app. It&amp;rsquo;s the client&amp;rsquo;s responsibility to either create a screen or a prompt to receive the code, then perform a code exchange for a token response.&lt;/p>
&lt;p>When using the &amp;ldquo;out-of-browser&amp;rdquo; flow, an ID Token nonce is strongly recommended.&lt;/p></description></item><item><title>Docs: Storage</title><link>https://dexidp.io/docs/configuration/storage/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/configuration/storage/</guid><description>
&lt;p>Dex requires persisting state to perform various tasks such as track refresh tokens, preventing replays, and rotating keys. This document is a summary of the storage configurations supported by dex.&lt;/p>
&lt;p>Storage breaches are serious as they can affect applications that rely on dex. Dex saves sensitive data in its backing storage, including signing keys and bcrypt&amp;rsquo;d passwords. As such, transport security and database ACLs should both be used, no matter which storage option is chosen.&lt;/p>
&lt;h2 id="etcd">Etcd&lt;a class="heading-anchor" href="#etcd" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex supports persisting state to &lt;a href="https://github.com/coreos/etcd">etcd v3&lt;/a>.&lt;/p>
&lt;p>An example etcd configuration is using these values:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: etcd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># list of etcd endpoints we should connect to&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">endpoints&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - http://localhost:2379
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">namespace&lt;/span>: my-etcd-namespace/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Etcd storage can be customized further using the following options:&lt;/p>
&lt;ul>
&lt;li>&lt;code>endpoints&lt;/code>: list of etcd endpoints we should connect to&lt;/li>
&lt;li>&lt;code>namespace&lt;/code>: etcd namespace to be set for the connection. All keys created by
etcd storage will be prefixed with the namespace. This is useful when you
share your etcd cluster amongst several applications. Another approach for
setting namespace is to use &lt;a href="https://coreos.com/etcd/docs/latest/op-guide/grpc_proxy.html#namespacing">etcd proxy&lt;/a>&lt;/li>
&lt;li>&lt;code>username&lt;/code>: username for etcd authentication&lt;/li>
&lt;li>&lt;code>password&lt;/code>: password for etcd authentication&lt;/li>
&lt;li>&lt;code>ssl&lt;/code>: ssl setup for etcd connection
&lt;ul>
&lt;li>&lt;code>serverName&lt;/code>: ensures that the certificate matches the given hostname the
client is connecting to.&lt;/li>
&lt;li>&lt;code>caFile&lt;/code>: path to the ca&lt;/li>
&lt;li>&lt;code>keyFile&lt;/code>: path to the private key&lt;/li>
&lt;li>&lt;code>certFile&lt;/code>: path to the certificate&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="kubernetes-custom-resource-definitions-crds">Kubernetes custom resource definitions (CRDs)&lt;a class="heading-anchor" href="#kubernetes-custom-resource-definitions-crds" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Kubernetes &lt;a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/">custom resource definitions&lt;/a> are a way for applications to create new resources types in the Kubernetes API.&lt;/p>
&lt;p>The Custom Resource Definition (CRD) API object was introduced in Kubernetes version 1.7 to replace the Third Party Resource (TPR) extension. CRDs allow dex to run on top of an existing Kubernetes cluster without the need for an external database. While this storage may not be appropriate for a large number of users, it&amp;rsquo;s extremely effective for many Kubernetes use cases.&lt;/p>
&lt;p>The rest of this section will explore internal details of how dex uses CRDs. &lt;strong>Admins should not interact with these resources directly&lt;/strong>, except while debugging. These resources are only designed to store state and aren&amp;rsquo;t meant to be consumed by end users. For modifying dex&amp;rsquo;s state dynamically see the &lt;a href="https://dexidp.io/docs/api/">API documentation&lt;/a>.&lt;/p>
&lt;p>The following is an example of the AuthCode resource managed by dex:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">apiVersion&lt;/span>: apiextensions.k8s.io/v1beta1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">kind&lt;/span>: CustomResourceDefinition
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">creationTimestamp&lt;/span>: 2017-09-13T19:56:28Z
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: authcodes.dex.coreos.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">resourceVersion&lt;/span>: &lt;span style="color:#98c379">&amp;#34;288893&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">selfLink&lt;/span>: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/authcodes.dex.coreos.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">uid&lt;/span>: a1cb72dc-98bd-11e7-8f6a-02d13336a01e
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">group&lt;/span>: dex.coreos.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">names&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">kind&lt;/span>: AuthCode
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">listKind&lt;/span>: AuthCodeList
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">plural&lt;/span>: authcodes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">singular&lt;/span>: authcode
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">scope&lt;/span>: Namespaced
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">version&lt;/span>: v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">status&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">acceptedNames&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">kind&lt;/span>: AuthCode
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">listKind&lt;/span>: AuthCodeList
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">plural&lt;/span>: authcodes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">singular&lt;/span>: authcode
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">conditions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">lastTransitionTime&lt;/span>: &lt;span style="color:#e5c07b">null&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">message&lt;/span>: &lt;span style="color:#e5c07b">no&lt;/span> conflicts found
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">reason&lt;/span>: NoConflicts
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">status&lt;/span>: &lt;span style="color:#98c379">&amp;#34;True&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: NamesAccepted
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">lastTransitionTime&lt;/span>: 2017-09-13T19:56:28Z
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">message&lt;/span>: the initial names have been accepted
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">reason&lt;/span>: InitialNamesAccepted
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">status&lt;/span>: &lt;span style="color:#98c379">&amp;#34;True&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: Established
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once the &lt;code>CustomResourceDefinition&lt;/code> is created, custom resources can be created and stored at a namespace level. The CRD type and the custom resources can be queried, deleted, and edited like any other resource using &lt;code>kubectl&lt;/code>.&lt;/p>
&lt;p>dex requires access to the non-namespaced &lt;code>CustomResourceDefinition&lt;/code> type. For example, clusters using RBAC authorization would need to create the following roles and bindings:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1beta1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">kind&lt;/span>: ClusterRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">rules&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">apiGroups&lt;/span>: [&lt;span style="color:#98c379">&amp;#34;dex.coreos.com&amp;#34;&lt;/span>] &lt;span style="color:#7f848e"># API group created by dex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">resources&lt;/span>: [&lt;span style="color:#98c379">&amp;#34;*&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">verbs&lt;/span>: [&lt;span style="color:#98c379">&amp;#34;*&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">apiGroups&lt;/span>: [&lt;span style="color:#98c379">&amp;#34;apiextensions.k8s.io&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">resources&lt;/span>: [&lt;span style="color:#98c379">&amp;#34;customresourcedefinitions&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">verbs&lt;/span>: [&lt;span style="color:#98c379">&amp;#34;create&amp;#34;&lt;/span>] &lt;span style="color:#7f848e"># To manage its own resources identity must be able to create customresourcedefinitions.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">---&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">apiVersion&lt;/span>: rbac.authorization.k8s.io/v1beta1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">kind&lt;/span>: ClusterRoleBinding
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">roleRef&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">apiGroup&lt;/span>: rbac.authorization.k8s.io
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">kind&lt;/span>: ClusterRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">subjects&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">kind&lt;/span>: ServiceAccount
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: dex &lt;span style="color:#7f848e"># Service account assigned to the dex pod.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">namespace&lt;/span>: dex-namespace &lt;span style="color:#7f848e"># The namespace dex is running in.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="removed-kubernetes-third-party-resourcestprs">Removed: Kubernetes third party resources(TPRs)&lt;a class="heading-anchor" href="#removed-kubernetes-third-party-resourcestprs" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>TPR support in dex has been removed. The last version to support TPR
is &lt;a href="https://github.com/dexidp/dex/tree/v2.17.0">v2.17.0&lt;/a>&lt;/p>
&lt;p>If you are currently running dex using TPRs, you will need to &lt;a href="https://github.com/dexidp/dex/blob/v2.17.0/Documentation/storage.md#migrating-from-tprs-to-crds">migrate to CRDs&lt;/a> before you upgrade to a post v2.17 dex. The script mentioned in the instructions can be &lt;a href="https://github.com/dexidp/dex/blob/v2.17.0/scripts/dump-tprs">found here&lt;/a>&lt;/p>
&lt;h3 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The storage configuration is extremely limited since installations running outside a Kubernetes cluster would likely prefer a different storage option. An example configuration for dex running inside Kubernetes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: kubernetes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">inCluster&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Dex determines the namespace it&amp;rsquo;s running in by parsing the service account token automatically mounted into its pod.&lt;/p>
&lt;h2 id="sql">SQL&lt;a class="heading-anchor" href="#sql" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex supports three flavors of SQL: SQLite3, Postgres and MySQL.&lt;/p>
&lt;p>Migrations are performed automatically on the first connection to the SQL server (it does not support rolling back). Because of this dex requires privileges to add and alter the tables for its database.&lt;/p>
&lt;p>&lt;strong>NOTE:&lt;/strong> Previous versions of dex required symmetric keys to encrypt certain values before sending them to the database. This feature has not yet been ported to dex v2. If it is added later there may not be a migration path for current v2 users.&lt;/p>
&lt;h3 id="sqlite3">SQLite3&lt;a class="heading-anchor" href="#sqlite3" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>SQLite3 is the recommended storage for users who want to stand up dex quickly. It is &lt;strong>not&lt;/strong> appropriate for real workloads.&lt;/p>
&lt;p>The SQLite3 configuration takes a single argument, the database file.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: sqlite3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">file&lt;/span>: /var/dex/dex.db
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Because SQLite3 uses file locks to prevent race conditions, if the &amp;ldquo;:memory:&amp;rdquo; value is provided dex will automatically disable support for concurrent database queries.&lt;/p>
&lt;h3 id="postgres">Postgres&lt;a class="heading-anchor" href="#postgres" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>When using Postgres, admins may want to dedicate a database to dex for the following reasons:&lt;/p>
&lt;ol>
&lt;li>Dex requires privileged access to its database because it performs migrations.&lt;/li>
&lt;li>Dex&amp;rsquo;s database table names are not configurable; when shared with other applications there may be table name clashes.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-postgres" data-lang="postgres">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">CREATE&lt;/span> &lt;span style="color:#c678dd">DATABASE&lt;/span> &lt;span style="color:#e06c75">dex_db&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">CREATE&lt;/span> &lt;span style="color:#c678dd">USER&lt;/span> &lt;span style="color:#e06c75">dex&lt;/span> &lt;span style="color:#c678dd">WITH&lt;/span> &lt;span style="color:#c678dd">PASSWORD&lt;/span> &lt;span style="color:#98c379">&amp;#39;66964843358242dbaaa7778d8477c288&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">GRANT&lt;/span> &lt;span style="color:#c678dd">ALL&lt;/span> &lt;span style="color:#c678dd">PRIVILEGES&lt;/span> &lt;span style="color:#c678dd">ON&lt;/span> &lt;span style="color:#c678dd">DATABASE&lt;/span> &lt;span style="color:#e06c75">dex_db&lt;/span> &lt;span style="color:#c678dd">TO&lt;/span> &lt;span style="color:#e06c75">dex&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>An example config for Postgres setup using these values:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: postgres
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">host&lt;/span>: localhost
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">port&lt;/span>: &lt;span style="color:#d19a66">5432&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">database&lt;/span>: dex_db
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">user&lt;/span>: dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">password&lt;/span>: 66964843358242dbaaa7778d8477c288
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">mode&lt;/span>: verify-ca
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">caFile&lt;/span>: /etc/dex/postgres.ca
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The SSL &amp;ldquo;mode&amp;rdquo; corresponds to the &lt;code>github.com/lib/pq&lt;/code> package &lt;a href="https://godoc.org/github.com/lib/pq#hdr-Connection_String_Parameters">connection options&lt;/a>. If unspecified, dex defaults to the strictest mode &amp;ldquo;verify-full&amp;rdquo;.&lt;/p>
&lt;h3 id="mysql">MySQL&lt;a class="heading-anchor" href="#mysql" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Dex requires MySQL 5.7 or later version. When using MySQL, admins may want to dedicate a database to dex for the following reasons:&lt;/p>
&lt;ol>
&lt;li>Dex requires privileged access to its database because it performs migrations.&lt;/li>
&lt;li>Dex&amp;rsquo;s database table names are not configurable; when shared with other applications there may be table name clashes.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">CREATE&lt;/span> &lt;span style="color:#c678dd">DATABASE&lt;/span> &lt;span style="color:#e06c75">dex_db&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">CREATE&lt;/span> &lt;span style="color:#c678dd">USER&lt;/span> &lt;span style="color:#e06c75">dex&lt;/span> &lt;span style="color:#e06c75">IDENTIFIED&lt;/span> &lt;span style="color:#c678dd">BY&lt;/span> &lt;span style="color:#98c379">&amp;#39;66964843358242dbaaa7778d8477c288&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">GRANT&lt;/span> &lt;span style="color:#c678dd">ALL&lt;/span> &lt;span style="color:#c678dd">PRIVILEGES&lt;/span> &lt;span style="color:#c678dd">ON&lt;/span> &lt;span style="color:#e06c75">dex_db&lt;/span>.&lt;span style="color:#56b6c2">*&lt;/span> &lt;span style="color:#c678dd">TO&lt;/span> &lt;span style="color:#e06c75">dex&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>An example config for MySQL setup using these values:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: mysql
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">database&lt;/span>: dex_db
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">user&lt;/span>: dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">password&lt;/span>: 66964843358242dbaaa7778d8477c288
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ssl&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">mode&lt;/span>: custom
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">caFile&lt;/span>: /etc/dex/mysql.ca
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The SSL &amp;ldquo;mode&amp;rdquo; corresponds to the &lt;code>github.com/go-sql-driver/mysql&lt;/code> package &lt;a href="https://github.com/go-sql-driver/mysql#tls">connection options&lt;/a>. If unspecified, dex defaults to the strictest mode &amp;ldquo;true&amp;rdquo;.&lt;/p>
&lt;h2 id="adding-a-new-storage-options">Adding a new storage options&lt;a class="heading-anchor" href="#adding-a-new-storage-options" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Each storage implementation bears a large ongoing maintenance cost and needs to be updated every time a feature requires storing a new type. Bugs often require in depth knowledge of the backing software, and much of this work will be done by developers who are not the original author. Changes to dex which add new storage implementations require a strong use case to be considered for inclusion.&lt;/p>
&lt;h3 id="new-storage-option-references">New storage option references&lt;a class="heading-anchor" href="#new-storage-option-references" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Those who still want to construct a proposal for a new storage should review the following packages:&lt;/p>
&lt;ul>
&lt;li>&lt;code>github.com/dexidp/dex/storage&lt;/code>: Interface definitions which the storage must implement. &lt;strong>NOTE:&lt;/strong> This package is not stable.&lt;/li>
&lt;li>&lt;code>github.com/dexidp/dex/storage/conformance&lt;/code>: Conformance tests which storage implementations must pass.&lt;/li>
&lt;/ul>
&lt;h3 id="new-storage-option-requirements">New storage option requirements&lt;a class="heading-anchor" href="#new-storage-option-requirements" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Any proposal to add a new implementation must address the following:&lt;/p>
&lt;ul>
&lt;li>Integration testing setups (Travis and developer workstations).&lt;/li>
&lt;li>Transactional requirements: atomic deletes, updates, etc.&lt;/li>
&lt;li>Is there an established and reasonable Go client?&lt;/li>
&lt;/ul></description></item><item><title>Docs: OAuth2</title><link>https://dexidp.io/docs/configuration/oauth2/</link><pubDate>Fri, 05 Jan 2024 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/configuration/oauth2/</guid><description>
&lt;p>Dex provides a range of configurable options that empower you to fine-tune and personalize various aspects of the authentication and user flow.&lt;/p>
&lt;h2 id="flow-customization">Flow Customization&lt;a class="heading-anchor" href="#flow-customization" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Customize OAuth2 settings to align with your authentication requirements.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">grantTypes&lt;/span>: [ &lt;span style="color:#98c379">&amp;#34;authorization_code&amp;#34;&lt;/span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">responseTypes&lt;/span>: [ &lt;span style="color:#98c379">&amp;#34;code&amp;#34;&lt;/span> ]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">skipApprovalScreen&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">alwaysShowLoginScreen&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="authentication-flow">Authentication flow&lt;a class="heading-anchor" href="#authentication-flow" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>&lt;code>responseTypes&lt;/code> - allows you to configure the desired auth flow (&lt;code>Authorization Code Flow&lt;/code>, &lt;code>Implicit Flow&lt;/code>, or &lt;code>Hybrid Flow&lt;/code>) based on different values. See the table below for valid configuration options.&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">&lt;code>responseTypes&lt;/code> value&lt;/th>
&lt;th style="text-align: left">flow&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;code>code&lt;/code>&lt;/td>
&lt;td style="text-align: left">Authorization Code Flow&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>id_token&lt;/code>&lt;/td>
&lt;td style="text-align: left">Implicit Flow&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>id_token token&lt;/code>&lt;/td>
&lt;td style="text-align: left">Implicit Flow&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>code id_token&lt;/code>&lt;/td>
&lt;td style="text-align: left">Hybrid Flow&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>code token&lt;/code>&lt;/td>
&lt;td style="text-align: left">Hybrid Flow&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>code id_token token&lt;/code>&lt;/td>
&lt;td style="text-align: left">Hybrid Flow&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">Examples of the different flows and their behavior can be found in the &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationExamples">official openid spec&lt;/a>.&lt;/td>
&lt;td style="text-align: left">&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="user-flow">User flow&lt;a class="heading-anchor" href="#user-flow" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Customizing the user flow allows you to influence how users login into your application.&lt;/p>
&lt;ul>
&lt;li>&lt;code>skipApprovalScreen&lt;/code> - controls the need for user approval before sharing data with connected applications. If enabled, users must approve data sharing with every auth flow.
&lt;div class="alert alert-info" role="alert">
This setting is not applicable when the request has the &lt;code>approval_prompt=force&lt;/code> parameter. In this case, the approval screen is always shown.
&lt;/div>
&lt;/li>
&lt;li>&lt;code>alwaysShowLoginScreen&lt;/code> - whether to always display the login screen. If only one authentication method is enabled, the default behavior is to go directly to it. For connected IdPs, this redirects the browser away from the application to upstream provider, such as the Google login page.&lt;/li>
&lt;/ul>
&lt;h2 id="configurable-grants">Configurable Grants&lt;a class="heading-anchor" href="#configurable-grants" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex supports various OAuth2 and OpenID Connect grant types. You can control which grant types are available by configuring the &lt;code>grantTypes&lt;/code> setting.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">grantTypes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#34;authorization_code&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#34;refresh_token&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#34;urn:ietf:params:oauth:grant-type:token-exchange&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="available-grant-types">Available grant types&lt;a class="heading-anchor" href="#available-grant-types" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The following grant types can be enabled or disabled:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">Grant Type&lt;/th>
&lt;th style="text-align: left">Description&lt;/th>
&lt;th style="text-align: left">Special Configuration&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">&lt;code>authorization_code&lt;/code>&lt;/td>
&lt;td style="text-align: left">Authorization Code Flow - recommended for web and mobile applications&lt;/td>
&lt;td style="text-align: left">-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>refresh_token&lt;/code>&lt;/td>
&lt;td style="text-align: left">Refresh Token Grant - allows clients to obtain new access tokens without user interaction&lt;/td>
&lt;td style="text-align: left">-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>password&lt;/code>&lt;/td>
&lt;td style="text-align: left">Resource Owner Password Credentials Flow - deprecated and less secure&lt;/td>
&lt;td style="text-align: left">&lt;strong>Requires &lt;code>passwordConnector&lt;/code> to be set&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>client_credentials&lt;/code>&lt;/td>
&lt;td style="text-align: left">Client Credentials Flow - for server-to-server communication&lt;/td>
&lt;td style="text-align: left">&lt;strong>Requires feature flag:&lt;/strong> &lt;code>DEX_CLIENT_CREDENTIAL_GRANT_ENABLED_BY_DEFAULT=true&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>urn:ietf:params:oauth:grant-type:token-exchange&lt;/code>&lt;/td>
&lt;td style="text-align: left">Token Exchange Grant (RFC 8693) - allows clients to exchange tokens from external identity providers&lt;/td>
&lt;td style="text-align: left">-&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">&lt;code>urn:ietf:params:oauth:grant-type:device_code&lt;/code>&lt;/td>
&lt;td style="text-align: left">Device Code Grant (RFC 8628) - for devices with limited input capabilities&lt;/td>
&lt;td style="text-align: left">-&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="alert alert-warning" role="alert">
&lt;p>&lt;strong>Important Notes:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Implicit Flow&lt;/strong> is not configured via &lt;code>grantTypes&lt;/code>. Instead, use the &lt;code>responseTypes&lt;/code> setting (see &lt;a href="https://dexidp.io/docs/configuration/oauth2/#authentication-flow">Authentication flow&lt;/a> section above).&lt;/li>
&lt;li>&lt;strong>Password Grant&lt;/strong> will not work unless &lt;code>passwordConnector&lt;/code> is configured (see &lt;a href="https://dexidp.io/docs/configuration/oauth2/#password-grants">Password grants&lt;/a> section below).&lt;/li>
&lt;li>&lt;strong>Client Credentials Grant&lt;/strong> requires the environment variable &lt;code>DEX_CLIENT_CREDENTIAL_GRANT_ENABLED_BY_DEFAULT=true&lt;/code> to be set.&lt;/li>
&lt;/ul>
&lt;/div>
&lt;h3 id="default-behavior">Default behavior&lt;a class="heading-anchor" href="#default-behavior" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>If the &lt;code>grantTypes&lt;/code> field is not specified, Dex enables these default grant types:&lt;/p>
&lt;ul>
&lt;li>&lt;code>authorization_code&lt;/code>&lt;/li>
&lt;li>&lt;code>refresh_token&lt;/code>&lt;/li>
&lt;li>&lt;code>urn:ietf:params:oauth:grant-type:token-exchange&lt;/code>&lt;/li>
&lt;/ul>
&lt;div class="alert alert-info" role="alert">
To use token exchange and device grants, the supported upstream connector must be properly configured. Token exchange works with OIDC connectors, while device code flow requires additional configuration.
&lt;/div>
&lt;h3 id="examples">Examples&lt;a class="heading-anchor" href="#examples" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>&lt;strong>Enable only Authorization Code flow:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">grantTypes&lt;/span>: [ &lt;span style="color:#98c379">&amp;#34;authorization_code&amp;#34;&lt;/span> ]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Enable client credentials grant for server-to-server authentication:&lt;/strong>&lt;/p>
&lt;p>Set the required environment variable, client credentials grant is enabled by default:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">DEX_CLIENT_CREDENTIAL_GRANT_ENABLED_BY_DEFAULT&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Enable password grant (not recommended):&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">passwordConnector&lt;/span>: local &lt;span style="color:#7f848e"># Required for password grant&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Password grants involve clients directly sending a user&amp;rsquo;s credentials (&lt;code>username&lt;/code> and &lt;code>password&lt;/code>) to the authorization server (dex), acquiring access tokens without the need for an intermediate authorization step.&lt;/p>
&lt;p>&lt;strong>Enable Implicit Flow:&lt;/strong>&lt;/p>
&lt;p>Implicit flow is configured via &lt;code>responseTypes&lt;/code>, not &lt;code>grantTypes&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">responseTypes&lt;/span>: [ &lt;span style="color:#98c379">&amp;#34;id_token&amp;#34;&lt;/span>, &lt;span style="color:#98c379">&amp;#34;token&amp;#34;&lt;/span> ]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configuration-options">Configuration options&lt;a class="heading-anchor" href="#configuration-options" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>&lt;code>grantTypes&lt;/code> - list of enabled grant types (see &lt;a href="https://dexidp.io/docs/configuration/oauth2/#configurable-grants">Configurable Grants&lt;/a> section above). To enable password grants, ensure &lt;code>&amp;quot;password&amp;quot;&lt;/code> is included in this list.&lt;/li>
&lt;li>&lt;code>passwordConnector&lt;/code> - specifies the connector&amp;rsquo;s id that is used for password grants&lt;/li>
&lt;/ul>
&lt;div class="alert alert-warning" role="alert">
&lt;h4 class="alert-heading">Warning&lt;/h4>
The password grant type is not recommended for use by the &lt;a href="https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13#section-3.4">OAuth 2.0 Security Best Current Practice&lt;/a> because of serious security concerns.
Please see &lt;a href="https://oauth.net/2/grant-types/password/">oauth.net&lt;/a> for additional information.
&lt;/div></description></item><item><title>Docs: The Dex API</title><link>https://dexidp.io/docs/configuration/api/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/configuration/api/</guid><description>
&lt;p>Dex provides a &lt;a href="http://www.grpc.io/">gRPC&lt;/a> service for programmatic modification of dex&amp;rsquo;s state.
The API is intended to expose hooks for management applications and is not expected to be used by most installations.&lt;/p>
&lt;p>This document is an overview of how to interact with the API.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Admins that wish to expose the gRPC service must add the following entry to the dex config file. This option is off by default.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">grpc&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Cannot be the same address as an HTTP(S) service.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">addr&lt;/span>: &lt;span style="color:#d19a66">127.0.0.1&lt;/span>:&lt;span style="color:#d19a66">5557&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Server certs. If TLS credentials aren&amp;#39;t provided dex will run in plaintext (HTTP) mode.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tlsCert&lt;/span>: /etc/dex/grpc.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tlsKey&lt;/span>: /etc/dex/grpc.key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Client auth CA.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tlsClientCA&lt;/span>: /etc/dex/client.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># enable reflection&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">reflection&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="clients">Clients&lt;a class="heading-anchor" href="#clients" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>gRPC is a suite of tools for generating client and server bindings from a common declarative language.
The canonical schema for Dex&amp;rsquo;s API can be found in the source tree at &lt;a href="https://github.com/dexidp/dex/blob/master/api/v2/api.proto">&lt;code>api/v2/api.proto&lt;/code>&lt;/a>.
Go bindings are generated and maintained in the same directory for both public and internal use.&lt;/p>
&lt;h3 id="go">Go&lt;a class="heading-anchor" href="#go" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>A Go project can import the API module directly, without having to import the entire project:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>go get github.com/dexidp/dex/api/v2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The client then can be used as follows:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">package&lt;/span> &lt;span style="color:#e06c75">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;context&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;github.com/dexidp/dex/api/v2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;google.golang.org/grpc&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#98c379">&amp;#34;google.golang.org/grpc/credentials&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">func&lt;/span> &lt;span style="color:#61afef;font-weight:bold">newDexClient&lt;/span>(&lt;span style="color:#e06c75">hostAndPort&lt;/span>, &lt;span style="color:#e06c75">caPath&lt;/span> &lt;span style="color:#e5c07b">string&lt;/span>) (&lt;span style="color:#e06c75">api&lt;/span>.&lt;span style="color:#e06c75">DexClient&lt;/span>, &lt;span style="color:#e5c07b">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">creds&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">credentials&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">NewClientTLSFromFile&lt;/span>(&lt;span style="color:#e06c75">caPath&lt;/span>, &lt;span style="color:#98c379">&amp;#34;&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span>, &lt;span style="color:#e06c75">fmt&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Errorf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;load dex cert: %v&amp;#34;&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">conn&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">grpc&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Dial&lt;/span>(&lt;span style="color:#e06c75">hostAndPort&lt;/span>, &lt;span style="color:#e06c75">grpc&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">WithTransportCredentials&lt;/span>(&lt;span style="color:#e06c75">creds&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span>, &lt;span style="color:#e06c75">fmt&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Errorf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;dial: %v&amp;#34;&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">return&lt;/span> &lt;span style="color:#e06c75">api&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">NewDexClient&lt;/span>(&lt;span style="color:#e06c75">conn&lt;/span>), &lt;span style="color:#e5c07b">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">func&lt;/span> &lt;span style="color:#61afef;font-weight:bold">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">client&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#61afef;font-weight:bold">newDexClient&lt;/span>(&lt;span style="color:#98c379">&amp;#34;127.0.0.1:5557&amp;#34;&lt;/span>, &lt;span style="color:#98c379">&amp;#34;/etc/dex/grpc.crt&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">log&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Fatalf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;failed creating dex client: %v &amp;#34;&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">req&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">api&lt;/span>.&lt;span style="color:#e06c75">CreateClientReq&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Client&lt;/span>: &lt;span style="color:#56b6c2">&amp;amp;&lt;/span>&lt;span style="color:#e06c75">api&lt;/span>.&lt;span style="color:#e06c75">Client&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Id&lt;/span>: &lt;span style="color:#98c379">&amp;#34;example-app&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Name&lt;/span>: &lt;span style="color:#98c379">&amp;#34;Example App&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">Secret&lt;/span>: &lt;span style="color:#98c379">&amp;#34;ZXhhbXBsZS1hcHAtc2VjcmV0&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">RedirectUris&lt;/span>: []&lt;span style="color:#e5c07b">string&lt;/span>{&lt;span style="color:#98c379">&amp;#34;http://127.0.0.1:5555/callback&amp;#34;&lt;/span>},
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#c678dd">if&lt;/span> &lt;span style="color:#e06c75">_&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">:=&lt;/span> &lt;span style="color:#e06c75">client&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">CreateClient&lt;/span>(&lt;span style="color:#e06c75">context&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">TODO&lt;/span>(), &lt;span style="color:#e06c75">req&lt;/span>); &lt;span style="color:#e06c75">err&lt;/span> &lt;span style="color:#56b6c2">!=&lt;/span> &lt;span style="color:#e5c07b">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">log&lt;/span>.&lt;span style="color:#61afef;font-weight:bold">Fatalf&lt;/span>(&lt;span style="color:#98c379">&amp;#34;failed creating oauth2 client: %v&amp;#34;&lt;/span>, &lt;span style="color:#e06c75">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A clear working example of the Dex gRPC client for Go can be found &lt;a href="https://github.com/dexidp/dex/tree/master/examples/grpc-client/README.md">here&lt;/a>.&lt;/p>
&lt;h3 id="other-languages">Other languages&lt;a class="heading-anchor" href="#other-languages" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>To generate a client for your own project install &lt;a href="https://github.com/google/protobuf/releases">&lt;code>protoc&lt;/code>&lt;/a>,
install a protobuf generator for your project&amp;rsquo;s language, and download the &lt;code>api.proto&lt;/code> file.&lt;/p>
&lt;p>Here is an example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Download api.proto for a given version.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#e06c75">DEX_VERSION&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>v2.24.0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ wget https://raw.githubusercontent.com/dexidp/dex/&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">DEX_VERSION&lt;/span>&lt;span style="color:#98c379">}&lt;/span>/api/v2/api.proto
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Generate the client bindings.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ protoc &lt;span style="color:#56b6c2">[&lt;/span>YOUR LANG PARAMS&lt;span style="color:#56b6c2">]&lt;/span> api.proto
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Client programs can then be written using the generated code.&lt;/p>
&lt;h2 id="authentication-and-access-control">Authentication and access control&lt;a class="heading-anchor" href="#authentication-and-access-control" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The Dex API does not provide any authentication or authorization beyond TLS client auth.&lt;/p>
&lt;p>Projects that wish to add access controls on top of the existing API should build apps which perform such checks.
For example to provide a &amp;ldquo;Change password&amp;rdquo; screen, a client app could use Dex&amp;rsquo;s OpenID Connect flow to authenticate an end user,
then call Dex&amp;rsquo;s API to update that user&amp;rsquo;s password.&lt;/p>
&lt;h2 id="dexctl">dexctl?&lt;a class="heading-anchor" href="#dexctl" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex does not ship with a command line tool for interacting with the API.
Command line tools are useful but hard to version, easy to design poorly,
and expose another interface which can never be changed in the name of compatibility.&lt;/p>
&lt;p>While the Dex team would be open to re-implementing &lt;code>dexctl&lt;/code> for v2 a majority of the work is writing a design document,
not the actual programming effort.&lt;/p>
&lt;h2 id="why-not-rest-or-grpc-gateway">Why not REST or gRPC Gateway?&lt;a class="heading-anchor" href="#why-not-rest-or-grpc-gateway" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Between v1 and v2, Dex switched from REST to gRPC. This largely stemmed from problems generating documentation,
client bindings, and server frameworks that adequately expressed REST semantics.
While &lt;a href="https://github.com/google/apis-client-generator">Google APIs&lt;/a>, &lt;a href="https://openapis.org/">Open API/Swagger&lt;/a>,
and &lt;a href="https://github.com/grpc-ecosystem/grpc-gateway">gRPC Gateway&lt;/a> were evaluated,
they often became clunky when trying to use specific HTTP error codes or complex request bodies.
As a result, v2&amp;rsquo;s API is entirely gRPC.&lt;/p>
&lt;p>Many arguments &lt;em>against&lt;/em> gRPC cite short term convenience rather than production use cases.
Though this is a recognized shortcoming, Dex already implements many features for developer convenience.
For instance, users who wish to manually edit clients during testing can use the &lt;code>staticClients&lt;/code> config field instead of the API.&lt;/p></description></item><item><title>Docs: Kubernetes Authentication Through Dex</title><link>https://dexidp.io/docs/guides/kubernetes/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/guides/kubernetes/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>This document covers setting up the &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens">Kubernetes OpenID Connect token authenticator plugin&lt;/a> with dex.
It also contains a worked example showing how the Dex server can be deployed within Kubernetes.&lt;/p>
&lt;p>Token responses from OpenID Connect providers include a signed JWT called an ID Token. ID Tokens contain names, emails, unique identifiers, and in dex&amp;rsquo;s case, a set of groups that can be used to identify the user. OpenID Connect providers, like dex, publish public keys; the Kubernetes API server understands how to use these to verify ID Tokens.&lt;/p>
&lt;p>The authentication flow looks like:&lt;/p>
&lt;ol>
&lt;li>OAuth2 client logs a user in through dex.&lt;/li>
&lt;li>That client uses the returned ID Token as a bearer token when talking to the Kubernetes API.&lt;/li>
&lt;li>Kubernetes uses dex&amp;rsquo;s public keys to verify the ID Token.&lt;/li>
&lt;li>A claim designated as the username (and optionally group information) will be associated with that request.&lt;/li>
&lt;/ol>
&lt;p>Username and group information can be combined with Kubernetes &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authorization/">authorization plugins&lt;/a>, such as role based access control (RBAC), to enforce policy.&lt;/p>
&lt;h2 id="configuring-kubernetes">Configuring Kubernetes&lt;a class="heading-anchor" href="#configuring-kubernetes" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Things to know before the start:&lt;/p>
&lt;ul>
&lt;li>Dex has to be running on HTTPS.
&lt;ul>
&lt;li>Custom CA files must be accessible by the API server.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Dex must be accessible to both your browser and the Kubernetes API server.&lt;/li>
&lt;li>The API server doesn&amp;rsquo;t require dex to be available upfront.
&lt;ul>
&lt;li>Other authenticators, such as client certs, can still be used.&lt;/li>
&lt;li>Dex doesn&amp;rsquo;t need to be running when you start your API server.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>If a claim other than &amp;ldquo;email&amp;rdquo; is used for the username, for example, &amp;ldquo;sub&amp;rdquo;, it will be prefixed by &lt;code>&amp;quot;issuer-url&amp;quot;&lt;/code>. This is to namespace user-controlled claims which may be used for privilege escalation.&lt;/li>
&lt;li>The &lt;code>/etc/ssl/certs/openid-ca.pem&lt;/code> used here is the CA from the &lt;a href="https://dexidp.io/docs/guides/kubernetes/#generate-tls-assets">generated TLS assets&lt;/a>, and is assumed to be present on the cluster nodes.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Flow:&lt;/strong>&lt;/p>
&lt;p>At the beginning, kube-apiserver will fetch Dex keys to validate signatures of bearer tokens. When there is a bearer token in the request, kube-apiserver:&lt;/p>
&lt;ol>
&lt;li>Checks the token signature.&lt;/li>
&lt;li>Makes an expiration check.&lt;/li>
&lt;li>Validates claims (aud, iss).&lt;/li>
&lt;li>Gets subject attributes from token claims.&lt;/li>
&lt;/ol>
&lt;p>Starting from Kubernetes v1.30.x, there are two options to connect Dex to your Kubernetes cluster:&lt;/p>
&lt;h3 id="using-structuredauthenticationconfiguration">Using StructuredAuthenticationConfiguration&lt;a class="heading-anchor" href="#using-structuredauthenticationconfiguration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>This is a structured configuration file that can be used to set up authenticator that will use Dex to validate incoming bearer tokens. You can find details about all the options and how the authenticator works by following &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#using-authentication-configuration">this link&lt;/a>.&lt;/p>
&lt;p>Steps to connect Dex:&lt;/p>
&lt;ol>
&lt;li>Create a configuration file with the following content:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># apiVersion can ends with the v1 / v1beta1 or v1alpha1 depending on your Kubernetes version&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">apiVersion&lt;/span>: apiserver.config.k8s.io/v1beta1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">kind&lt;/span>: AuthenticationConfiguration
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">jwt&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">issuer&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">url&lt;/span>: https://dex.example.com:32000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">audiences&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - example-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># cat /etc/ssl/certs/openid-ca.pem | base64 -w0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">certificateAuthority&lt;/span>: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">claimMappings&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">claim&lt;/span>: email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">claim&lt;/span>: groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userValidationRules&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">expression&lt;/span>: &lt;span style="color:#98c379">&amp;#34;!user.username.startsWith(&amp;#39;system:&amp;#39;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">message&lt;/span>: &lt;span style="color:#98c379">&amp;#34;username cannot use reserved system: prefix&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>Use the &lt;code>--authentication-config=/path-to-your-config&lt;/code> flag for the &lt;code>kube-apiserver&lt;/code> to apply the config.&lt;/li>
&lt;/ol>
&lt;h3 id="using-the-openid-connect-authenticator">Using the OpenID Connect authenticator&lt;a class="heading-anchor" href="#using-the-openid-connect-authenticator" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Configuring the API server to use the OpenID Connect &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens">authentication plugin&lt;/a> is possible for all Kubernetes versions.&lt;/p>
&lt;p>Use the following flags to point your API server(s) at Dex. &lt;code>dex.example.com&lt;/code> should be replaced by whatever DNS name or IP address Dex is running under.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>--oidc-issuer-url&lt;span style="color:#56b6c2">=&lt;/span>https://dex.example.com:32000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-client-id&lt;span style="color:#56b6c2">=&lt;/span>example-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-ca-file&lt;span style="color:#56b6c2">=&lt;/span>/etc/ssl/certs/openid-ca.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-username-claim&lt;span style="color:#56b6c2">=&lt;/span>email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-groups-claim&lt;span style="color:#56b6c2">=&lt;/span>groups
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Additional notes:&lt;/p>
&lt;ul>
&lt;li>Kubernetes configured with the &lt;code>oidc&lt;/code> flags can only trusts ID Tokens issued to a single client.
&lt;ul>
&lt;li>As a workaround dex allows clients to &lt;a href="https://godoc.org/github.com/dexidp/dex/storage#Client">trust other clients&lt;/a> to mint tokens on their behalf.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="deploying-dex-on-kubernetes">Deploying dex on Kubernetes&lt;a class="heading-anchor" href="#deploying-dex-on-kubernetes" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The dex repo contains scripts for running dex on a Kubernetes cluster with authentication through GitHub. The dex service is exposed using a &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport">node port&lt;/a> on port 32000. This likely requires a custom &lt;code>/etc/hosts&lt;/code> entry pointed at one of the cluster&amp;rsquo;s workers.&lt;/p>
&lt;p>Because dex uses &lt;a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/">CRDs&lt;/a> to store state, no external database is needed. For more details see the &lt;a href="https://dexidp.io/docs/configuration/storage/#kubernetes-custom-resource-definitions-crds">storage documentation&lt;/a>.&lt;/p>
&lt;p>There are many different ways to spin up a Kubernetes development cluster, each with different host requirements and support for API server reconfiguration. At this time, this guide does not have copy-pastable examples, but can recommend the following methods for spinning up a cluster:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/coreos/coreos-kubernetes/">coreos-kubernetes&lt;/a> repo for vagrant and VirtualBox users.&lt;/li>
&lt;li>&lt;a href="https://github.com/coreos/coreos-baremetal/">coreos-baremetal&lt;/a> repo for Linux QEMU/KVM users.&lt;/li>
&lt;/ul>
&lt;p>To run dex on Kubernetes perform the following steps:&lt;/p>
&lt;ol>
&lt;li>Generate TLS assets for dex.&lt;/li>
&lt;li>Spin up a Kubernetes cluster with the appropriate flags and CA volume mount.&lt;/li>
&lt;li>Create secrets for TLS and for your &lt;a href="https://github.com/settings/applications/new">GitHub OAuth2 client credentials&lt;/a>.&lt;/li>
&lt;li>Deploy dex.&lt;/li>
&lt;/ol>
&lt;h3 id="generate-tls-assets">Generate TLS assets&lt;a class="heading-anchor" href="#generate-tls-assets" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Running Dex with HTTPS enabled requires a valid SSL certificate, and the API server needs to trust the certificate of the signing CA using the &lt;code>--oidc-ca-file&lt;/code> flag.&lt;/p>
&lt;p>For our example use case, the TLS assets can be created using the following command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#e5c07b">cd&lt;/span> examples/k8s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ./gencert.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will generate several files under the &lt;code>ssl&lt;/code> directory, the important ones being &lt;code>cert.pem&lt;/code> ,&lt;code>key.pem&lt;/code> and &lt;code>ca.pem&lt;/code>. The generated SSL certificate is for &amp;lsquo;dex.example.com&amp;rsquo;, although you could change this by editing &lt;code>gencert.sh&lt;/code> if required.&lt;/p>
&lt;h3 id="configure-the-api-server">Configure the API server&lt;a class="heading-anchor" href="#configure-the-api-server" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;h4 id="ensure-the-ca-certificate-is-available-to-the-api-server">Ensure the CA certificate is available to the API server&lt;a class="heading-anchor" href="#ensure-the-ca-certificate-is-available-to-the-api-server" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h4>
&lt;p>The CA file which was used to sign the SSL certificates for Dex needs to be copied to a location where the API server can read it, and the API server configured to look for it with the flag &lt;code>--oidc-ca-file&lt;/code>.&lt;/p>
&lt;p>There are several options here but if you run your API server as a container probably the easiest method is to use a &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#hostpath">hostPath&lt;/a> volume to mount the CA file directly from the host.&lt;/p>
&lt;p>The example pod manifest below assumes that you copied the CA file into &lt;code>/etc/ssl/certs&lt;/code>. Adjust as necessary:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">containers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [...]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">volumeMounts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">mountPath&lt;/span>: /etc/ssl/certs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: etc-ssl-certs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">readOnly&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [...]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: ca-certs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">hostPath&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">path&lt;/span>: /etc/ssl/certs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: DirectoryOrCreate
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Depending on your installation you may also find that certain folders are already mounted in this way and that you can simply copy the CA file into an existing folder for the same effect.&lt;/p>
&lt;h4 id="configure-api-server-flags">Configure API server flags&lt;a class="heading-anchor" href="#configure-api-server-flags" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h4>
&lt;p>Configure the API server as in &lt;a href="https://dexidp.io/docs/guides/kubernetes/#configuring-the-openid-connect-plugin">Configuring the OpenID Connect Plugin&lt;/a> above.&lt;/p>
&lt;p>Note that the &lt;code>ca.pem&lt;/code> from above has been renamed to &lt;code>openid-ca.pem&lt;/code> in this example - this is just to separate it from any other CA certificates that may be in use.&lt;/p>
&lt;h3 id="create-cluster-secrets">Create cluster secrets&lt;a class="heading-anchor" href="#create-cluster-secrets" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Once the cluster is up and correctly configured, use kubectl to add the serving certs as secrets.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ kubectl -n dex create secret tls dex.example.com.tls --cert&lt;span style="color:#56b6c2">=&lt;/span>ssl/cert.pem --key&lt;span style="color:#56b6c2">=&lt;/span>ssl/key.pem
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then create a secret for the GitHub OAuth2 client.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ kubectl -n dex create secret &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> generic github-client &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --from-literal&lt;span style="color:#56b6c2">=&lt;/span>client-id&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#e06c75">$GITHUB_CLIENT_ID&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --from-literal&lt;span style="color:#56b6c2">=&lt;/span>client-secret&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#e06c75">$GITHUB_CLIENT_SECRET&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="deploy-the-dex-server">Deploy the Dex server&lt;a class="heading-anchor" href="#deploy-the-dex-server" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Create the dex deployment, configmap, and node port service. This will also create RBAC bindings allowing the Dex pod access to manage &lt;a href="https://dexidp.io/docs/configuration/storage/#kubernetes-custom-resource-definitions-crds">Custom Resource Definitions&lt;/a> within Kubernetes.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ kubectl create -f dex.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="logging-into-the-cluster">Logging into the cluster&lt;a class="heading-anchor" href="#logging-into-the-cluster" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The &lt;code>example-app&lt;/code> can be used to log into the cluster and get an ID Token. To build the app, run the following commands:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">cd&lt;/span> examples/example-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go install .
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To build the &lt;code>example-app&lt;/code> requires at least a 1.7 version of Go.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ example-app --issuer https://dex.example.com:32000 --issuer-root-ca examples/k8s/ssl/ca.pem
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note that the &lt;code>example-app&lt;/code> will listen at http://127.0.0.1:5555 and can be changed with the &lt;code>--listen&lt;/code> flag.&lt;/p>
&lt;p>Once the example app is running, open a browser and go to http://127.0.0.1:5555&lt;/p>
&lt;p>A page appears with fields such as scope and client-id. For the most basic case these are not required, so leave the form blank. Click login.&lt;/p>
&lt;p>On the next page, choose the GitHub option and grant access to dex to view your profile.&lt;/p>
&lt;p>The default redirect uri is http://127.0.0.1:5555/callback and can be changed with the &lt;code>--redirect-uri&lt;/code> flag and should correspond with your configmap.&lt;/p>
&lt;p>Please note the redirect uri is different from the one you filled when creating &lt;code>GitHub OAuth2 client credentials&lt;/code>.
When you login, GitHub first redirects to dex (&lt;a href="https://dex.example.com:32000/callback)">https://dex.example.com:32000/callback)&lt;/a>, then dex redirects to the redirect uri of example-app.&lt;/p>
&lt;p>The printed &amp;ldquo;ID Token&amp;rdquo; can then be used as a bearer token to authenticate against the API server.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#e06c75">token&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#39;(id token)&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ curl -H &lt;span style="color:#98c379">&amp;#34;Authorization: Bearer &lt;/span>&lt;span style="color:#e06c75">$token&lt;/span>&lt;span style="color:#98c379">&amp;#34;&lt;/span> -k https://&lt;span style="color:#56b6c2">(&lt;/span> API server host &lt;span style="color:#56b6c2">)&lt;/span>:443/api/v1/nodes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the kubeconfig file ~/.kube/config, the format is:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">users&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">name&lt;/span>: (USERNAME)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">user&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">token&lt;/span>: (ID-TOKEN)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Machine Authentication to Dex</title><link>https://dexidp.io/docs/guides/token-exchange/</link><pubDate>Sat, 01 Jul 2023 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/guides/token-exchange/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Most Dex connectors redirect users to the upstream identity provider as part of the authentication flow.
While this works for human users,
it is much harder for machines and automated processes (e.g., CI pipelines) to complete this interactive flow.
This is where &lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html">OAuth2 Token Exchange&lt;/a> comes in:
it allows clients to exchange an access or ID token they already have
(obtained from their environment, through custom CLI commands, etc.)
for a token issued by dex.&lt;/p>
&lt;p>This works like &lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation">GCP Workload Identity Federation&lt;/a> and &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html">AWS Web Identity Federation&lt;/a>,
allowing processes running in trusted execution environments that issue OIDC tokens,
such as &lt;a href="https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect">Github Actions&lt;/a>, &lt;a href="https://buildkite.com/docs/agent/v3/cli-oidc">Buildkite&lt;/a>, &lt;a href="https://circleci.com/docs/openid-connect-tokens/">CircleCI&lt;/a>, &lt;a href="https://cloud.google.com/sdk/gcloud/reference/auth/print-access-token">GCP&lt;/a>, and others,
to exchange them for a dex issued token to access protected resources.&lt;/p>
&lt;p>The authentication flow looks like this:&lt;/p>
&lt;ol>
&lt;li>Client independently obtains an access / id token from the upstream IDP.&lt;/li>
&lt;li>Client exchanges the upstream token for a dex access / id token via the token exchange flow.&lt;/li>
&lt;li>Use token to access dex protected resources.&lt;/li>
&lt;li>Repeat these steps when the token expires.&lt;/li>
&lt;/ol>
&lt;h2 id="configuring-dex">Configuring dex&lt;a class="heading-anchor" href="#configuring-dex" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Currently, only the &lt;a href="https://dexidp.io/docs/connectors/oidc/">OIDC Connector&lt;/a> supports token exchanges.
For this flow, &lt;code>clientID&lt;/code>, &lt;code>clientSecret&lt;/code>, and &lt;code>redirectURI&lt;/code> aren&amp;rsquo;t required.
&lt;code>getUserInfo&lt;/code> is required if you want to exchange from access tokens to dex issued tokens.&lt;/p>
&lt;p>As the user performing the token exchange will need the client secret,
we configure the client as a &lt;a href="https://dexidp.io/docs/configuration/custom-scopes-claims-clients/#public-clients">public client&lt;/a>.
If you need to allow humans and machines to authenticate,
consider creating a dedicated public client for token exchange
and using &lt;a href="https://dexidp.io/docs/configuration/custom-scopes-claims-clients/#cross-client-trust-and-authorized-party">cross-client trust&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">issuer&lt;/span>: https://dex.example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: sqlite3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">file&lt;/span>: dex.db
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">web&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">http&lt;/span>: &lt;span style="color:#d19a66">0.0.0.0&lt;/span>:&lt;span style="color:#d19a66">8001&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">grantTypes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># ensure grantTypes includes the token-exchange grant (default)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#34;urn:ietf:params:oauth:grant-type:token-exchange&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: My Upstream
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: oidc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: my-upstream
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The client submitted subject token will be verified against the issuer given here.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">issuer&lt;/span>: https://token.example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Additional scopes in token response, supported list at:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># https://dexidp.io/docs/custom-scopes-claims-clients/#scopes&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">scopes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - federated:id
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># mapping of fields from the submitted token&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userNameKey&lt;/span>: sub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Access tokens are generally considered opaque.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># We check their validity by calling the user info endpoint if it&amp;#39;s supported.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># getUserInfo: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># dex issued tokens are bound to clients.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For the token exchange flow, the client id and secret pair must be submitted as the username:password&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># via Basic Authentication.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: My App
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: my-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: my-secret
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># We set public to indicate we don&amp;#39;t intend to keep the client secret actually secret.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># https://dexidp.io/docs/configuration/custom-scopes-claims-clients/#public-clients&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">public&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="performing-a-token-exchange">Performing a token exchange&lt;a class="heading-anchor" href="#performing-a-token-exchange" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>To exchange an upstream IDP token for a dex issued token,
perform an &lt;code>application/x-www-form-urlencoded&lt;/code> &lt;code>POST&lt;/code> request
to dex&amp;rsquo;s &lt;code>/token&lt;/code> endpoint following &lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#name-request">RFC 8693 Section 2.1&lt;/a>.
Additionally, dex requires the connector to be specified with the &lt;code>connector_id&lt;/code> parameter
and a client id/secret to be included as the username/password via Basic Authentication.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sh" data-lang="sh">&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">UPSTREAM_TOKEN&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#c678dd">$(&lt;/span>&lt;span style="color:#7f848e"># get a token from the upstream IDP)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ curl https://dex.example.com/token &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --user my-app:my-secret &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --data-urlencode &lt;span style="color:#e06c75">connector_id&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>my-upstream &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --data-urlencode &lt;span style="color:#e06c75">grant_type&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>urn:ietf:params:oauth:grant-type:token-exchange &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --data-urlencode &lt;span style="color:#e06c75">scope&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#34;openid groups federated:id&amp;#34;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --data-urlencode &lt;span style="color:#e06c75">requested_token_type&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>urn:ietf:params:oauth:token-type:access_token &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --data-urlencode &lt;span style="color:#e06c75">subject_token&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#e06c75">$UPSTREAM_TOKEN&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --data-urlencode &lt;span style="color:#e06c75">subject_token_type&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>urn:ietf:params:oauth:token-type:access_token
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Below is an example of a successful response.
Note that regardless of the &lt;code>requested_token_type&lt;/code>,
the token will always be in the &lt;code>access_token&lt;/code> field,
with the type indicated by the &lt;code>issued_token_type&lt;/code> field.
See &lt;a href="https://www.rfc-editor.org/rfc/rfc8693.html#name-successful-response">RFC 8693 Section 2.2.1&lt;/a> for details.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;access_token&amp;#34;&lt;/span>:&lt;span style="color:#98c379">&amp;#34;eyJhbGciOi....aU5oA&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;issued_token_type&amp;#34;&lt;/span>:&lt;span style="color:#98c379">&amp;#34;urn:ietf:params:oauth:token-type:access_token&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;token_type&amp;#34;&lt;/span>:&lt;span style="color:#98c379">&amp;#34;bearer&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">&amp;#34;expires_in&amp;#34;&lt;/span>:&lt;span style="color:#d19a66">86399&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="full-example-with-github-actions">Full example with GitHub Actions&lt;a class="heading-anchor" href="#full-example-with-github-actions" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Here is an example of running dex as a service during a Github Actions workflow
and getting an access token from it, exchanged from a Github Actions OIDC token.&lt;/p>
&lt;p>Dex config:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">issuer&lt;/span>: http://127.0.0.1:5556/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: sqlite3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">file&lt;/span>: dex.db
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">web&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">http&lt;/span>: &lt;span style="color:#d19a66">0.0.0.0&lt;/span>:&lt;span style="color:#d19a66">8080&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: oidc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: github-actions
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: github-actions
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">issuer&lt;/span>: https://token.actions.githubusercontent.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">scopes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - openid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userNameKey&lt;/span>: sub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: My app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: my-app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: my-secret
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">public&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Github actions workflow.
Replace the service image with one that has the config included.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">name&lt;/span>: workflow1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">on&lt;/span>: [push]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">permissions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id-token&lt;/span>: write &lt;span style="color:#7f848e"># This is required for requesting the JWT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">jobs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">job&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">runs-on&lt;/span>: ubuntu-latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">dex&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># replace with an image that has the config above&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">image&lt;/span>: ghcr.io/dexidp/dex:latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#d19a66">80&lt;/span>:&lt;span style="color:#d19a66">8080&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">steps&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Actions have access to two special environment variables ACTIONS_CACHE_URL and ACTIONS_RUNTIME_TOKEN.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Inline step scripts in workflows do not see these variables.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">uses&lt;/span>: actions/github-script@v6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: script
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">timeout-minutes&lt;/span>: &lt;span style="color:#d19a66">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">with&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">debug&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">script&lt;/span>: |&lt;span style="color:#98c379">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> const token = process.env[&amp;#39;ACTIONS_RUNTIME_TOKEN&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> const runtimeUrl = process.env[&amp;#39;ACTIONS_ID_TOKEN_REQUEST_URL&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> core.setOutput(&amp;#39;TOKEN&amp;#39;, token.trim())
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> core.setOutput(&amp;#39;IDTOKENURL&amp;#39;, runtimeUrl.trim())&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">run&lt;/span>: |&lt;span style="color:#98c379">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> # get an token from github
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> GH_TOKEN_RESPONSE=$(curl \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> &amp;#34;${{steps.script.outputs.IDTOKENURL}}&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> -H &amp;#34;Authorization: bearer ${{steps.script.outputs.TOKEN}}&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> -H &amp;#34;Accept: application/json; api-version=2.0&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> -H &amp;#34;Content-Type: application/json&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> -d &amp;#34;{}&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> )
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> GH_TOKEN=$(jq -r .value &amp;lt;&amp;lt;&amp;lt; $GH_TOKEN_RESPONSE)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> # exchange it for a dex token
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> DEX_TOKEN_RESPONSE=$(curl \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> http://127.0.0.1/token \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --user my-app:my-secret \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --data-urlencode &amp;#34;connector_id=github-actions&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --data-urlencode &amp;#34;grant_type=urn:ietf:params:oauth:grant-type:token-exchange&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --data-urlencode &amp;#34;scope=openid groups federated:id&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --data-urlencode &amp;#34;requested_token_type=urn:ietf:params:oauth:token-type:access_token&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --data-urlencode &amp;#34;subject_token=$GH_TOKEN&amp;#34; \
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> --data-urlencode &amp;#34;subject_token_type=urn:ietf:params:oauth:token-type:access_token&amp;#34;)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> DEX_TOKEN=$(jq -r .access_token &amp;lt;&amp;lt;&amp;lt; $DEX_TOKEN_RESPONSE)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379"> # use $DEX_TOKEN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: idtoken
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Customizing Dex Templates</title><link>https://dexidp.io/docs/guides/templates/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/guides/templates/</guid><description>
&lt;h2 id="using-your-own-templates">Using your own templates&lt;a class="heading-anchor" href="#using-your-own-templates" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex supports using your own templates and passing arbitrary data to them to help customize your installation.&lt;/p>
&lt;p>Steps:&lt;/p>
&lt;ol>
&lt;li>Copy contents of the &lt;code>web&lt;/code> directory over to a new directory.&lt;/li>
&lt;li>Customize the templates as needed, be sure to retain all the existing variables so Dex continues working correctly.
(Use the following syntax to render values from &lt;code>frontend.extra&lt;/code> config: &lt;code>{{ &amp;quot;your_key&amp;quot; | extra }}&lt;/code>)&lt;/li>
&lt;li>Set the &lt;code>frontend.dir&lt;/code> value to your own &lt;code>web&lt;/code> directory (Alternatively, you can set the &lt;code>DEX_FRONTEND_DIR&lt;/code> environment variable).&lt;/li>
&lt;li>Add your custom data to the Dex configuration &lt;code>frontend.extra&lt;/code>. (optional)&lt;/li>
&lt;li>Change the issuer by setting the &lt;code>frontend.issuer&lt;/code> config in order to modify the Dex title and the &lt;code>Log in to &amp;lt;&amp;lt;dex&amp;gt;&amp;gt;&lt;/code> tag. (optional)&lt;/li>
&lt;li>Create a custom theme for your templates in the &lt;code>themes&lt;/code> directory. (optional)&lt;/li>
&lt;/ol>
&lt;p>Here is an example configuration:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">frontend&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">dir&lt;/span>: /path/to/custom/web
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">issuer&lt;/span>: my-dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">extra&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tos_footer_link&lt;/span>: &lt;span style="color:#98c379">&amp;#34;https://example.com/terms&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">client_logo_url&lt;/span>: &lt;span style="color:#98c379">&amp;#34;../theme/client-logo.png&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">foo&lt;/span>: &lt;span style="color:#98c379">&amp;#34;bar&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To test your templates simply run Dex with a valid configuration and go through a login flow.&lt;/p>
&lt;h2 id="customize-the-official-container-image">Customize the official container image&lt;a class="heading-anchor" href="#customize-the-official-container-image" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex is primarily distributed as a container image.
The above guide explains how to customize the templates for any Dex instance.&lt;/p>
&lt;p>You can combine that with a custom &lt;code>Dockerfile&lt;/code> to ease the deployment of those custom templates:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">FROM&lt;/span>&lt;span style="color:#98c379"> ghcr.io/dexidp/dex:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">ENV&lt;/span> &lt;span style="color:#e06c75">DEX_FRONTEND_DIR&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>/srv/dex/web
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#c678dd">COPY&lt;/span> --chown&lt;span style="color:#56b6c2">=&lt;/span>root:root web /srv/dex/web
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Using the snippet above, you can avoid setting the &lt;code>frontend.dir&lt;/code> config.&lt;/p></description></item><item><title>Docs: Integrations</title><link>https://dexidp.io/docs/archive/integrations/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/archive/integrations/</guid><description>
&lt;p>This document tracks the libraries and tools that are compatible with dex. &lt;a href="https://github.com/dexidp/dex/">Join the community&lt;/a>, and help us keep the list up-to-date.&lt;/p>
&lt;h2 id="tools">Tools&lt;a class="heading-anchor" href="#tools" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;h2 id="projects-with-a-dex-dependency">Projects with a dex dependency&lt;a class="heading-anchor" href="#projects-with-a-dex-dependency" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2></description></item><item><title>Docs: OpenID Connect Provider Certification</title><link>https://dexidp.io/docs/development/oidc-certification/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/development/oidc-certification/</guid><description>
&lt;p>The OpenID Foundation provides a set of &lt;a href="https://openid.net/wordpress-content/uploads/2018/06/OpenID-Connect-Conformance-Profiles.pdf">conformance test profiles&lt;/a> that test both Relying Party (RP)
and OpenID Provider (OP) OpenID Connect implementations.
Upon submission of &lt;a href="https://openid.net/certification/submission/">results&lt;/a> and an affirmative response,
the affirmed OP will be listed as a &lt;a href="https://openid.net/developers/certified/">certified OP&lt;/a> on the OpenID Connect website
and allowed to use the &lt;a href="https://openid.net/certification/mark/">certification mark&lt;/a> according to the certification &lt;a href="https://openid.net/wordpress-content/uploads/2015/03/OpenID-Certification-Terms-and-Conditions.pdf">terms and conditions&lt;/a>, section 3(d).&lt;/p>
&lt;p>Further details about the certification are available on the &lt;a href="https://openid.net/certification/instructions/">OpenID Connect website&lt;/a>.&lt;/p>
&lt;h2 id="basic-openid-provider-profile">Basic OpenID Provider profile&lt;a class="heading-anchor" href="#basic-openid-provider-profile" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex is an OP that strives to implement the &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI">mandatory set&lt;/a> of OpenID Connect features,
and can be tested against the Basic OpenID Provider profile (&lt;a href="https://openid.net/wordpress-content/uploads/2018/06/OpenID-Connect-Conformance-Profiles.pdf">profile outline&lt;/a>, section 2.1.1).
These tests ensure that all features required by a &lt;a href="https://openid.net/specs/openid-connect-basic-1_0.html">basic client&lt;/a> work as expected.&lt;/p>
&lt;p>Unfortunately, Dex currently does not fully comply with the Basic profile at the moment.&lt;/p>
&lt;p>The progress for getting Dex certified can be tracked here: &lt;a href="https://github.com/orgs/dexidp/projects/3/views/1">https://github.com/orgs/dexidp/projects/3/views/1&lt;/a>&lt;/p>
&lt;h3 id="configuring-dex">Configuring Dex&lt;a class="heading-anchor" href="#configuring-dex" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The Basic OP test suite doesn&amp;rsquo;t require extensive configuration from Dex.
The suite needs the following:&lt;/p>
&lt;ul>
&lt;li>A public issuer URL&lt;/li>
&lt;li>At least two separate clients (with redirect URIs pointing to &lt;code>https://www.certification.openid.net/test/a/YOUR_ALIAS/callback&lt;/code>).&lt;/li>
&lt;/ul>
&lt;p>&lt;code>YOUR_ALIAS&lt;/code> is an arbitrary string that MUST be unique to avoid interference with other test runs.&lt;/p>
&lt;p>The easiest way to run a public Dex instance is running one locally and exposing it using a &lt;a href="https://github.com/anderspitman/awesome-tunneling">tunnel&lt;/a>.&lt;/p>
&lt;p>The following instructions use &lt;a href="https://tunnelto.dev/">tunnelto.dev&lt;/a>.&lt;/p>
&lt;p>Here is a minimal configuration example for running Dex:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">issuer&lt;/span>: https://dex.tunnelto.dev/dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">type&lt;/span>: memory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">web&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">http&lt;/span>: &lt;span style="color:#d19a66">0.0.0.0&lt;/span>:&lt;span style="color:#d19a66">5556&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Automate some clicking&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Note: this might actually make some tests pass that otherwise wouldn&amp;#39;t.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">skipApprovalScreen&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Note: this might actually make some tests pass that otherwise wouldn&amp;#39;t.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: mockCallback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: mock
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Example
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Basic OP test suite requires two clients.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">id&lt;/span>: first_client
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: 89d6205220381728e85c4cf5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - https://www.certification.openid.net/test/a/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: First client
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">id&lt;/span>: second_client
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: 51c612288018fd384b05d6ad
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - https://www.certification.openid.net/test/a/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Second client
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Save it in a file (eg. &lt;code>config.yaml&lt;/code>) then launch Dex:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>dex serve config.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then launch the tunnel:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>tunnelto --subdomain dex --port &lt;span style="color:#d19a66">5556&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can verify Dex running by checking the discovery endpoint:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>curl https://dex.tunnelto.dev/dex/.well-known/openid-configuration
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="running-tests">Running tests&lt;a class="heading-anchor" href="#running-tests" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;ol>
&lt;li>Open &lt;a href="https://www.certification.openid.net/">https://www.certification.openid.net/&lt;/a> in your browser&lt;/li>
&lt;li>Login with your Google or GitLab account&lt;/li>
&lt;li>Click &lt;em>Create a new test plan&lt;/em>&lt;/li>
&lt;li>Select &lt;em>OpenID Connect Core: Basic Certification Profile Authorization server test&lt;/em> as the test plan&lt;/li>
&lt;li>&lt;em>Server metadata location&lt;/em> should be &lt;strong>discovery&lt;/strong>&lt;/li>
&lt;li>&lt;em>Client registration type&lt;/em> should be &lt;strong>static_client&lt;/strong>&lt;/li>
&lt;li>Choose an alias (that you used in the redirect URIs above)&lt;/li>
&lt;li>Enter the discovery URL&lt;/li>
&lt;li>Enter the first client details in the &lt;em>Client&lt;/em> and &lt;em>Second client&lt;/em> sections&lt;/li>
&lt;li>Enter the second client details in the &lt;em>Client for client_secret_post&lt;/em> section&lt;/li>
&lt;li>Hit &lt;em>Create test plan&lt;/em>&lt;/li>
&lt;li>Run through each test case, following all instructions given by individual cases.
&lt;ul>
&lt;li>In order to pass certain cases, screenshots of OP responses might be required.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="last-results">Last results&lt;a class="heading-anchor" href="#last-results" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Dex does not fully pass the Basic profile test suite yet. The following table contains the current state of test results.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: left">Test Name&lt;/th>
&lt;th style="text-align: left">Status&lt;/th>
&lt;th style="text-align: left">Result&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: left">oidcc-server&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-response-type-missing&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-userinfo-get&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-userinfo-post-header&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-userinfo-post-body&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-request-without-nonce-succeeds-for-code-flow&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-scope-profile&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-scope-email&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-scope-address&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">SKIPPED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-scope-phone&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">SKIPPED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-scope-all&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">SKIPPED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-other-scope-order-succeeds&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-display-page&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-display-popup&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-prompt-login&lt;/td>
&lt;td style="text-align: left">INTERRUPTED&lt;/td>
&lt;td style="text-align: left">UNKNOWN&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-prompt-none-not-logged-in&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">FAILED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-prompt-none-logged-in&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-max-age-1&lt;/td>
&lt;td style="text-align: left">INTERRUPTED&lt;/td>
&lt;td style="text-align: left">FAILED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-max-age-10000&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">FAILED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-request-with-unknown-parameter-succeeds&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-id-token-hint&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-login-hint&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ui-locales&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-claims-locales&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-request-with-acr-values-succeeds&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-codereuse&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-codereuse-30seconds&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-registered-redirect-uri&lt;/td>
&lt;td style="text-align: left">INTERRUPTED&lt;/td>
&lt;td style="text-align: left">REVIEW&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-server-client-secret-post&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-unsigned-request-object-supported-correctly-or-rejected-as-unsupported&lt;/td>
&lt;td style="text-align: left">INTERRUPTED&lt;/td>
&lt;td style="text-align: left">UNKNOWN&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-claims-essential&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">WARNING&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-request-object-with-redirect-uri&lt;/td>
&lt;td style="text-align: left">INTERRUPTED&lt;/td>
&lt;td style="text-align: left">UNKNOWN&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-refresh-token&lt;/td>
&lt;td style="text-align: left">INTERRUPTED&lt;/td>
&lt;td style="text-align: left">FAILED&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: left">oidcc-ensure-request-with-valid-pkce-succeeds&lt;/td>
&lt;td style="text-align: left">FINISHED&lt;/td>
&lt;td style="text-align: left">PASSED&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>TODO: find a better place for test results.&lt;/p>
&lt;/blockquote></description></item><item><title>Docs: Authentication Through LDAP</title><link>https://dexidp.io/docs/connectors/ldap/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/ldap/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The LDAP connector allows email/password based authentication, backed by a LDAP directory.&lt;/p>
&lt;p>The connector executes two primary queries:&lt;/p>
&lt;ol>
&lt;li>Finding the user based on the end user&amp;rsquo;s credentials.&lt;/li>
&lt;li>Searching for groups using the user entry.&lt;/li>
&lt;/ol>
&lt;h2 id="getting-started">Getting started&lt;a class="heading-anchor" href="#getting-started" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The dex repo contains a basic LDAP setup using &lt;a href="https://www.openldap.org/">OpenLDAP&lt;/a>.&lt;/p>
&lt;p>First start the LDAP server using docker-compose. This will run the OpenLDAP daemon in a Docker container, and seed it with an initial set of users.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">cd&lt;/span> examples/ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker-compose up
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This container is expected to print several warning messages which are normal. Once the server is up, run dex in another terminal.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./bin/dex serve examples/ldap/config-ldap.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then run the OAuth client in another terminal.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./bin/example-app
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Go to &lt;a href="http://localhost:5555">http://localhost:5555&lt;/a>, login and enter the username and password of the LDAP user: &lt;code>janedoe@example.com&lt;/code>/&lt;code>foo&lt;/code>. Add the &amp;ldquo;groups&amp;rdquo; scope as part of the initial redirect to add group information from the LDAP server.&lt;/p>
&lt;h2 id="security-considerations">Security considerations&lt;a class="heading-anchor" href="#security-considerations" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex attempts to bind with the backing LDAP server using the end user&amp;rsquo;s &lt;em>plain text password&lt;/em>. Though some LDAP implementations allow passing hashed passwords, dex doesn&amp;rsquo;t support hashing and instead &lt;em>strongly recommends that all administrators just use TLS&lt;/em>. This can often be achieved by using port 636 instead of 389, and administrators that choose 389 are actively leaking passwords.&lt;/p>
&lt;p>Dex currently allows insecure connections because the project is still verifying that dex works with the wide variety of LDAP implementations. However, dex may remove this transport option, and &lt;em>users who configure LDAP login using 389 are not covered by any compatibility guarantees with future releases.&lt;/em>&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>User entries are expected to have an email attribute (configurable through &lt;code>emailAttr&lt;/code>), and a display name attribute (configurable through &lt;code>nameAttr&lt;/code>). &lt;code>*Attr&lt;/code> attributes could be set to &amp;ldquo;DN&amp;rdquo; in situations where it is needed but not available elsewhere, and if &amp;ldquo;DN&amp;rdquo; attribute does not exist in the record.&lt;/p>
&lt;p>For the purposes of configuring this connector, &amp;ldquo;DN&amp;rdquo; is case-sensitive and should always be capitalised.&lt;/p>
&lt;p>The following is an example config file that can be used by the LDAP connector to authenticate a user.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: LDAP
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Host and optional port of the LDAP server in the form &amp;#34;host:port&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If the port is not supplied, it will be guessed based on &amp;#34;insecureNoSSL&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># and &amp;#34;startTLS&amp;#34; flags. 389 for insecure or StartTLS connections, 636&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># otherwise.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">host&lt;/span>: ldap.example.com:636
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Following field is required if the LDAP host is not using TLS (port 389).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Because this option inherently leaks passwords to anyone on the same network&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># as dex, THIS OPTION MAY BE REMOVED WITHOUT WARNING IN A FUTURE RELEASE.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureNoSSL: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If a custom certificate isn&amp;#39;t provide, this option can be used to turn on&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># TLS certificate checks. As noted, it is insecure and shouldn&amp;#39;t be used outside&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># of explorative phases.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureSkipVerify: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># When connecting to the server, connect using the ldap:// protocol then issue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># a StartTLS command. If unspecified, connections will use the ldaps:// protocol&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># startTLS: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Path to a trusted root certificate file. Default: use the host&amp;#39;s root CA.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">rootCA&lt;/span>: /etc/dex/ldap.ca
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># A raw certificate file can also be provided inline.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># rootCAData: ( base64 encoded PEM file )&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The DN and password for an application service account. The connector uses&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># these credentials to search for users and groups. Not required if the LDAP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># server provides access for anonymous auth.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Please note that if the bind password contains a `$`, it has to be saved in an&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># environment variable which should be given as the value to `bindPW`.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">bindDN&lt;/span>: uid=serviceaccount,cn=users,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">bindPW&lt;/span>: password
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The attribute to display in the provided password prompt. If unset, will&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># display &amp;#34;Username&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">usernamePrompt&lt;/span>: SSO Username
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># User search maps a username and password entered by a user to a LDAP entry.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># BaseDN to start the search from. It will translate to the query&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># &amp;#34;(&amp;amp;(objectClass=person)(uid=&amp;lt;username&amp;gt;))&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=users,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional filter to apply when searching the directory.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=person)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># username attribute used for comparing user entries. This will be translated&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># and combined with the other filter as &amp;#34;(&amp;lt;attr&amp;gt;=&amp;lt;username&amp;gt;)&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The following three fields are direct mappings of attributes on the user entry.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># String representation of the user.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">idAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required. Attribute to map to Email.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: mail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Maps to display name of users. No default value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Maps to preferred username of users. No default value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">preferredUsernameAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Group search queries for groups given a user entry.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># BaseDN to start the search from. It will translate to the query&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># &amp;#34;(&amp;amp;(objectClass=group)(member=&amp;lt;user uid&amp;gt;))&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=groups,dc=freeipa,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional filter to apply when searching the directory.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=group)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Following list contains field pairs that are used to match a user to a group. It adds an additional&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># requirement to the filter that an attribute in the group must match the user&amp;#39;s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># attribute value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Represents group name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The LDAP connector first initializes a connection to the LDAP directory using the &lt;code>bindDN&lt;/code> and &lt;code>bindPW&lt;/code>. It then tries to search for the given &lt;code>username&lt;/code> and bind as that user to verify their password.
Searches that return multiple entries are considered ambiguous and will return an error.&lt;/p>
&lt;h2 id="example-mapping-a-schema-to-a-search-config">Example: Mapping a schema to a search config&lt;a class="heading-anchor" href="#example-mapping-a-schema-to-a-search-config" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Writing a search configuration often involves mapping an existing LDAP schema to the various options dex provides. To query an existing LDAP schema install the OpenLDAP tool &lt;code>ldapsearch&lt;/code>. For &lt;code>rpm&lt;/code> based distros run:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo dnf install openldap-clients
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For &lt;code>apt-get&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo apt-get install ldap-utils
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For smaller user directories it may be practical to dump the entire contents and search by hand.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ldapsearch -x -H ldap://ldap.example.org -b &lt;span style="color:#98c379">&amp;#39;dc=example,dc=org&amp;#39;&lt;/span> | less
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>First, find a user entry. User entries declare users who can login to LDAP connector using username and password.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">uid&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>jdoe,cn&lt;span style="color:#56b6c2">=&lt;/span>users,cn&lt;span style="color:#56b6c2">=&lt;/span>compat,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cn: Jane Doe
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: posixAccount
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: ipaOverrideTarget
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: top
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gidNumber: &lt;span style="color:#d19a66">200015&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gecos: Jane Doe
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>uidNumber: &lt;span style="color:#d19a66">200015&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>loginShell: /bin/bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>homeDirectory: /home/jdoe
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mail: jane.doe@example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>uid: janedoe
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Compose a user search which returns this user.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">userSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The directory directly above the user entry.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=users,cn=compat,dc=example,dc=org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=posixAccount)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Expect user to enter &amp;#34;janedoe&amp;#34; when logging in.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Use the full DN as an ID.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">idAttr&lt;/span>: DN
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># When an email address is not available, use another value unique to the user, like uid.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: mail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: gecos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Second, find a group entry.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">cn&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>developers,cn&lt;span style="color:#56b6c2">=&lt;/span>groups,cn&lt;span style="color:#56b6c2">=&lt;/span>compat,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>memberUid: janedoe
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>memberUid: johndoe
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gidNumber: &lt;span style="color:#d19a66">200115&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: posixGroup
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: ipaOverrideTarget
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: top
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cn: developers
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Group searches must match a user attribute to a group attribute. In this example, the search returns users whose uid is found in the group&amp;rsquo;s list of memberUid attributes.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The directory directly above the group entry.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=groups,cn=compat,dc=example,dc=org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=posixGroup)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The group search needs to match the &amp;#34;uid&amp;#34; attribute on&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># the user with the &amp;#34;memberUid&amp;#34; attribute on the group.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: memberUid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Unique name of the group.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: cn
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To extract group specific information the &lt;code>DN&lt;/code> can be used in the &lt;code>userAttr&lt;/code> field.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Top level object example.coma in LDIF file.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">dc&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: top
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: dcObject
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: organization
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dc: example
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The following is an example of a group query would match any entry with member=&lt;user DN>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># BaseDN to start the search from. It will translate to the query&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># &amp;#34;(&amp;amp;(objectClass=group)(member=&amp;lt;user DN&amp;gt;))&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=groups,cn=compat,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional filter to apply when searching the directory.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=group)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: DN &lt;span style="color:#7f848e"># Use &amp;#34;DN&amp;#34; here not &amp;#34;uid&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>There are cases when different types (objectClass) of groups use different attributes to keep a list of members. Below is an example of group query for such case:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=groups,cn=compat,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional filter to search for different group types&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(|(objectClass=posixGroup)(objectClass=group))&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Use multiple user matchers so Dex will know which attribute names should be used to search for group members&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: memberUid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: DN
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="example-searching-a-freeipa-server-with-groups">Example: Searching a FreeIPA server with groups&lt;a class="heading-anchor" href="#example-searching-a-freeipa-server-with-groups" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The following configuration will allow the LDAP connector to search a FreeIPA directory using an LDAP filter.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: LDAP
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># host and port of the LDAP server in form &amp;#34;host:port&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">host&lt;/span>: freeipa.example.com:636
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># freeIPA server&amp;#39;s CA&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">rootCA&lt;/span>: ca.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Would translate to the query &amp;#34;(&amp;amp;(objectClass=posixAccount)(uid=&amp;lt;username&amp;gt;))&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=users,dc=freeipa,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=posixAccount)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">idAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required. Attribute to map to Email.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: mail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Entity attribute to map to display name of users.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Would translate to the query &amp;#34;(&amp;amp;(objectClass=group)(member=&amp;lt;user uid&amp;gt;))&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=groups,dc=freeipa,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=group)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If the search finds an entry, it will attempt to use the provided password to bind as that user entry.&lt;/p>
&lt;h2 id="example-searching-a-active-directory-server-with-groups">Example: Searching a Active Directory server with groups&lt;a class="heading-anchor" href="#example-searching-a-active-directory-server-with-groups" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The following configuration will allow the LDAP connector to search a Active Directory using an LDAP filter.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: ActiveDirectory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: ad
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">host&lt;/span>: ad.example.com:636
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">insecureNoSSL&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">insecureSkipVerify&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">bindDN&lt;/span>: cn=Administrator,cn=users,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">bindPW&lt;/span>: admin0!
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">usernamePrompt&lt;/span>: Email Address
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=Users,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=person)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>: userPrincipalName
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">idAttr&lt;/span>: DN
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: userPrincipalName
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: cn
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=Users,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=group)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: DN
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: cn
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="example-searching-a-freeipa-server-for-nested-groups">Example: Searching a FreeIPA server for nested groups&lt;a class="heading-anchor" href="#example-searching-a-freeipa-server-for-nested-groups" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Some LDAP schemas support group nesting, where groups can contain other groups. Dex supports resolving these indirect group memberships using the &lt;code>recursionGroupAttr&lt;/code> attribute within the &lt;code>groupSearch.userMatchers&lt;/code> block. By defining this attribute, recursive group lookup will be enabled.&lt;/p>
&lt;p>You might want to use this if, for example, John is a member of the group &lt;code>seniorAdmins&lt;/code>, and &lt;code>seniorAdmins&lt;/code> is itself a member of the group &lt;code>admins&lt;/code>. With recursive search enabled, John will be treated as a member of both &lt;code>seniorAdmins&lt;/code> and &lt;code>admins&lt;/code>, even though he’s only directly assigned to &lt;code>seniorAdmins&lt;/code>.&lt;/p>
&lt;p>The following is a &lt;code>groupsearch&lt;/code> configuration that enables this functionality.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">groupSearch&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseDN&lt;/span>: cn=groups,dc=freeipa,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">filter&lt;/span>: &lt;span style="color:#98c379">&amp;#34;(objectClass=group)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userMatchers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">userAttr&lt;/span>: uid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">recursionGroupAttr&lt;/span>: member
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this example:&lt;/p>
&lt;ol>
&lt;li>Dex looks for groups where the &lt;code>member&lt;/code> attribute matches the user&amp;rsquo;s &lt;code>uid&lt;/code>.&lt;/li>
&lt;li>Groups can also list other groups in the same &lt;code>member&lt;/code> attribute, allowing nesting.&lt;/li>
&lt;li>By specifying &lt;code>recursionGroupAttr&lt;/code>, Dex will recursively search for parent groups that contain the matched groups. This attribute tells Dex which field to follow when tracing nested group links.&lt;/li>
&lt;li>If &lt;code>recursionGroupAttr&lt;/code> is not set, Dex performs only a single-level group lookup.&lt;/li>
&lt;/ol>
&lt;p>Dex includes built-in cycle detection to prevent infinite loops if group references form a cycle.&lt;/p></description></item><item><title>Docs: Authentication Through GitHub</title><link>https://dexidp.io/docs/connectors/github/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/github/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>One of the login options for dex uses the GitHub OAuth2 flow to identify the end user through their GitHub account.&lt;/p>
&lt;p>When a client redeems a refresh token through dex, dex will re-query GitHub to update user information in the ID Token. To do this, &lt;strong>dex stores a readonly GitHub access token in its backing datastore.&lt;/strong> Users that reject dex&amp;rsquo;s access through GitHub will also revoke all dex clients which authenticated them through GitHub.&lt;/p>
&lt;h2 id="caveats">Caveats&lt;a class="heading-anchor" href="#caveats" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>A user must explicitly &lt;a href="https://help.github.com/articles/requesting-organization-approval-for-oauth-apps/">request&lt;/a> an &lt;a href="https://developer.github.com/v3/orgs/">organization&lt;/a> give dex &lt;a href="https://help.github.com/articles/approving-oauth-apps-for-your-organization/">resource access&lt;/a>. Dex will not have the correct permissions to determine if the user is in that organization otherwise, and the user will not be able to log in. This request mechanism is a feature of the GitHub API.&lt;/li>
&lt;/ul>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Register a new application with &lt;a href="https://github.com/settings/applications/new">GitHub&lt;/a> ensuring the callback URL is &lt;code>(dex issuer)/callback&lt;/code>. For example if dex is listening at the non-root path &lt;code>https://auth.example.com/dex&lt;/code> the callback would be &lt;code>https://auth.example.com/dex/callback&lt;/code>.&lt;/p>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: GitHub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $GITHUB_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $GITHUB_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Legacy &amp;#39;org&amp;#39; field.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - A user MUST be a member of the following org to authenticate with dex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Both &amp;#39;org&amp;#39; and &amp;#39;orgs&amp;#39; can NOT be used simultaneously.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#org: my-organization&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># List of org and team names.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - If specified, a user MUST be a member of at least ONE of these orgs&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># and teams (if set) to authenticate with dex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Dex queries the following organizations for group information if the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># &amp;#34;groups&amp;#34; scope is requested. Group claims are formatted as &amp;#34;(org):(team)&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For example if a user is part of the &amp;#34;engineering&amp;#34; team of the &amp;#34;coreos&amp;#34; org,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># the group claim would include &amp;#34;coreos:engineering&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - If teams are specified, dex only returns group claims for those teams.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">orgs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: my-organization
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: my-organization-with-teams
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">teams&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - red-team
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - blue-team
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Flag which indicates that all the user&amp;#39;s orgs and teams should be loaded.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Only works if neither &amp;#39;org&amp;#39; nor &amp;#39;orgs&amp;#39; are specified in the config.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">loadAllGroups&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># How the team names are formatted.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Options: &amp;#39;name&amp;#39; (default), &amp;#39;slug&amp;#39;, &amp;#39;both&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Examples:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;#39;name&amp;#39;: &amp;#39;acme:Site Reliability Engineers&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;#39;slug&amp;#39;: &amp;#39;acme:site-reliability-engineers&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;#39;both&amp;#39;: &amp;#39;acme:Site Reliability Engineers&amp;#39;, &amp;#39;acme:site-reliability-engineers&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">teamNameField&lt;/span>: slug
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Flag which will switch from using the internal GitHub id to the users handle (@mention) as the user id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># It is possible for a user to change their own username, but it is very rare for them to do so&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">useLoginAsID&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># A preferred email domain to use when returning the user&amp;#39;s email.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - If the user has a PUBLIC email, it is ALWAYS returned in the email claim,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># so this field would have NO effect (this may change in the future).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - By default, if the user does NOT have a public email, their primary email is returned.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - When &amp;#39;preferredEmailDomain&amp;#39; is set, the first email matching this domain is returned,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># we fall back to the primary email if no match is found.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - To allow multiple subdomains, you may specify a wildcard like &amp;#34;*.example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># which will match &amp;#34;aaaa.example.com&amp;#34; and &amp;#34;bbbb.example.com&amp;#34;, but NOT &amp;#34;example.com&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - To return the user&amp;#39;s no-reply email, set this field to &amp;#34;users.noreply.github.com&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># this is a mostly static email that GitHub assigns to the user. These emails&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># are formatted like &amp;#39;ID+USERNAME@users.noreply.github.com&amp;#39; for newer accounts&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># and &amp;#39;USERNAME@users.noreply.github.com&amp;#39; for older accounts.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#preferredEmailDomain: &amp;#34;example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="github-enterprise">GitHub Enterprise&lt;a class="heading-anchor" href="#github-enterprise" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Users can use their GitHub Enterprise account to login to dex. The following configuration can be used to enable a GitHub Enterprise connector on dex:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: github
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: GitHub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required fields. Dex must be pre-registered with GitHub Enterprise&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># to get the following values.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $GITHUB_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $GITHUB_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># List of org and team names.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - If specified, a user MUST be a member of at least ONE of these orgs&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># and teams (if set) to authenticate with dex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Dex queries the following organizations for group information if the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># &amp;#34;groups&amp;#34; scope is requested. Group claims are formatted as &amp;#34;(org):(team)&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For example if a user is part of the &amp;#34;engineering&amp;#34; team of the &amp;#34;coreos&amp;#34; org,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># the group claim would include &amp;#34;coreos:engineering&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - If teams are specified, dex only returns group claims for those teams.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">orgs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: my-organization
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">name&lt;/span>: my-organization-with-teams
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">teams&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - red-team
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - blue-team
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Flag which indicates that all the user&amp;#39;s orgs and teams should be loaded.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Only works if neither &amp;#39;org&amp;#39; nor &amp;#39;orgs&amp;#39; are specified in the config.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">loadAllGroups&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># How the team names are formatted&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Options: &amp;#39;name&amp;#39; (default), &amp;#39;slug&amp;#39;, &amp;#39;both&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Examples:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;#39;name&amp;#39;: &amp;#39;acme:Site Reliability Engineers&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;#39;slug&amp;#39;: &amp;#39;acme:site-reliability-engineers&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;#39;both&amp;#39;: &amp;#39;acme:Site Reliability Engineers&amp;#39;, &amp;#39;acme:site-reliability-engineers&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">teamNameField&lt;/span>: slug
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required ONLY for GitHub Enterprise.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This is the Hostname of the GitHub Enterprise account listed on the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># management console. Ensure this domain is routable on your network.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">hostName&lt;/span>: git.example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># ONLY for GitHub Enterprise. Optional field.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Used to support self-signed or untrusted CA root certificates.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">rootCA&lt;/span>: /etc/dex/ca.crt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="generate-tls-assets">Generate TLS assets&lt;a class="heading-anchor" href="#generate-tls-assets" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Running Dex with HTTPS enabled requires a valid SSL certificate, and the API server needs to trust the certificate of the signing CA using the &lt;code>--oidc-ca-file&lt;/code> flag.&lt;/p>
&lt;p>For our example use case, the TLS assets can be created using the following command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ ./examples/k8s/gencert.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will generate several files under the &lt;code>ssl&lt;/code> directory, the important ones being &lt;code>cert.pem&lt;/code> ,&lt;code>key.pem&lt;/code> and &lt;code>ca.pem&lt;/code>. The generated SSL certificate is for &amp;lsquo;dex.example.com&amp;rsquo;, although you could change this by editing &lt;code>gencert.sh&lt;/code> if required.&lt;/p>
&lt;h3 id="run-example-client-app-with-github-config">Run example client app with GitHub config&lt;a class="heading-anchor" href="#run-example-client-app-with-github-config" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./bin/example-app --issuer-root-ca examples/k8s/ssl/ca.pem
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>Open browser to http://127.0.0.1:5555&lt;/li>
&lt;li>Click Login&lt;/li>
&lt;li>Select Log in with GitHub and grant access to dex to view your profile&lt;/li>
&lt;/ol></description></item><item><title>Docs: Authentication through SAML 2.0</title><link>https://dexidp.io/docs/connectors/saml/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/saml/</guid><description>
&lt;h2 id="warning">WARNING&lt;a class="heading-anchor" href="#warning" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The SAML connector is unmaintained, likely vulnerable to authentication bypass vulnerabilities, and is under consideration for deprecation (see &lt;a href="https://github.com/dexidp/dex/discussions/1884">#1884&lt;/a>). Please consider switching to OpenID Connect, OAuth2, or LDAP for identity providers that support these protocols. If you have domain expertise in SAML/XMLDSig and would like to volunteer to maintain the connector please comment on the discussion.&lt;/p>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The SAML provider allows authentication through the SAML 2.0 HTTP POST binding. The connector maps attribute values in the SAML assertion to user info, such as username, email, and groups.&lt;/p>
&lt;p>The connector uses the value of the &lt;code>NameID&lt;/code> element as the user&amp;rsquo;s unique identifier which dex assumes is both unique and never changes. Use the &lt;code>nameIDPolicyFormat&lt;/code> to ensure this is set to a value which satisfies these requirements.&lt;/p>
&lt;p>Unlike some clients which will process unprompted AuthnResponses, dex must send the initial AuthnRequest and validates the response&amp;rsquo;s InResponseTo value.&lt;/p>
&lt;h2 id="caveats">Caveats&lt;a class="heading-anchor" href="#caveats" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>&lt;strong>The connector doesn&amp;rsquo;t support refresh tokens&lt;/strong> since the SAML 2.0 protocol doesn&amp;rsquo;t provide a way to requery a provider without interaction. If the &amp;ldquo;offline_access&amp;rdquo; scope is requested, it will be ignored.&lt;/p>
&lt;p>The connector doesn&amp;rsquo;t support signed AuthnRequests or encrypted attributes.&lt;/p>
&lt;h2 id="group-filtering">Group Filtering&lt;a class="heading-anchor" href="#group-filtering" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The SAML Connector supports providing a whitelist of SAML Groups to filter access based on, and when the &lt;code>groupsattr&lt;/code> is set with a scope including groups, Dex will check for membership based on configured groups in the &lt;code>allowedGroups&lt;/code> config setting for the SAML connector.&lt;/p>
&lt;p>If &lt;code>filterGroups&lt;/code> is set to true, any groups &lt;em>not&lt;/em> part of &lt;code>allowedGroups&lt;/code> will be excluded.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: SAML
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># SSO URL used for POST value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ssoURL&lt;/span>: https://saml.example.com/sso
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># CA to use when validating the signature of the SAML response.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ca&lt;/span>: /path/to/ca.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Dex&amp;#39;s callback URL.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If the response assertion status value contains a Destination element, it&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># must match this value exactly.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This is also used as the expected audience for AudienceRestriction elements&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># if entityIssuer isn&amp;#39;t specified.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: https://dex.example.com/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Name of attributes in the returned assertions to map to ID token claims.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">usernameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupsAttr&lt;/span>: groups &lt;span style="color:#7f848e"># optional&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># List of groups to filter access based on membership&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># allowedGroups&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - Admins&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># CA&amp;#39;s can also be provided inline as a base64&amp;#39;d blob.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># caData: ( RAW base64&amp;#39;d PEM encoded CA )&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># To skip signature validation, uncomment the following field. This should&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># only be used during testing and may be removed in the future.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureSkipSignatureValidation: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Manually specify dex&amp;#39;s Issuer value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># When provided dex will include this as the Issuer value during AuthnRequest.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># It will also override the redirectURI as the required audience when evaluating&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># AudienceRestriction elements in the response.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">entityIssuer&lt;/span>: https://dex.example.com/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Issuer value expected in the SAML response.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ssoIssuer&lt;/span>: https://saml.example.com/sso
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Delimiter for splitting groups returned as a single string.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># By default, multiple groups are assumed to be represented as multiple&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># attributes with the same name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If &amp;#34;groupsDelim&amp;#34; is provided groups are assumed to be represented as a&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># single attribute and the delimiter is used to split the attribute&amp;#39;s value&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># into multiple groups.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupsDelim&lt;/span>: &lt;span style="color:#98c379">&amp;#34;, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Requested format of the NameID.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The NameID value is is mapped to the user ID of the user. This can be an&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># abbreviated form of the full URI with just the last component. For example,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># if this value is set to &amp;#34;emailAddress&amp;#34; the format will resolve to:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If no value is specified, this value defaults to:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># urn:oasis:names:tc:SAML:2.0:nameid-format:persistent&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">nameIDPolicyFormat&lt;/span>: persistent
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A minimal working configuration might look like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: okta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Okta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ssoURL&lt;/span>: https://dev-111102.oktapreview.com/app/foo/exk91cb99lKkKSYoy0h7/sso/saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ca&lt;/span>: /etc/dex/saml-ca.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">usernameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupsAttr&lt;/span>: groups
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through GitLab</title><link>https://dexidp.io/docs/connectors/gitlab/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/gitlab/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>GitLab is a web-based Git repository manager with wiki and issue tracking features, using an open source license, developed by GitLab Inc. One of the login options for dex uses the GitLab OAuth2 flow to identify the end user through their GitLab account. You can use this option with &lt;a href="https://gitlab.com">gitlab.com&lt;/a>, GitLab community or enterprise edition.&lt;/p>
&lt;p>When a client redeems a refresh token through dex, dex will re-query GitLab to update user information in the ID Token. To do this, &lt;strong>dex stores a readonly GitLab access token in its backing datastore.&lt;/strong> Users that reject dex&amp;rsquo;s access through GitLab will also revoke all dex clients which authenticated them through GitLab.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Register a new application via &lt;code>User Settings -&amp;gt; Applications&lt;/code> ensuring the callback URL is &lt;code>(dex issuer)/callback&lt;/code>. For example if dex is listening at the non-root path &lt;code>https://auth.example.com/dex&lt;/code> the callback would be &lt;code>https://auth.example.com/dex/callback&lt;/code>.&lt;/p>
&lt;p>The application requires the user to grant the &lt;code>read_user&lt;/code> and &lt;code>openid&lt;/code> scopes. The latter is required only if group membership is a desired claim.&lt;/p>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: gitlab
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: gitlab
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: GitLab
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># optional, default = https://gitlab.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseURL&lt;/span>: https://gitlab.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $GITLAB_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $GITLAB_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional groups whitelist, communicated through the &amp;#34;groups&amp;#34; scope.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `groups` is omitted, all of the user&amp;#39;s GitLab groups are returned when the groups scope is present.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `groups` is provided, this acts as a whitelist - only the user&amp;#39;s GitLab groups that are in the configured `groups` below will go into the groups claim. Conversely, if the user is not in any of the configured `groups`, the user will not be authenticated.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - my-group
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># flag which will switch from using the internal GitLab id to the users handle (@mention) as the user id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># It is possible for a user to change their own user name but it is very rare for them to do so&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">useLoginAsID&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Flag to include user group permissions in the user groups.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For example, if the user has maintainer access to a GitLab group named &amp;#34;project/group1&amp;#34;, &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># the user&amp;#39;s groups will reflect two entries: &amp;#34;project/group1&amp;#34; and &amp;#34;project/group1:maintainer&amp;#34;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">getGroupsPermission&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through an OpenID Connect Provider</title><link>https://dexidp.io/docs/connectors/oidc/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/oidc/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex is able to use another OpenID Connect provider as an authentication source. When logging in, dex will redirect to the upstream provider and perform the necessary OAuth2 flows to determine the end users email, username, etc. More details on the OpenID Connect protocol can be found in &lt;a href="https://dexidp.io/docs/openid-connect/">&lt;em>An overview of OpenID Connect&lt;/em>&lt;/a>.&lt;/p>
&lt;p>Prominent examples of OpenID Connect providers include Google Accounts, Salesforce, and Azure AD v2 (&lt;a href="https://github.com/coreos/go-oidc/issues/133">not v1&lt;/a>).&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: oidc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: google
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Google
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Canonical URL of the provider, also used for configuration discovery.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This value MUST match the value returned in the provider config discovery.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># See: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">issuer&lt;/span>: https://accounts.google.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Some offspec providers like Azure, Oracle IDCS have oidc discovery url&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># different from issuer url which causes issuerValidation to fail&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># issuerAlias provides a way to override the Issuer url&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># from the .well-known/openid-configuration issuer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># issuerAlias: https://accounts.google.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Connector config values starting with a &amp;#34;$&amp;#34; will read from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $GOOGLE_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $GOOGLE_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Dex&amp;#39;s issuer URL + &amp;#34;/callback&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Some providers require passing client_secret via POST parameters instead&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># of basic auth, despite the OAuth2 RFC discouraging it. Many of these&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># cases are caught internally, but some may need to uncomment the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># following field.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># basicAuthUnsupported: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># List of additional scopes to request in token response&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default is profile and email&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Full list at https://dexidp.io/docs/custom-scopes-claims-clients/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># scopes:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - profile&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - email&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - groups&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Some providers return claims without &amp;#34;email_verified&amp;#34;, when they had no usage of emails verification in enrollment process&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># or if they are acting as a proxy for another IDP etc AWS Cognito with an upstream SAML IDP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This can be overridden with the below option&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureSkipEmailVerified: true &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Groups claims (like the rest of oidc claims through dex) only refresh when the id token is refreshed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># meaning the regular refresh flow doesn&amp;#39;t update the groups claim. As such by default the oidc connector&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># doesn&amp;#39;t allow groups claims. If you are okay with having potentially stale group claims you can use&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># this option to enable groups claims through the oidc connector on a per-connector basis.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This can be overridden with the below option&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureEnableGroups: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Filter users based on membership in the given groups. Authentication will be successful it the user is a member in a least&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># one of the specified groups.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># allowedGroups:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;lt;value&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># When enabled, the OpenID Connector will query the UserInfo endpoint for additional claims. UserInfo claims&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># take priority over claims returned by the IDToken. This option should be used when the IDToken doesn&amp;#39;t contain&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># all the claims requested.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># https://openid.net/specs/openid-connect-core-1_0.html#UserInfo&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># getUserInfo: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The set claim is used as user id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Claims list at https://openid.net/specs/openid-connect-core-1_0.html#Claims&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: sub&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># userIDKey: nickname&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The set claim is used as user name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: name&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># userNameKey: nickname&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The acr_values variable specifies the Authentication Context Class Values within&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># the Authentication Request that the Authorization Server is being requested to process&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># from this Client.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># acrValues: &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;lt;value&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - &amp;lt;value&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For offline_access, the prompt parameter is set by default to &amp;#34;prompt=consent&amp;#34;. &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># However this is not supported by all OIDC providers, some of them support different&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># value for prompt, like &amp;#34;prompt=login&amp;#34; or &amp;#34;prompt=none&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># promptType: consent&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Some providers return non-standard claims (eg. mail).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Use claimMapping to map those claims to standard claims:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># https://openid.net/specs/openid-connect-core-1_0.html#Claims&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># claimMapping can only map a non-standard claim to a standard one if it&amp;#39;s not returned in the id_token.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">claimMapping&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The set claim is used as preferred username.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: preferred_username&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># preferred_username: other_user_name&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The set claim is used as email.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: email&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># email: mail&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The set claim is used as groups.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: groups&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># groups: &amp;#34;cognito:groups&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># claimModifications can change claims during the login&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">claimModifications&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># newGroupFromClaims allows to create a new group, based on other claims&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># they are concatenated using the delimiter.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Currently only string claims are supported, and other claims are skipped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The new group name is added to the groups claims, passed to the clients.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For this example, the resulting group would be: `example::organization::email`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># newGroupFromClaims:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - prefix: example&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># delimiter: &amp;#34;::&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># clearDelimiter: false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># claims:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - organization&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - email&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># filterGroupClaims allows to filter the groups, using a regex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The regex must conform to the RE2 regex specification used in go regexp.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Groups added using the newGroupFromClaims modification, are not passed through the filterGroupClaims&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># filterGroupClaims:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># groupsFilter: &amp;#34;&amp;lt;REGEX&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># modifyGroupNames allows to add a prefix or suffix to all groups&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Either one, or both fields can be specified, and they will be pre-/appended directly to the group-name as provided by the oidc issuer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The modifications are applied to all groups, not filtered by filterGroupClaims, and before Groups from newGroupFromClaims are created&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># For example, if the connector provides a group called &amp;#34;regular-users&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># this modification would convert it to &amp;#34;example-prefix-regular-usersexample-suffix&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># modifyGroupNames:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># prefix: example-prefix- # note the delimiter at the end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># suffix: example-suffix&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># overrideClaimMapping will be used to override the options defined in claimMappings.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># i.e. if there are &amp;#39;email&amp;#39; and `preferred_email` claims available, by default Dex will always use the `email` claim independent of the claimMapping.email.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This setting allows you to override the default behavior of Dex and enforce the mappings defined in `claimMapping`.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">overrideClaimMapping&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The section to override options discovered automatically from&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># the providers&amp;#39; discovery URL (.well-known/openid-configuration).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">providerDiscoveryOverrides&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># tokenURL provides a way to user overwrite the token URL&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># from the .well-known/openid-configuration &amp;#39;token_endpoint&amp;#39;.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># tokenURL: &amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># authURL provides a way to user overwrite the authorization URL&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># from the .well-known/openid-configuration &amp;#39;authorization_endpoint&amp;#39;. &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># authURL: &amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through an OAuth 2.0 Provider</title><link>https://dexidp.io/docs/connectors/oauth/</link><pubDate>Mon, 15 Mar 2021 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/oauth/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex users can make use of this connector to work with standards-compliant &lt;a href="https://oauth.net/2/">OAuth 2.0&lt;/a> authorization providers, in case those authorization providers are not already in the Dex connectors list.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The following is an example of a configuration for using OAuth connector with Reddit.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: oauth
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># ID of OAuth 2.0 provider&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: reddit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Name of OAuth 2.0 provider&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: reddit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Connector config values starting with a &amp;#34;$&amp;#34; will read from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $REDDIT_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $REDDIT_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tokenURL&lt;/span>: https://www.reddit.com/api/v1/access_token
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">authorizationURL&lt;/span>: https://www.reddit.com/api/v1/authorize
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userInfoURL&lt;/span>: https://www.reddit.com/api/v1/me
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Some providers return claims without &amp;#34;email_verified&amp;#34;, when they had no usage of emails verification in enrollment process&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># or if they are acting as a proxy for another IDP etc AWS Cognito with an upstream SAML IDP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This can be overridden with the below option&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureSkipEmailVerified: true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Specify whether to communicate to Auth provider without&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># validating SSL certificates&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># insecureSkipVerify: false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: The location of file containing SSL certificates to communicate&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># to Auth provider&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># rootCAs:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - /etc/ssl/reddit.pem&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: List of scopes to request Auth provider for access user account&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># scopes:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - identity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Configurable keys for user ID look up&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: id&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># userIDKey:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Auth providers return non-standard user identity profile&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Use claimMapping to map those user informations to standard claims:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">claimMapping&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Configurable keys for user name look up&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: user_name&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># userNameKey:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Configurable keys for preferred username look up&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: preferred_username&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># preferredUsernameKey:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Configurable keys for user groups look up&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: groups&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># groupsKey:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Configurable keys for email look up&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: email&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># emailKey:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Configurable keys for email verified look up&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Default: email_verified&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># emailVerifiedKey:&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through Google</title><link>https://dexidp.io/docs/connectors/google/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/google/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex is able to use Google&amp;rsquo;s OpenID Connect provider as an authentication source.&lt;/p>
&lt;p>The connector uses the same authentication flow as the OpenID Connect provider but adds Google specific features such as Hosted domain support and reading groups using a service account.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: google
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: google
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Google
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Connector config values starting with a &amp;#34;$&amp;#34; will read from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $GOOGLE_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $GOOGLE_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Dex&amp;#39;s issuer URL + &amp;#34;/callback&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Set the value of `prompt` query parameter in the authorization request&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The default value is &amp;#34;consent&amp;#34; when not set.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># promptType: consent&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Google supports whitelisting allowed domains when using G Suite&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># (Google Apps). The following field can be set to a list of domains&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># that can log in:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># hostedDomains:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - example.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># The Google connector supports whitelisting allowed groups when using G Suite&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># (Google Apps). The following field can be set to a list of groups&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># that can log in:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># groups:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># - admins@example.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Google does not support the OpenID Connect groups claim and only supports&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># fetching a user&amp;#39;s group membership with a service account.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This service account requires an authentication JSON file and the email&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># of a G Suite admin to impersonate:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#serviceAccountFilePath: googleAuth.json&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e">#domainToAdminEmail:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># *: super-user@example.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># my-domain.com: super-user@my-domain.com&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="fetching-groups-from-google">Fetching groups from Google&lt;a class="heading-anchor" href="#fetching-groups-from-google" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>To allow Dex to fetch group information from Google, you will need to configure a service account for Dex to use.
This account needs Domain-Wide Delegation and permission to access the &lt;code>https://www.googleapis.com/auth/admin.directory.group.readonly&lt;/code> API scope.&lt;/p>
&lt;p>To get group fetching set up:&lt;/p>
&lt;ol>
&lt;li>Follow the &lt;a href="https://developers.google.com/admin-sdk/directory/v1/guides/delegation">instructions&lt;/a> to set up a service account with Domain-Wide Delegation&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>During service account creation, a JSON key file will be created that contains authentication information for the service account. This needs storing in a location accessible by Dex and you will set the &lt;code>serviceAccountFilePath&lt;/code> to point at it.&lt;/li>
&lt;li>When delegating the API scopes to the service account, delegate the &lt;code>https://www.googleapis.com/auth/admin.directory.group.readonly&lt;/code> scope and only this scope. If you delegate more scopes to the service account, it will not be able to access the API.&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>Enable the &lt;a href="https://console.developers.google.com/apis/library/admin.googleapis.com/">Admin SDK&lt;/a>&lt;/li>
&lt;li>Add the &lt;code>serviceAccountFilePath&lt;/code> and &lt;code>domainToAdminEmail&lt;/code> configuration options to your Dex config.&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>&lt;code>serviceAccountFilePath&lt;/code> should point to the location of the service account JSON key file&lt;/li>
&lt;li>&lt;code>domainToAdminEmail&lt;/code> should map the base domain to the email address of a Google Workspace user with a minimum of the &lt;code>Groups Reader (BETA)&lt;/code> Role assigned. The service account you created earlier will impersonate this user when making calls to the admin API. A valid user should be able to retrieve a list of groups when &lt;a href="https://developers.google.com/admin-sdk/directory/v1/reference/groups/list#try-it">testing the API&lt;/a>.&lt;/li>
&lt;/ul>
&lt;h2 id="consent-screen">Consent Screen&lt;a class="heading-anchor" href="#consent-screen" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex will set &lt;code>prompt=consent&lt;/code> by default when redirecting users to Google&amp;rsquo;s
authorization endpoint. This will force users to see the consent screen every
time they log in.&lt;/p>
&lt;p>To change this behavior, you can set the &lt;code>promptType&lt;/code> field in config file to
any OIDC-supported value. To skip the consent screen for every authorization
request, set &lt;code>promptType&lt;/code> to &lt;code>&amp;quot;&amp;quot;&lt;/code> (empty string) to fall back to Google&amp;rsquo;s
default behavior.&lt;/p></description></item><item><title>Docs: Authentication Through LinkedIn</title><link>https://dexidp.io/docs/connectors/linkedin/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/linkedin/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>One of the login options for dex uses the LinkedIn OAuth2 flow to identify the end user through their LinkedIn account.&lt;/p>
&lt;p>When a client redeems a refresh token through dex, dex will re-query LinkedIn to update user information in the ID Token. To do this, &lt;strong>dex stores a readonly LinkedIn access token in its backing datastore.&lt;/strong> Users that reject dex&amp;rsquo;s access through LinkedIn will also revoke all dex clients which authenticated them through LinkedIn.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Register a new application via &lt;code>My Apps -&amp;gt; Create Application&lt;/code> ensuring the callback URL is &lt;code>(dex issuer)/callback&lt;/code>. For example if dex is listening at the non-root path &lt;code>https://auth.example.com/dex&lt;/code> the callback would be &lt;code>https://auth.example.com/dex/callback&lt;/code>.&lt;/p>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: linkedin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: linkedin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: LinkedIn
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $LINKEDIN_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $LINKEDIN_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through Microsoft</title><link>https://dexidp.io/docs/connectors/microsoft/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/microsoft/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>One of the login options for dex uses the Microsoft OAuth2 flow to identify the
end user through their Microsoft account.&lt;/p>
&lt;p>When a client redeems a refresh token through dex, dex will re-query Microsoft
to update user information in the ID Token. To do this, &lt;strong>dex stores a readonly
Microsoft access and refresh tokens in its backing datastore.&lt;/strong> Users that
reject dex&amp;rsquo;s access through Microsoft will also revoke all dex clients which
authenticated them through Microsoft.&lt;/p>
&lt;h3 id="caveats">Caveats&lt;a class="heading-anchor" href="#caveats" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>&lt;code>groups&lt;/code> claim in dex is only supported when &lt;code>tenant&lt;/code> is specified in Microsoft
connector config. Furthermore, &lt;code>tenant&lt;/code> must also be configured to either
&lt;code>&amp;lt;tenant uuid&amp;gt;&lt;/code> or &lt;code>&amp;lt;tenant name&amp;gt;&lt;/code> (see &lt;a href="https://dexidp.io/docs/connectors/microsoft/#configuration">Configuration&lt;/a>). In
order for dex to be able to list groups on behalf of logged in user, an
explicit organization administrator consent is required. To obtain the
consent do the following:&lt;/p>
&lt;ul>
&lt;li>when registering dex application on &lt;a href="https://apps.dev.microsoft.com">https://apps.dev.microsoft.com&lt;/a> add
an explicit &lt;code>Directory.Read.All&lt;/code> permission to the list of &lt;strong>Delegated
Permissions&lt;/strong>&lt;/li>
&lt;li>open the following link in your browser and log in under organization
administrator account:&lt;/li>
&lt;/ul>
&lt;p>&lt;code>https://login.microsoftonline.com/&amp;lt;tenant&amp;gt;/adminconsent?client_id=&amp;lt;dex client id&amp;gt;&lt;/code>&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Register a new application on &lt;a href="https://apps.dev.microsoft.com">https://apps.dev.microsoft.com&lt;/a> via &lt;code>Add an app&lt;/code>
ensuring the callback URL is &lt;code>(dex issuer)/callback&lt;/code>. For example if dex
is listening at the non-root path &lt;code>https://auth.example.com/dex&lt;/code> the callback
would be &lt;code>https://auth.example.com/dex/callback&lt;/code>.&lt;/p>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $MICROSOFT_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $MICROSOFT_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>tenant&lt;/code> configuration parameter controls what kinds of accounts may be
authenticated in dex. By default, all types of Microsoft accounts (consumers
and organizations) can authenticate in dex via Microsoft. To change this, set
the &lt;code>tenant&lt;/code> parameter to one of the following:&lt;/p>
&lt;ul>
&lt;li>&lt;code>common&lt;/code>- both personal and business/school accounts can authenticate in dex
via Microsoft (default)&lt;/li>
&lt;li>&lt;code>consumers&lt;/code> - only personal accounts can authenticate in dex&lt;/li>
&lt;li>&lt;code>organizations&lt;/code> - only business/school accounts can authenticate in dex&lt;/li>
&lt;li>&lt;code>&amp;lt;tenant uuid&amp;gt;&lt;/code> or &lt;code>&amp;lt;tenant name&amp;gt;&lt;/code> - only accounts belonging to specific
tenant identified by either &lt;code>&amp;lt;tenant uuid&amp;gt;&lt;/code> or &lt;code>&amp;lt;tenant name&amp;gt;&lt;/code> can
authenticate in dex&lt;/li>
&lt;/ul>
&lt;p>For example, the following snippet configures dex to only allow business/school
accounts:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $MICROSOFT_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $MICROSOFT_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tenant&lt;/span>: organizations
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>domainHint&lt;/code> configuration parameter allows for a more streamlined login
experience when the email domain is common to all users of the connector.
By default, users with multiple Microsoft sessions will be prompted to choose
which account they want to use for login. When &lt;code>domainHint&lt;/code> is configured,
Microsoft will select the session with matching email without the interactive
prompt.&lt;/p>
&lt;p>For example: user John Doe has 2 active Microsoft sessions:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="mailto:John.Doe@live.com">John.Doe@live.com&lt;/a> (consumer)&lt;/li>
&lt;li>&lt;a href="mailto:John.Doe@example.com">John.Doe@example.com&lt;/a> (organization)&lt;/li>
&lt;/ul>
&lt;p>If Example Organization configures the &lt;code>domainHint&lt;/code> parameter with its
organization&amp;rsquo;s email suffix, John will not be prompted to select an account
from the active sessions. Instead, the matching organization session is
selected automatically.&lt;/p>
&lt;p>&lt;code>scopes&lt;/code> configuration parameter controls what the initial scope(s) of the identity
token that dex requests from Microsoft. To change this initial set, configure
the &lt;code>scopes&lt;/code> parameter to be a list of one or more valid scopes (as defined in
&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent">Microsoft Documentation&lt;/a>).&lt;/p>
&lt;p>The default scope (if one is not specified in the connector&amp;rsquo;s configuration) is
&lt;code>user.read&lt;/code>.&lt;/p>
&lt;p>The scope list requested may also be appended by specifying &lt;a href="https://dexidp.io/docs/connectors/microsoft/#groups">groups&lt;/a> or
requesting a new token through the use of a refresh token.&lt;/p>
&lt;p>For example, the following snippet configures dex to request an OpenID token
with only getting the email address associated with the account and nothing else:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $MICROSOFT_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $MICROSOFT_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tenant&lt;/span>: example.onmicrosoft.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">domainHint&lt;/span>: example.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">scopes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - openid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - email
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="groups">Groups&lt;a class="heading-anchor" href="#groups" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>When the &lt;code>groups&lt;/code> claim is present in a request to dex &lt;strong>and&lt;/strong> &lt;code>tenant&lt;/code> is
configured, dex will query Microsoft API to obtain a list of groups the user is
a member of. &lt;code>onlySecurityGroups&lt;/code> configuration option restricts the list to
include only security groups. By default all groups (security, Office 365,
mailing lists) are included.&lt;/p>
&lt;p>Please note that &lt;code>tenant&lt;/code> must be configured to either &lt;code>&amp;lt;tenant uuid&amp;gt;&lt;/code> or
&lt;code>&amp;lt;tenant name&amp;gt;&lt;/code> for this to work. For more details on &lt;code>tenant&lt;/code> configuration,
see &lt;a href="https://dexidp.io/docs/connectors/microsoft/#configuration">Configuration&lt;/a>.&lt;/p>
&lt;p>By default, dex resolve groups ids to groups names, to keep groups ids, you can
specify the configuration option &lt;code>groupNameFormat: id&lt;/code>.&lt;/p>
&lt;p>It is possible to require a user to be a member of a particular group in order
to be successfully authenticated in dex. For example, with the following
configuration file only the users who are members of at least one of the listed
groups will be able to successfully authenticate in dex:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $MICROSOFT_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $MICROSOFT_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tenant&lt;/span>: myorg.onmicrosoft.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - developers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - devops
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Also, &lt;code>useGroupsAsWhitelist&lt;/code> configuration option, can restrict the groups
claims to include only the user&amp;rsquo;s groups that are in the configured &lt;code>groups&lt;/code>.&lt;/p>
&lt;p>You can use the emailToLowercase (boolean) configuration option to streamline
UPNs (user email) from Active Directory before putting them into an id token.
Without this option, it can be tough to match the email claim because a client
application doesn&amp;rsquo;t know whether an email address has been added with
capital- or lowercase letters.
For example, it is hard to bind Roles in Kubernetes using email as a user name
(&amp;ndash;oidc-username-claim=email flag) because user names are case sensitive.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Microsoft
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $MICROSOFT_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $MICROSOFT_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">tenant&lt;/span>: myorg.onmicrosoft.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - developers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - devops
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># All relevant E-Mail Addresses delivered by AD will transformed to&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># lowercase if config is TRUE&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailToLowercase&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authenticating Proxy</title><link>https://dexidp.io/docs/connectors/authproxy/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/authproxy/</guid><description>
&lt;p>NOTE: This connector is experimental and may change in the future.&lt;/p>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The &lt;code>authproxy&lt;/code> connector returns identities based on authentication which your
front-end web server performs. Dex consumes the &lt;code>X-Remote-User&lt;/code> header set by
the proxy, which is then used as the user&amp;rsquo;s email address.&lt;/p>
&lt;p>It also consumes the &lt;code>X-Remote-Group&lt;/code> header to use as the user&amp;rsquo;s group.&lt;/p>
&lt;p>Header&amp;rsquo;s names can be configured via the &lt;code>userHeader&lt;/code> and &lt;code>groupHeader&lt;/code> config.&lt;/p>
&lt;p>Additional static groups can also be defined in the connector&amp;rsquo;s configuration.&lt;/p>
&lt;p>&lt;strong>The proxy MUST remove any &lt;code>X-Remote-*&lt;/code> headers set by the client, for any URL
path, before the request is forwarded to dex.&lt;/strong>&lt;/p>
&lt;p>The connector does not support refresh tokens.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The &lt;code>authproxy&lt;/code> connector is used by proxies to implement login strategies not
supported by dex. For example, a proxy could handle a different OAuth2 strategy
such as Slack:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Slack login implemented by an authenticating proxy, not by dex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: authproxy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: slack
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Slack
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The proxy only needs to authenticate the user when they attempt to visit the
callback URL path:&lt;/p>
&lt;pre tabindex="0">&lt;code>( dex issuer URL )/callback/( connector id )?( url query )
&lt;/code>&lt;/pre>&lt;p>For example, if dex is running at &lt;code>https://auth.example.com/dex&lt;/code> and the connector
ID is &lt;code>slack&lt;/code>, the callback URL would look like:&lt;/p>
&lt;pre tabindex="0">&lt;code>https://auth.example.com/dex/callback/slack?state=xdg3z6quhrhwaueo5iysvliqf
&lt;/code>&lt;/pre>&lt;p>The proxy should login the user then return them to the exact URL (including the
query), setting &lt;code>X-Remote-User&lt;/code> to the user&amp;rsquo;s email before proxying the request
to dex.&lt;/p>
&lt;h2 id="configuration-example---apache-2">Configuration example - Apache 2&lt;a class="heading-anchor" href="#configuration-example---apache-2" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The following is an example config file that can be used by the external
connector to authenticate a user.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: authproxy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: myBasicAuth
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: HTTP Basic Auth
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userHeader&lt;/span>: X-Forwarded-User &lt;span style="color:#7f848e"># default is X-Remote-User&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupHeader&lt;/span>: X-Forwarded-Group &lt;span style="color:#7f848e"># default is X-Remote-Group&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">staticGroups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - default
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The authproxy connector assumes that you configured your front-end web server
such that it performs authentication for the &lt;code>/dex/callback/myBasicAuth&lt;/code>
location and provides the result in the HTTP headers.&lt;/p>
&lt;p>In this example, the configured headers are &lt;code>X-Forwarded-User&lt;/code> for the user&amp;rsquo;s mail
and &lt;code>X-Forwarded-Group&lt;/code> for the user&amp;rsquo;s group.
Dex authproxy connector will return a list of groups containing both
configured &lt;code>staticGroups&lt;/code> and return the group header.&lt;/p>
&lt;p>The following configuration will work for Apache 2.4.10+:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&amp;lt;Location /dex/&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPass &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPassReverse &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Strip the X-Remote-User header from all requests except for the ones&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># where we override it.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequestHeader &lt;span style="color:#e5c07b">unset&lt;/span> X-Remote-User
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/Location&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;Location /dex/callback/myBasicAuth&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthType Basic
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthName &lt;span style="color:#98c379">&amp;#34;db.debian.org webPassword&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthBasicProvider file
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthUserFile &lt;span style="color:#98c379">&amp;#34;/etc/apache2/debian-web-pw.htpasswd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Require valid-user
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Defense in depth: clear the Authorization header so that&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Debian Web Passwords never even reach dex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequestHeader &lt;span style="color:#e5c07b">unset&lt;/span> Authorization
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Requires Apache 2.4.10+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequestHeader &lt;span style="color:#e5c07b">set&lt;/span> X-Remote-User &lt;span style="color:#e06c75">expr&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>%&lt;span style="color:#56b6c2">{&lt;/span>REMOTE_USER&lt;span style="color:#56b6c2">}&lt;/span>@debian.org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPass &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/callback/myBasicAuth&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPassReverse &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/callback/myBasicAuth&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/Location&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="full-apache2-setup">Full Apache2 setup&lt;a class="heading-anchor" href="#full-apache2-setup" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>After installing your Linux distribution’s Apache2 package, place the following
virtual host configuration in e.g. &lt;code>/etc/apache2/sites-available/sso.conf&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&amp;lt;VirtualHost sso.example.net&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ServerName sso.example.net
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ServerAdmin webmaster@localhost
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> DocumentRoot /var/www/html
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ErrorLog &lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">APACHE_LOG_DIR&lt;/span>&lt;span style="color:#98c379">}&lt;/span>/error.log
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> CustomLog &lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">APACHE_LOG_DIR&lt;/span>&lt;span style="color:#98c379">}&lt;/span>/access.log combined
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;Location /dex/&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPass &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPassReverse &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Strip the X-Remote-User header from all requests except for the ones&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># where we override it.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequestHeader &lt;span style="color:#e5c07b">unset&lt;/span> X-Remote-User
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;/Location&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;Location /dex/callback/myBasicAuth&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthType Basic
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthName &lt;span style="color:#98c379">&amp;#34;db.debian.org webPassword&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthBasicProvider file
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> AuthUserFile &lt;span style="color:#98c379">&amp;#34;/etc/apache2/debian-web-pw.htpasswd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Require valid-user
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Defense in depth: clear the Authorization header so that&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Debian Web Passwords never even reach dex.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequestHeader &lt;span style="color:#e5c07b">unset&lt;/span> Authorization
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Requires Apache 2.4.10+&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequestHeader &lt;span style="color:#e5c07b">set&lt;/span> X-Remote-User &lt;span style="color:#e06c75">expr&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>%&lt;span style="color:#56b6c2">{&lt;/span>REMOTE_USER&lt;span style="color:#56b6c2">}&lt;/span>@debian.org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPass &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/callback/myBasicAuth&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ProxyPassReverse &lt;span style="color:#98c379">&amp;#34;http://localhost:5556/dex/callback/myBasicAuth&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;/Location&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/VirtualHost&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, enable it using &lt;code>a2ensite sso.conf&lt;/code>, followed by a restart of Apache2.&lt;/p></description></item><item><title>Docs: Authentication Through Bitbucket Cloud</title><link>https://dexidp.io/docs/connectors/bitbucketcloud/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/bitbucketcloud/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>One of the login options for dex uses the Bitbucket OAuth2 flow to identify the end user through their Bitbucket account.&lt;/p>
&lt;p>When a client redeems a refresh token through dex, dex will re-query Bitbucket to update user information in the ID Token. To do this, &lt;strong>dex stores a readonly Bitbucket access token in its backing datastore.&lt;/strong> Users that reject dex&amp;rsquo;s access through Bitbucket will also revoke all dex clients which authenticated them through Bitbucket.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Register a new OAuth consumer with &lt;a href="https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html">Bitbucket&lt;/a> ensuring the callback URL is &lt;code>(dex issuer)/callback&lt;/code>. For example if dex is listening at the non-root path &lt;code>https://auth.example.com/dex&lt;/code> the callback would be &lt;code>https://auth.example.com/dex/callback&lt;/code>.&lt;/p>
&lt;p>There are several permissions required for an OAuth consumer to use it with Dex:&lt;/p>
&lt;ul>
&lt;li>&lt;code>Account: Read&lt;/code> - required for extracting base information (email, username)&lt;/li>
&lt;li>&lt;code>Workspace membership: Read&lt;/code> - only necessary to get user&amp;rsquo;s teams&lt;/li>
&lt;/ul>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: bitbucket-cloud
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: bitbucket-cloud
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Bitbucket Cloud
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $BITBUCKET_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $BITBUCKET_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional teams whitelist, communicated through the &amp;#34;groups&amp;#34; scope.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `teams` is omitted, all of the user&amp;#39;s Bitbucket teams are returned when the groups scope is present.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `teams` is provided, this acts as a whitelist - only the user&amp;#39;s Bitbucket teams that are in the configured `teams` below will go into the groups claim. Conversely, if the user is not in any of the configured `teams`, the user will not be authenticated.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">teams&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - my-team
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional parameter to include team groups.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If enabled, the groups claim of dex id_token will looks like this:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># [&amp;#34;my_team&amp;#34;, &amp;#34;my_team/administrators&amp;#34;, &amp;#34;my_team/members&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">includeTeamGroups&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through the builtin connector</title><link>https://dexidp.io/docs/connectors/local/</link><pubDate>Fri, 05 Jan 2024 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/local/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex comes with a built-in local connector, acting as a &amp;ldquo;virtual&amp;rdquo; identity provider within Dex&amp;rsquo;s ecosystem, securely storing login credentials in the specified &lt;a href="https://dexidp.io/docs/storage">storage&lt;/a>.
This local connector simplifies authentication workflows by managing and storing user credentials directly within Dex&amp;rsquo;s infrastructure.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The local connector can be utilized by adding the following flag to the configuration.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">enablePasswordDB&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="creating-users">Creating Users&lt;a class="heading-anchor" href="#creating-users" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Once the local connector is enabled, users can be added in two ways: statically within the configuration file or dynamically through the &lt;a href="https://dexidp.io/docs/api">gRPC API&lt;/a>.&lt;/p>
&lt;h4 id="static-configuration-config-file">Static configuration (config file)&lt;a class="heading-anchor" href="#static-configuration-config-file" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticPasswords&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">email&lt;/span>: &lt;span style="color:#98c379">&amp;#34;admin@example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># bcrypt hash of the string &amp;#34;password&amp;#34;: $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">hash&lt;/span>: &lt;span style="color:#98c379">&amp;#34;$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>: &lt;span style="color:#98c379">&amp;#34;admin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userID&lt;/span>: &lt;span style="color:#98c379">&amp;#34;08a8684b-db88-4b73-90a9-3cd1661f5466&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To specify users within the configuration file, the &lt;code>staticPasswords&lt;/code> option can be used. It contains a list of predefined users, each defined by the following entities:&lt;/p>
&lt;ul>
&lt;li>&lt;code>email&lt;/code>: The email address of the user (used as the main identifier).&lt;/li>
&lt;li>&lt;code>hash&lt;/code>: The bcrypt hash of the user&amp;rsquo;s password.&lt;/li>
&lt;li>&lt;code>username&lt;/code>: The username associated with the user.&lt;/li>
&lt;li>&lt;code>userID&lt;/code>: The unique identifier (ID) of the user.&lt;/li>
&lt;/ul>
&lt;h4 id="dynamic-configuration-api">Dynamic configuration (API)&lt;a class="heading-anchor" href="#dynamic-configuration-api" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h4>
&lt;p>Users can be dynamically managed via the gRPC API, offering a versatile method to handle user-related operations within the system.
This functionality enables seamless additions, updates, and removals of users, providing a flexible approach to user management.
For comprehensive information and detailed procedures, please refer to the specific &lt;a href="https://dexidp.io/docs/api">API documentation&lt;/a>.&lt;/p>
&lt;h3 id="obtaining-a-token">Obtaining a token&lt;a class="heading-anchor" href="#obtaining-a-token" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Let&amp;rsquo;s explore a sample configuration in dex that involves a public and private client along with a static user.
Both local users and password grants are enabled, allowing the exchange of a token for user credentials.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">issuer&lt;/span>: http://localhost:8080/dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">storage&lt;/span>: &lt;span style="color:#7f848e"># .. storage configuration&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Setup clients&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticClients&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">id&lt;/span>: public-client
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">public&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: &lt;span style="color:#98c379">&amp;#39;Public Client&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#39;https://example.com/oidc/callback&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">id&lt;/span>: private-client
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">secret&lt;/span>: app-secret
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: &lt;span style="color:#98c379">&amp;#39;Private Client&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#39;https://example.com/oidc/callback&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Set up an test user&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">staticPasswords&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">email&lt;/span>: &lt;span style="color:#98c379">&amp;#34;admin@example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># bcrypt hash of the string &amp;#34;password&amp;#34;: $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">hash&lt;/span>: &lt;span style="color:#98c379">&amp;#34;$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">username&lt;/span>: &lt;span style="color:#98c379">&amp;#34;admin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">userID&lt;/span>: &lt;span style="color:#98c379">&amp;#34;08a8684b-db88-4b73-90a9-3cd1661f5466&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Enable local users&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">enablePasswordDB&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># Allow password grants with local users&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">oauth2&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">passwordConnector&lt;/span>: local
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Depending on whether you use a public or a private client you need to either include the just &lt;code>clientId&lt;/code> or the &lt;code>clientId&lt;/code> and &lt;code>clientPassword&lt;/code> in the authorization header.&lt;/p>
&lt;p>&lt;strong>Public Client&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>curl -L -X POST &lt;span style="color:#98c379">&amp;#39;http://localhost:8080/dex/token&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>-H &lt;span style="color:#98c379">&amp;#39;Authorization: Basic cHVibGljLWNsaWVudDo=&amp;#39;&lt;/span> &lt;span style="color:#98c379">\ &lt;/span>&lt;span style="color:#7f848e"># base64 encoded: public-client:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-H &lt;span style="color:#98c379">&amp;#39;Content-Type: application/x-www-form-urlencoded&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;grant_type=password&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;scope=openid profile&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;username=admin@example.com&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;password=password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Private Client&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>curl -L -X POST &lt;span style="color:#98c379">&amp;#39;http://localhost:8080/dex/token&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>-H &lt;span style="color:#98c379">&amp;#39;Authorization: Basic cHJpdmF0ZS1jbGllbnQ6YXBwLXNlY3JldA==&amp;#39;&lt;/span> &lt;span style="color:#98c379">\ &lt;/span>&lt;span style="color:#7f848e"># base64 encoded: private-client:app-secret&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-H &lt;span style="color:#98c379">&amp;#39;Content-Type: application/x-www-form-urlencoded&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;grant_type=password&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;scope=openid&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;username=admin@example.com&amp;#39;&lt;/span> &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span>--data-urlencode &lt;span style="color:#98c379">&amp;#39;password=password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication using OpenShift</title><link>https://dexidp.io/docs/connectors/openshift/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/openshift/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Dex can make use of users and groups defined within OpenShift by querying the platform provided OAuth server.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;h3 id="creating-an-oauth-client">Creating an OAuth Client&lt;a class="heading-anchor" href="#creating-an-oauth-client" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Two forms of OAuth Clients can be utilized:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.openshift.com/container-platform/latest/authentication/using-service-accounts-as-oauth-client.html">Using a Service Account as an OAuth Client&lt;/a> (Recommended)&lt;/li>
&lt;li>&lt;a href="https://docs.openshift.com/container-platform/latest/authentication/configuring-internal-oauth.html#oauth-register-additional-client_configuring-internal-oauth">Registering An Additional OAuth Client&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="using-a-service-account-as-an-oauth-client">Using a Service Account as an OAuth Client&lt;a class="heading-anchor" href="#using-a-service-account-as-an-oauth-client" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h4>
&lt;p>OpenShift Service Accounts can be used as a constrained form of OAuth client. Making use of a Service Account to represent an OAuth Client is the recommended option as it does not require elevated privileged within the OpenShift cluster. Create a new Service Account or make use of an existing Service Account.&lt;/p>
&lt;p>Patch the Service Account to add an annotation for location of the Redirect URI&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>oc patch serviceaccount &amp;lt;name&amp;gt; --type&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#39;json&amp;#39;&lt;/span> -p&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#39;[{&amp;#34;op&amp;#34;: &amp;#34;add&amp;#34;, &amp;#34;path&amp;#34;: &amp;#34;/metadata/annotations/serviceaccounts.openshift.io~1oauth-redirecturi.dex&amp;#34;, &amp;#34;value&amp;#34;:&amp;#34;https://&amp;lt;dex_url&amp;gt;/callback&amp;#34;}]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Client ID for a Service Account representing an OAuth Client takes the form &lt;code>system:serviceaccount:&amp;lt;namespace&amp;gt;:&amp;lt;service_account_name&amp;gt;&lt;/code>&lt;/p>
&lt;p>The Client Secret for a Service Account representing an OAuth Client is the long lived OAuth Token that is configued for the Service Account. Execute the following command to retrieve the OAuth Token.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>oc serviceaccounts get-token &amp;lt;name&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="registering-an-additional-oauth-client">Registering An Additional OAuth Client&lt;a class="heading-anchor" href="#registering-an-additional-oauth-client" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h4>
&lt;p>Instead of using a constrained form of Service Account to represent an OAuth Client, an additional OAuthClient resource can be created.&lt;/p>
&lt;p>Create a new OAuthClient resource similar to the following:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">kind&lt;/span>: OAuthClient
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">apiVersion&lt;/span>: oauth.openshift.io/v1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># The value that should be utilized as the `client_secret`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">secret&lt;/span>: &lt;span style="color:#98c379">&amp;#34;&amp;lt;clientSecret&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#7f848e"># List of valid addresses for the callback. Ensure one of the values that are provided is `(dex issuer)/callback` &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">redirectURIs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#98c379">&amp;#34;https:///&amp;lt;dex_url&amp;gt;/callback&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">grantMethod&lt;/span>: prompt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="dex-configuration">Dex Configuration&lt;a class="heading-anchor" href="#dex-configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: openshift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: openshift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: OpenShift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># OpenShift API&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">issuer&lt;/span>: https://api.mycluster.example.com:6443
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $OPENSHIFT_OAUTH_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $OPENSHIFT_OAUTH_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: Specify whether to communicate to OpenShift without validating SSL certificates&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">insecureCA&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional: The location of file containing SSL certificates to communicate to OpenShift&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">rootCA&lt;/span>: /etc/ssl/openshift.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional list of required groups a user must be a member of&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - users
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through Atlassian Crowd</title><link>https://dexidp.io/docs/connectors/atlassian-crowd/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/atlassian-crowd/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Atlassian Crowd is a centralized identity management solution providing single sign-on and user identity.&lt;/p>
&lt;p>Current connector uses request to &lt;a href="https://developer.atlassian.com/server/crowd/json-requests-and-responses/">Crowd REST API&lt;/a> endpoints:&lt;/p>
&lt;ul>
&lt;li>&lt;code>/user&lt;/code> - to get user-info&lt;/li>
&lt;li>&lt;code>/session&lt;/code> - to authenticate the user&lt;/li>
&lt;/ul>
&lt;p>Offline Access scope support provided with a new request to user authentication and user info endpoints.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>To start using the Atlassian Crowd connector, firstly you need to register an application in your Crowd like specified in the &lt;a href="https://confluence.atlassian.com/crowd/adding-an-application-18579591.html">docs&lt;/a>.&lt;/p>
&lt;p>The following is an example of a configuration for dex &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: atlassian-crowd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: crowd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Crowd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field to connect to Crowd.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseURL&lt;/span>: https://crowd.example.com/crowd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $ATLASSIAN_CROWD_APPLICATION_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $ATLASSIAN_CROWD_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optional groups whitelist, communicated through the &amp;#34;groups&amp;#34; scope.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `groups` is omitted, all of the user&amp;#39;s Crowd groups are returned when the groups scope is present.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `groups` is provided, this acts as a whitelist - only the user&amp;#39;s Crowd groups that are in the configured `groups` below will go into the groups claim. &lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Conversely, if the user is not in any of the configured `groups`, the user will not be authenticated.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groups&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - my-group
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Prompt for username field.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">usernamePrompt&lt;/span>: Login
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Optionally set preferred_username claim.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `preferredUsernameField` is omitted or contains an invalid option, the `preferred_username` claim will be empty.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># If `preferredUsernameField` is set, the `preferred_username` claim will be set to the chosen Crowd user attribute value.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Possible choices are: &amp;#34;key&amp;#34;, &amp;#34;name&amp;#34;, &amp;#34;email&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">preferredUsernameField&lt;/span>: name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through Gitea</title><link>https://dexidp.io/docs/connectors/gitea/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/gitea/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>One of the login options for dex uses the Gitea OAuth2 flow to identify the end user through their Gitea account.&lt;/p>
&lt;p>When a client redeems a refresh token through dex, dex will re-query Gitea to update user information in the ID Token. To do this, &lt;strong>dex stores a readonly Gitea access token in its backing datastore.&lt;/strong> Users that reject dex&amp;rsquo;s access through Gitea will also revoke all dex clients which authenticated them through Gitea.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Register a new OAuth consumer with &lt;a href="https://docs.gitea.com/next/development/oauth2-provider">Gitea&lt;/a> ensuring the callback URL is &lt;code>(dex issuer)/callback&lt;/code>. For example if dex is listening at the non-root path &lt;code>https://auth.example.com/dex&lt;/code> the callback would be &lt;code>https://auth.example.com/dex/callback&lt;/code>.&lt;/p>
&lt;p>The following is an example of a configuration for &lt;code>examples/config-dev.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: gitea
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: gitea
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Gitea
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Credentials can be string literals or pulled from the environment.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientID&lt;/span>: $GITEA_CLIENT_ID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">clientSecret&lt;/span>: $GITEA_CLIENT_SECRET
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># optional, default = https://gitea.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">baseURL&lt;/span>: https://gitea.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Authentication Through OpenStack Keystone</title><link>https://dexidp.io/docs/connectors/keystone/</link><pubDate>Thu, 11 Mar 2021 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/connectors/keystone/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>&lt;a href="https://docs.openstack.org/keystone/latest/">Keystone&lt;/a> is an OpenStack service that provides API client authentication, service discovery, and distributed multi-tenant authorization.&lt;/p>
&lt;p>OpenStack Keystone connector supports &lt;code>offline_access&lt;/code> and &lt;code>groups&lt;/code> scopes. To use this connector, create a domain and user with an admin role, then specify the credentials in the configuration file (see the example below).&lt;/p>
&lt;p>OpenStack Keystone exposes the &lt;a href="https://docs.openstack.org/api-ref/identity/v3/">Identity API v3&lt;/a> to work with dex.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;a class="heading-anchor" href="#configuration" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The following is an example of an OpenStack Keystone configuration for dex:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e06c75">type&lt;/span>: keystone
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector id.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: keystone
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required field for connector name.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Keystone
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required, without v3 suffix.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">keystoneHost&lt;/span>: http://example:5000
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># Required, admin user credentials to connect to keystone.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">domain&lt;/span>: default
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">keystoneUsername&lt;/span>: demo
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">keystonePassword&lt;/span>: DEMO_PASS
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Integration kubelogin and Active Directory</title><link>https://dexidp.io/docs/guides/kubelogin-activedirectory/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/guides/kubelogin-activedirectory/</guid><description>
&lt;h2 id="overview">Overview&lt;a class="heading-anchor" href="#overview" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>kubelogin is helper tool for kubernetes and oidc integration.
It makes easy to login Open ID Provider.
This document describes how dex work with kubelogin and Active Directory.&lt;/p>
&lt;p>examples/config-ad-kubelogin.yaml is sample configuration to integrate Active Directory and kubelogin.&lt;/p>
&lt;h2 id="precondition">Precondition&lt;a class="heading-anchor" href="#precondition" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>Active Directory
You should have Active Directory or LDAP has Active Directory compatible schema such as samba ad.
You may have user objects and group objects in AD. Please ensure TLS is enabled.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Install kubelogin
Download kubelogin from &lt;a href="https://github.com/int128/kubelogin/releases">https://github.com/int128/kubelogin/releases&lt;/a>.
Install it to your terminal.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="getting-started">Getting started&lt;a class="heading-anchor" href="#getting-started" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;h3 id="generate-certificate-and-private-key">Generate certificate and private key&lt;a class="heading-anchor" href="#generate-certificate-and-private-key" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Create OpenSSL conf req.conf as follow:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">[&lt;/span>req&lt;span style="color:#56b6c2">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">req_extensions&lt;/span> &lt;span style="color:#56b6c2">=&lt;/span> v3_req
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">distinguished_name&lt;/span> &lt;span style="color:#56b6c2">=&lt;/span> req_distinguished_name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">[&lt;/span>req_distinguished_name&lt;span style="color:#56b6c2">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">[&lt;/span> v3_req &lt;span style="color:#56b6c2">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">basicConstraints&lt;/span> &lt;span style="color:#56b6c2">=&lt;/span> CA:FALSE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">keyUsage&lt;/span> &lt;span style="color:#56b6c2">=&lt;/span> nonRepudiation, digitalSignature, keyEncipherment
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">subjectAltName&lt;/span> &lt;span style="color:#56b6c2">=&lt;/span> @alt_names
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#56b6c2">[&lt;/span>alt_names&lt;span style="color:#56b6c2">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>DNS.1 &lt;span style="color:#56b6c2">=&lt;/span> dex.example.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please replace dex.example.com to your favorite hostname.
Generate certificate and private key by following command.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ openssl req -new -x509 -sha256 -days &lt;span style="color:#d19a66">3650&lt;/span> -newkey rsa:4096 -extensions v3_req -out openid-ca.pem -keyout openid-key.pem -config req.cnf -subj &lt;span style="color:#98c379">&amp;#34;/CN=kube-ca&amp;#34;&lt;/span> -nodes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ls openid*
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openid-ca.pem openid-key.pem
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="modify-dex-config">Modify dex config&lt;a class="heading-anchor" href="#modify-dex-config" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Modify following host, bindDN and bindPW in examples/config-ad-kubelogin.yaml.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: OpenLDAP
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">host&lt;/span>: ldap.example.com:636
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># No TLS for this setup.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">insecureNoSSL&lt;/span>: &lt;span style="color:#e5c07b">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">insecureSkipVerify&lt;/span>: &lt;span style="color:#e5c07b">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#7f848e"># This would normally be a read-only user.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">bindDN&lt;/span>: cn=Administrator,cn=users,dc=example,dc=com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">bindPW&lt;/span>: admin0!
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="run-dex">Run dex&lt;a class="heading-anchor" href="#run-dex" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ bin/dex serve examples/config-ad-kubelogin.yaml
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configure-kubernetes-with-oidc">Configure kubernetes with oidc&lt;a class="heading-anchor" href="#configure-kubernetes-with-oidc" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Copy &lt;code>openid-ca.pem&lt;/code> to &lt;code>/etc/ssl/certs/openid-ca.pem&lt;/code> on master node.&lt;/p>
&lt;p>Use the following flags to point your API server(s) at dex. &lt;code>dex.example.com&lt;/code> should be replaced by whatever DNS name or IP address dex is running under.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>--oidc-issuer-url&lt;span style="color:#56b6c2">=&lt;/span>https://dex.example.com:32000/dex
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-client-id&lt;span style="color:#56b6c2">=&lt;/span>kubernetes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-ca-file&lt;span style="color:#56b6c2">=&lt;/span>/etc/ssl/certs/openid-ca.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-username-claim&lt;span style="color:#56b6c2">=&lt;/span>email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>--oidc-groups-claim&lt;span style="color:#56b6c2">=&lt;/span>groups
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then restart API server(s).&lt;/p>
&lt;p>See &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/">https://kubernetes.io/docs/reference/access-authn-authz/authentication/&lt;/a> for more detail.&lt;/p>
&lt;h3 id="set-up-kubeconfig">Set up kubeconfig&lt;a class="heading-anchor" href="#set-up-kubeconfig" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>Add a new user to the kubeconfig for dex authentication:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ kubectl config set-credentials oidc &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-api-version&lt;span style="color:#56b6c2">=&lt;/span>client.authentication.k8s.io/v1beta1 &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-command&lt;span style="color:#56b6c2">=&lt;/span>kubectl &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>oidc-login &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>get-token &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--oidc-issuer-url&lt;span style="color:#56b6c2">=&lt;/span>https://dex.example.com:32000/dex &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--oidc-client-id&lt;span style="color:#56b6c2">=&lt;/span>kubernetes &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--oidc-client-secret&lt;span style="color:#56b6c2">=&lt;/span>ZXhhbXBsZS1hcHAtc2VjcmV0 &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--oidc-extra-scope&lt;span style="color:#56b6c2">=&lt;/span>profile &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--oidc-extra-scope&lt;span style="color:#56b6c2">=&lt;/span>email &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--oidc-extra-scope&lt;span style="color:#56b6c2">=&lt;/span>groups &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --exec-arg&lt;span style="color:#56b6c2">=&lt;/span>--certificate-authority-data&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#c678dd">$(&lt;/span>base64 -w &lt;span style="color:#d19a66">0&lt;/span> openid-ca.pem&lt;span style="color:#c678dd">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please confirm &lt;code>--oidc-issuer-url&lt;/code>, &lt;code>--oidc-client-id&lt;/code>, &lt;code>--oidc-client-secret&lt;/code> and &lt;code>--certificate-authority-data&lt;/code> are same as values in config-ad-kubelogin.yaml.&lt;/p>
&lt;p>Run the following command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ kubectl --user&lt;span style="color:#56b6c2">=&lt;/span>oidc cluster-info
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It launches the browser and navigates it to http://localhost:8000.
Please log in with your AD account (eg. &lt;a href="mailto:test@example.com">test@example.com&lt;/a>) and password.
After login and grant, you can access the cluster.&lt;/p>
&lt;p>You can switch the current context to dex authentication.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ kubectl config set-context --current --user&lt;span style="color:#56b6c2">=&lt;/span>oidc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Releases</title><link>https://dexidp.io/docs/development/releases/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/development/releases/</guid><description>
&lt;p>Releasing a new version of Dex can be done by one of the core maintainers with push access to the
&lt;a href="https://github.com/dexidp/dex">git repository&lt;/a>.
It&amp;rsquo;s usually good to have an extra pair of eyes ready when tagging a new release though,
so feel free to ask a peer to be ready in case anything goes wrong or you need a review.&lt;/p>
&lt;p>The release process is semi-automated at the moment: artifacts are automatically built and published to
GitHub Container Registry (primary source of container images) and Docker Hub.&lt;/p>
&lt;p>The GitHub release needs to be manually created (use past releases as templates).&lt;/p>
&lt;blockquote>
&lt;p>&lt;em>Note:&lt;/em> this will hopefully be improved in the future.&lt;/p>
&lt;/blockquote>
&lt;h2 id="tagging-a-new-release">Tagging a new release&lt;a class="heading-anchor" href="#tagging-a-new-release" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Make sure you&amp;rsquo;ve &lt;a href="https://github.com/settings/keys">uploaded your GPG key&lt;/a> and
configured git to &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work">use that signing key&lt;/a> either globally or
for the Dex repo. Note that the email the key is issued for must be the email
you use for git.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git config &lt;span style="color:#56b6c2">[&lt;/span>--global&lt;span style="color:#56b6c2">]&lt;/span> user.signingkey &lt;span style="color:#98c379">&amp;#34;{{ GPG key ID }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git config &lt;span style="color:#56b6c2">[&lt;/span>--global&lt;span style="color:#56b6c2">]&lt;/span> user.email &lt;span style="color:#98c379">&amp;#34;{{ Email associated with key }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create a signed tag at the commit you wish to release.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">RELEASE_VERSION&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>v2.0.0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git tag -s -m &lt;span style="color:#98c379">&amp;#34;Release &lt;/span>&lt;span style="color:#e06c75">$RELEASE_VERSION&lt;/span>&lt;span style="color:#98c379">&amp;#34;&lt;/span> &lt;span style="color:#e06c75">$RELEASE_VERSION&lt;/span> &lt;span style="color:#7f848e"># optionally: commit hash as the last argument&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Push that tag to the Dex repo.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git push origin &lt;span style="color:#e06c75">$RELEASE_VERSION&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Draft releases on GitHub and summarize the changes since the last release.
See &lt;a href="https://github.com/dexidp/dex/releases">previous releases&lt;/a> for the expected format.&lt;/p>
&lt;h2 id="patch-releases">Patch releases&lt;a class="heading-anchor" href="#patch-releases" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Occasionally, patch releases might be necessary to fix an urgent bug or vulnerability.&lt;/p>
&lt;p>First, check if there is a release branch for a minor release. Create one if necessary:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">MINOR_RELEASE&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#34;v2.1.0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">RELEASE_BRANCH&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#34;v2.1.x&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git checkout -b &lt;span style="color:#e06c75">$RELEASE_BRANCH&lt;/span> tags/&lt;span style="color:#e06c75">$MINOR_RELEASE&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git push origin &lt;span style="color:#e06c75">$RELEASE_BRANCH&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If a patch version is needed (2.1.1, 2.1.2, etc.), checkout the desired release branch and cherry pick specific commits.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">RELEASE_BRANCH&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#98c379">&amp;#34;v2.1.x&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git checkout &lt;span style="color:#e06c75">$RELEASE_BRANCH&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git checkout -b &lt;span style="color:#98c379">&amp;#34;cherry-picked-change&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git cherry-pick &lt;span style="color:#56b6c2">(&lt;/span>SHA of change&lt;span style="color:#56b6c2">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git push origin &lt;span style="color:#98c379">&amp;#34;cherry-picked-change&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Open a PR onto &lt;code>$RELEASE_BRANCH&lt;/code> to get the changes approved.&lt;/p>
&lt;p>Continue with the regular release process.&lt;/p>
&lt;h2 id="dex-api">Dex API&lt;a class="heading-anchor" href="#dex-api" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>If there are changes in the API, the API version should be bumped to appear correctly in
the &lt;a href="https://pkg.go.dev/github.com/dexidp/dex/api/v2">pkg.go.dev&lt;/a> and be able to
be pulled by tags (via go get or go modules).&lt;/p>
&lt;p>Create a new tag with the &lt;code>api/&lt;/code> path:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">RELEASE_VERSION&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>v2.3.0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git tag -s -m &lt;span style="color:#98c379">&amp;#34;&lt;/span>&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">RELEASE_VERSION&lt;/span>&lt;span style="color:#98c379">}&lt;/span>&lt;span style="color:#98c379"> Dex API release&amp;#34;&lt;/span> &lt;span style="color:#98c379">&amp;#34;api/&lt;/span>&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">RELEASE_VERSION&lt;/span>&lt;span style="color:#98c379">}&lt;/span>&lt;span style="color:#98c379">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Push that tag to the Dex repo.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git push origin &lt;span style="color:#98c379">&amp;#34;api/&lt;/span>&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">RELEASE_VERSION&lt;/span>&lt;span style="color:#98c379">}&lt;/span>&lt;span style="color:#98c379">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docs: Running Integration Tests</title><link>https://dexidp.io/docs/development/integration-tests/</link><pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate><guid>https://dexidp.io/docs/development/integration-tests/</guid><description>
&lt;h2 id="postgres">Postgres&lt;a class="heading-anchor" href="#postgres" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Running database tests locally requires:&lt;/p>
&lt;ul>
&lt;li>Docker&lt;/li>
&lt;/ul>
&lt;p>To run the database integration tests:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>start a postgres container:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker run --name dex-postgres -e &lt;span style="color:#e06c75">POSTGRES_USER&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>postgres -e &lt;span style="color:#e06c75">POSTGRES_DB&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>dex -p 5432:5432 -d postgres:11
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>export the required environment variables:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">DEX_POSTGRES_DATABASE&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>dex &lt;span style="color:#e06c75">DEX_POSTGRES_USER&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>postgres &lt;span style="color:#e06c75">DEX_POSTGRES_PASSWORD&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>postgres &lt;span style="color:#e06c75">DEX_POSTGRES_HOST&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>127.0.0.1:5432
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>run the storage/sql tests:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#7f848e"># sqlite3 takes forever to compile, be sure to install test dependencies&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go &lt;span style="color:#e5c07b">test&lt;/span> -v -i ./storage/sql
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go &lt;span style="color:#e5c07b">test&lt;/span> -v ./storage/sql
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>clean up the postgres container:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker rm -f dex-postgres
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h2 id="etcd">Etcd&lt;a class="heading-anchor" href="#etcd" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>These tests can also be executed using docker:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>start the container (where &lt;code>NODE1&lt;/code> is set to the host IP address):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">NODE1&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>0.0.0.0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker run --name dex-etcd -p 2379:2379 -p 2380:2380 gcr.io/etcd-development/etcd:v3.3.10 &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> /usr/local/bin/etcd --name node1 &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --initial-advertise-peer-urls http://&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">NODE1&lt;/span>&lt;span style="color:#98c379">}&lt;/span>:2380 --listen-peer-urls http://&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">NODE1&lt;/span>&lt;span style="color:#98c379">}&lt;/span>:2380 &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --advertise-client-urls http://&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">NODE1&lt;/span>&lt;span style="color:#98c379">}&lt;/span>:2379 --listen-client-urls http://&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">NODE1&lt;/span>&lt;span style="color:#98c379">}&lt;/span>:2379 &lt;span style="color:#98c379">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#98c379">&lt;/span> --initial-cluster &lt;span style="color:#e06c75">node1&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>http://&lt;span style="color:#98c379">${&lt;/span>&lt;span style="color:#e06c75">NODE1&lt;/span>&lt;span style="color:#98c379">}&lt;/span>:2380
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>run the tests, passing the correct endpoint for this etcd instance in &lt;code>DEX_ETCD_ENDPOINTS&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">DEX_ETCD_ENDPOINTS&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>http://localhost:2379 go &lt;span style="color:#e5c07b">test&lt;/span> -v ./storage/etcd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>clean up the etcd container: &lt;code>docker rm -f dex-etcd&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="kubernetes">Kubernetes&lt;a class="heading-anchor" href="#kubernetes" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>Running integration tests for Kubernetes storage requires the &lt;code>DEX_KUBERNETES_CONFIG_PATH&lt;/code> environment variable
be set with the path to kubeconfig file of the existing cluster. For tests, it is ok to use &amp;ldquo;mini&amp;rdquo; Kubernetes distributive, e.g., &lt;a href="https://github.com/kubernetes-sigs/kind/">KinD&lt;/a>, &lt;a href="https://github.com/ubuntu/microk8s">Microk8s&lt;/a>.&lt;/p>
&lt;p>Example KinD cluster test run:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Install KinD using the instructions from the &lt;a href="https://kind.sigs.k8s.io/docs/user/quick-start/#installation">official website&lt;/a>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Run tests by executing the following commands:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">DEX_KUBERNETES_CONFIG_PATH&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#c678dd">$(&lt;/span>mktemp /tmp/kubeconfig.XXXXXXXX&lt;span style="color:#c678dd">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kind create cluster --kubeconfig &lt;span style="color:#98c379">&amp;#34;&lt;/span>&lt;span style="color:#e06c75">$DEX_KUBERNETES_CONFIG_PATH&lt;/span>&lt;span style="color:#98c379">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go &lt;span style="color:#e5c07b">test&lt;/span> -v ./storage/kubernetes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>To clean up, run:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>rm -f &lt;span style="color:#98c379">&amp;#34;&lt;/span>&lt;span style="color:#e06c75">$DEX_KUBERNETES_CONFIG_PATH&lt;/span>&lt;span style="color:#98c379">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">unset&lt;/span> DEX_KUBERNETES_CONFIG_PATH
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>kind delete cluster
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;h2 id="ldap">LDAP&lt;a class="heading-anchor" href="#ldap" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;p>The LDAP integration tests require &lt;a href="https://www.openldap.org/">OpenLDAP&lt;/a> installed on the host machine. To run them, use &lt;code>go test&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e5c07b">export&lt;/span> &lt;span style="color:#e06c75">DEX_LDAP_TESTS&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>&lt;span style="color:#d19a66">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go &lt;span style="color:#e5c07b">test&lt;/span> -v ./connector/ldap/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To quickly stand up a LDAP server for development, see the LDAP &lt;a href="https://dexidp.io/docs/connectors/ldap/#getting-started">&lt;em>&amp;ldquo;Getting started&amp;rdquo;&lt;/em>&lt;/a> example. This also requires OpenLDAP installed on the host.&lt;/p>
&lt;p>To stand up a containerized LDAP server run the OpenLDAP docker image:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ sudo docker run --hostname ldap.example.org --name openldap-container --detach osixia/openldap:1.1.6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>By default TLS is enabled and a certificate is created with the container hostname, which in this case is &amp;ldquo;ldap.example.org&amp;rdquo;. It will create an empty LDAP for the company Example Inc. and the domain example.org. By default the admin has the password admin.&lt;/p>
&lt;p>Add new users and groups (sample .ldif file included at the end):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ sudo docker &lt;span style="color:#e5c07b">exec&lt;/span> openldap-container ldapadd -x -D &lt;span style="color:#98c379">&amp;#34;cn=admin,dc=example,dc=org&amp;#34;&lt;/span> -w admin -f &amp;lt;path to .ldif&amp;gt; -h ldap.example.org -ZZ
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Verify that the added entries are in your directory with ldapsearch :&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ sudo docker &lt;span style="color:#e5c07b">exec&lt;/span> openldap-container ldapsearch -x -h localhost -b &lt;span style="color:#e06c75">dc&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org -D &lt;span style="color:#98c379">&amp;#34;cn=admin,dc=example,dc=org&amp;#34;&lt;/span> -w admin
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The .ldif file should contain seed data. Example file contents:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">cn&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>Test1,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: organizationalRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cn: Test1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">cn&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>Test2,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: organizationalRole
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cn: Test2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">ou&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>groups,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ou: groups
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: top
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: organizationalUnit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dn: &lt;span style="color:#e06c75">cn&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>tstgrp,ou&lt;span style="color:#56b6c2">=&lt;/span>groups,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: top
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>objectClass: groupOfNames
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>member: &lt;span style="color:#e06c75">cn&lt;/span>&lt;span style="color:#56b6c2">=&lt;/span>Test1,dc&lt;span style="color:#56b6c2">=&lt;/span>example,dc&lt;span style="color:#56b6c2">=&lt;/span>org
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cn: tstgrp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="saml">SAML&lt;a class="heading-anchor" href="#saml" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h2>
&lt;h3 id="okta">Okta&lt;a class="heading-anchor" href="#okta" aria-label="Copy link to this section" tabindex="-1">&lt;/a>&lt;/h3>
&lt;p>The Okta identity provider supports free accounts for developers to test their implementation against. This document describes configuring an Okta application to test dex&amp;rsquo;s SAML connector.&lt;/p>
&lt;p>First, &lt;a href="https://www.okta.com/developer/signup/">sign up for a developer account&lt;/a>. Then, to create a SAML application:&lt;/p>
&lt;ul>
&lt;li>Go to the admin screen.&lt;/li>
&lt;li>Click &amp;ldquo;Add application&amp;rdquo;&lt;/li>
&lt;li>Click &amp;ldquo;Create New App&amp;rdquo;&lt;/li>
&lt;li>Choose &amp;ldquo;SAML 2.0&amp;rdquo; and press &amp;ldquo;Create&amp;rdquo;&lt;/li>
&lt;li>Configure SAML
&lt;ul>
&lt;li>Enter &lt;code>http://127.0.0.1:5556/dex/callback&lt;/code> for &amp;ldquo;Single sign on URL&amp;rdquo;&lt;/li>
&lt;li>Enter &lt;code>http://127.0.0.1:5556/dex/callback&lt;/code> for &amp;ldquo;Audience URI (SP Entity ID)&amp;rdquo;&lt;/li>
&lt;li>Under &amp;ldquo;ATTRIBUTE STATEMENTS (OPTIONAL)&amp;rdquo; add an &amp;ldquo;email&amp;rdquo; and &amp;ldquo;name&amp;rdquo; attribute. The values should be something like &lt;code>user:email&lt;/code> and &lt;code>user:firstName&lt;/code>, respectively.&lt;/li>
&lt;li>Under &amp;ldquo;GROUP ATTRIBUTE STATEMENTS (OPTIONAL)&amp;rdquo; add a &amp;ldquo;groups&amp;rdquo; attribute. Use the &amp;ldquo;Regexp&amp;rdquo; filter &lt;code>.*&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>After the application&amp;rsquo;s created, assign yourself to the app.&lt;/p>
&lt;ul>
&lt;li>&amp;ldquo;Applications&amp;rdquo; &amp;gt; &amp;ldquo;Applications&amp;rdquo;&lt;/li>
&lt;li>Click on your application then under the &amp;ldquo;People&amp;rdquo; tab press the &amp;ldquo;Assign to People&amp;rdquo; button and add yourself.&lt;/li>
&lt;/ul>
&lt;p>At the app, go to the &amp;ldquo;Sign On&amp;rdquo; tab and then click &amp;ldquo;View Setup Instructions&amp;rdquo;. Use those values to fill out the following connector in &lt;code>examples/config-dev.yaml&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e06c75">connectors&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#e06c75">type&lt;/span>: saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">id&lt;/span>: saml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">name&lt;/span>: Okta
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">ssoURL&lt;/span>: ( &amp;#34;Identity Provider Single Sign-On URL&amp;#34; )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">caData&lt;/span>: ( base64&amp;#39;d value of &amp;#34;X.509 Certificate&amp;#34; )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">redirectURI&lt;/span>: http://127.0.0.1:5556/dex/callback
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">usernameAttr&lt;/span>: name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">emailAttr&lt;/span>: email
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e06c75">groupsAttr&lt;/span>: groups
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Start both dex and the example app, and try logging in (requires not requesting a refresh token).&lt;/p></description></item></channel></rss>