From 460f48320eaf1dfc858dd3b2882511f8cc230598 Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Thu, 4 Jan 2018 13:50:14 -0800 Subject: [PATCH] Documentation: restructure connector docs to a single folder --- Documentation/authproxy.md | 139 +------------ Documentation/connectors/authproxy.md | 138 +++++++++++++ Documentation/connectors/github.md | 109 ++++++++++ Documentation/connectors/gitlab.md | 29 +++ Documentation/connectors/ldap.md | 284 +++++++++++++++++++++++++ Documentation/connectors/linkedin.md | 27 +++ Documentation/connectors/microsoft.md | 112 ++++++++++ Documentation/connectors/oidc.md | 55 +++++ Documentation/connectors/saml.md | 105 ++++++++++ Documentation/github-connector.md | 110 +--------- Documentation/gitlab-connector.md | 30 +-- Documentation/ldap-connector.md | 285 +------------------------- Documentation/linkedin-connector.md | 28 +-- Documentation/microsoft-connector.md | 113 +--------- Documentation/oidc-connector.md | 56 +---- Documentation/saml-connector.md | 106 +--------- README.md | 16 +- 17 files changed, 875 insertions(+), 867 deletions(-) create mode 100644 Documentation/connectors/authproxy.md create mode 100644 Documentation/connectors/github.md create mode 100644 Documentation/connectors/gitlab.md create mode 100644 Documentation/connectors/ldap.md create mode 100644 Documentation/connectors/linkedin.md create mode 100644 Documentation/connectors/microsoft.md create mode 100644 Documentation/connectors/oidc.md create mode 100644 Documentation/connectors/saml.md diff --git a/Documentation/authproxy.md b/Documentation/authproxy.md index 2e12ab09..759c97bd 100644 --- a/Documentation/authproxy.md +++ b/Documentation/authproxy.md @@ -1,138 +1 @@ -# Authenticating proxy - -NOTE: This connector is experimental and may change in the future. - -## Overview - -The `authproxy` connector returns identities based on authentication which your -front-end web server performs. Dex consumes the `X-Remote-User` header set by -the proxy, which is then used as the user's email address. - -__The proxy MUST remove any `X-Remote-*` headers set by the client, for any URL -path, before the request is forwarded to dex.__ - -The connector does not support refresh tokens or groups. - -## Configuration - -The `authproxy` 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. The connector takes no configuration other than a `name` and `id`: - -```yaml -connectors: -# Slack login implemented by an authenticating proxy, not by dex. -- type: authproxy - id: slack - name: Slack -``` - -The proxy only needs to authenticate the user when they attempt to visit the -callback URL path: - -``` -( dex issuer URL )/callback/( connector id )?( url query ) -``` - -For example, if dex is running at `https://auth.example.com/dex` and the connector -ID is `slack`, the callback URL would look like: - -``` -https://auth.example.com/dex/callback/slack?state=xdg3z6quhrhwaueo5iysvliqf -``` - -The proxy should login the user then return them to the exact URL (inlucing the -query), setting `X-Remote-User` to the user's email before proxying the request -to dex. - -## Configuration example - Apache 2 - -The following is an example config file that can be used by the external -connector to authenticate a user. - -```yaml -connectors: -- type: authproxy - id: myBasicAuth - name: HTTP Basic Auth -``` - -The authproxy connector assumes that you configured your front-end web server -such that it performs authentication for the `/dex/callback/myBasicAuth` -location and provides the result in the X-Remote-User HTTP header. The following -configuration will work for Apache 2.4.10+: - -``` - - ProxyPass "http://localhost:5556/dex/" - ProxyPassReverse "http://localhost:5556/dex/" - - # Strip the X-Remote-User header from all requests except for the ones - # where we override it. - RequestHeader unset X-Remote-User - - - - AuthType Basic - AuthName "db.debian.org webPassword" - AuthBasicProvider file - AuthUserFile "/etc/apache2/debian-web-pw.htpasswd" - Require valid-user - - # Defense in depth: clear the Authorization header so that - # Debian Web Passwords never even reach dex. - RequestHeader unset Authorization - - # Requires Apache 2.4.10+ - RequestHeader set X-Remote-User expr=%{REMOTE_USER}@debian.org - - ProxyPass "http://localhost:5556/dex/callback/myBasicAuth" - ProxyPassReverse "http://localhost:5556/dex/callback/myBasicAuth" - -``` - -## Full Apache2 setup - -After installing your Linux distribution’s Apache2 package, place the following -virtual host configuration in e.g. `/etc/apache2/sites-available/sso.conf`: - -``` - - ServerName sso.example.net - - ServerAdmin webmaster@localhost - DocumentRoot /var/www/html - - ErrorLog ${APACHE_LOG_DIR}/error.log - CustomLog ${APACHE_LOG_DIR}/access.log combined - - - ProxyPass "http://localhost:5556/dex/" - ProxyPassReverse "http://localhost:5556/dex/" - - # Strip the X-Remote-User header from all requests except for the ones - # where we override it. - RequestHeader unset X-Remote-User - - - - AuthType Basic - AuthName "db.debian.org webPassword" - AuthBasicProvider file - AuthUserFile "/etc/apache2/debian-web-pw.htpasswd" - Require valid-user - - # Defense in depth: clear the Authorization header so that - # Debian Web Passwords never even reach dex. - RequestHeader unset Authorization - - # Requires Apache 2.4.10+ - RequestHeader set X-Remote-User expr=%{REMOTE_USER}@debian.org - - ProxyPass "http://localhost:5556/dex/callback/myBasicAuth" - ProxyPassReverse "http://localhost:5556/dex/callback/myBasicAuth" - - -``` - -Then, enable it using `a2ensite sso.conf`, followed by a restart of Apache2. +This document has moved to [connectors/authproxy.md](connectors/authproxy.md). diff --git a/Documentation/connectors/authproxy.md b/Documentation/connectors/authproxy.md new file mode 100644 index 00000000..2e12ab09 --- /dev/null +++ b/Documentation/connectors/authproxy.md @@ -0,0 +1,138 @@ +# Authenticating proxy + +NOTE: This connector is experimental and may change in the future. + +## Overview + +The `authproxy` connector returns identities based on authentication which your +front-end web server performs. Dex consumes the `X-Remote-User` header set by +the proxy, which is then used as the user's email address. + +__The proxy MUST remove any `X-Remote-*` headers set by the client, for any URL +path, before the request is forwarded to dex.__ + +The connector does not support refresh tokens or groups. + +## Configuration + +The `authproxy` 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. The connector takes no configuration other than a `name` and `id`: + +```yaml +connectors: +# Slack login implemented by an authenticating proxy, not by dex. +- type: authproxy + id: slack + name: Slack +``` + +The proxy only needs to authenticate the user when they attempt to visit the +callback URL path: + +``` +( dex issuer URL )/callback/( connector id )?( url query ) +``` + +For example, if dex is running at `https://auth.example.com/dex` and the connector +ID is `slack`, the callback URL would look like: + +``` +https://auth.example.com/dex/callback/slack?state=xdg3z6quhrhwaueo5iysvliqf +``` + +The proxy should login the user then return them to the exact URL (inlucing the +query), setting `X-Remote-User` to the user's email before proxying the request +to dex. + +## Configuration example - Apache 2 + +The following is an example config file that can be used by the external +connector to authenticate a user. + +```yaml +connectors: +- type: authproxy + id: myBasicAuth + name: HTTP Basic Auth +``` + +The authproxy connector assumes that you configured your front-end web server +such that it performs authentication for the `/dex/callback/myBasicAuth` +location and provides the result in the X-Remote-User HTTP header. The following +configuration will work for Apache 2.4.10+: + +``` + + ProxyPass "http://localhost:5556/dex/" + ProxyPassReverse "http://localhost:5556/dex/" + + # Strip the X-Remote-User header from all requests except for the ones + # where we override it. + RequestHeader unset X-Remote-User + + + + AuthType Basic + AuthName "db.debian.org webPassword" + AuthBasicProvider file + AuthUserFile "/etc/apache2/debian-web-pw.htpasswd" + Require valid-user + + # Defense in depth: clear the Authorization header so that + # Debian Web Passwords never even reach dex. + RequestHeader unset Authorization + + # Requires Apache 2.4.10+ + RequestHeader set X-Remote-User expr=%{REMOTE_USER}@debian.org + + ProxyPass "http://localhost:5556/dex/callback/myBasicAuth" + ProxyPassReverse "http://localhost:5556/dex/callback/myBasicAuth" + +``` + +## Full Apache2 setup + +After installing your Linux distribution’s Apache2 package, place the following +virtual host configuration in e.g. `/etc/apache2/sites-available/sso.conf`: + +``` + + ServerName sso.example.net + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/html + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + + ProxyPass "http://localhost:5556/dex/" + ProxyPassReverse "http://localhost:5556/dex/" + + # Strip the X-Remote-User header from all requests except for the ones + # where we override it. + RequestHeader unset X-Remote-User + + + + AuthType Basic + AuthName "db.debian.org webPassword" + AuthBasicProvider file + AuthUserFile "/etc/apache2/debian-web-pw.htpasswd" + Require valid-user + + # Defense in depth: clear the Authorization header so that + # Debian Web Passwords never even reach dex. + RequestHeader unset Authorization + + # Requires Apache 2.4.10+ + RequestHeader set X-Remote-User expr=%{REMOTE_USER}@debian.org + + ProxyPass "http://localhost:5556/dex/callback/myBasicAuth" + ProxyPassReverse "http://localhost:5556/dex/callback/myBasicAuth" + + +``` + +Then, enable it using `a2ensite sso.conf`, followed by a restart of Apache2. diff --git a/Documentation/connectors/github.md b/Documentation/connectors/github.md new file mode 100644 index 00000000..d7a15b67 --- /dev/null +++ b/Documentation/connectors/github.md @@ -0,0 +1,109 @@ +# Authentication through GitHub + +## Overview + +One of the login options for dex uses the GitHub OAuth2 flow to identify the end user through their GitHub account. + +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, __dex stores a readonly GitHub access token in its backing datastore.__ Users that reject dex's access through GitHub will also revoke all dex clients which authenticated them through GitHub. + +## Caveats + +* A user must explicitly [request][github-request-org-access] an [organization][github-orgs] give dex [resource access][github-approve-org-access]. 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. + +## Configuration + +Register a new application with [GitHub][github-oauth2] ensuring the callback URL is `(dex issuer)/callback`. For example if dex is listening at the non-root path `https://auth.example.com/dex` the callback would be `https://auth.example.com/dex/callback`. + +The following is an example of a configuration for `examples/config-dev.yaml`: + +```yaml +connectors: +- type: github + # Required field for connector id. + id: github + # Required field for connector name. + name: GitHub + config: + # Credentials can be string literals or pulled from the environment. + clientID: $GITHUB_CLIENT_ID + clientSecret: $GITHUB_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback + # Optional organizations and teams, communicated through the "groups" scope. + # + # NOTE: This is an EXPERIMENTAL config option and will likely change. + # + # Legacy 'org' field. 'org' and 'orgs' cannot be used simultaneously. A user + # MUST be a member of the following org to authenticate with dex. + # org: my-organization + # + # Dex queries the following organizations for group information if the + # "groups" scope is provided. Group claims are formatted as "(org):(team)". + # For example if a user is part of the "engineering" team of the "coreos" + # org, the group claim would include "coreos:engineering". + # + # A user MUST be a member of at least one of the following orgs to + # authenticate with dex. + orgs: + - name: my-organization + # Include all teams as claims. + - name: my-organization-with-teams + # A white list of teams. Only include group claims for these teams. + teams: + - red-team + - blue-team +``` + +## GitHub Enterprise + +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: + +```yaml +connectors: +- type: github + # Required field for connector id. + id: github + # Required field for connector name. + name: GitHub + config: + # Required fields. Dex must be pre-registered with GitHub Enterprise + # to get the following values. + # Credentials can be string literals or pulled from the environment. + clientID: $GITHUB_CLIENT_ID + clientSecret: $GITHUB_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback + # Optional organizations and teams, communicated through the "groups" scope. + # + # NOTE: This is an EXPERIMENTAL config option and will likely change. + # + # Legacy 'org' field. 'org' and 'orgs' cannot be used simultaneously. A user + # MUST be a member of the following org to authenticate with dex. + # org: my-organization + # + # Dex queries the following organizations for group information if the + # "groups" scope is provided. Group claims are formatted as "(org):(team)". + # For example if a user is part of the "engineering" team of the "coreos" + # org, the group claim would include "coreos:engineering". + # + # A user MUST be a member of at least one of the following orgs to + # authenticate with dex. + orgs: + - name: my-organization + # Include all teams as claims. + - name: my-organization-with-teams + # A white list of teams. Only include group claims for these teams. + teams: + - red-team + - blue-team + # Required ONLY for GitHub Enterprise. + # This is the Hostname of the GitHub Enterprise account listed on the + # management console. Ensure this domain is routable on your network. + hostName: git.example.com + # ONLY for GitHub Enterprise. Optional field. + # Used to support self-signed or untrusted CA root certificates. + rootCA: /etc/dex/ca.crt +``` + +[github-oauth2]: https://github.com/settings/applications/new +[github-orgs]: https://developer.github.com/v3/orgs/ +[github-request-org-access]: https://help.github.com/articles/requesting-organization-approval-for-oauth-apps/ +[github-approve-org-access]: https://help.github.com/articles/approving-oauth-apps-for-your-organization/ diff --git a/Documentation/connectors/gitlab.md b/Documentation/connectors/gitlab.md new file mode 100644 index 00000000..fc797e9f --- /dev/null +++ b/Documentation/connectors/gitlab.md @@ -0,0 +1,29 @@ +# Authentication through Gitlab + +## Overview + +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 [gitlab.com](gitlab.com), GitLab community or enterprise edition. + +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, __dex stores a readonly GitLab access token in its backing datastore.__ Users that reject dex's access through GitLab will also revoke all dex clients which authenticated them through GitLab. + +## Configuration + +Register a new application via `User Settings -> Applications` ensuring the callback URL is `(dex issuer)/callback`. For example if dex is listening at the non-root path `https://auth.example.com/dex` the callback would be `https://auth.example.com/dex/callback`. + +The following is an example of a configuration for `examples/config-dev.yaml`: + +```yaml +connectors: + - type: gitlab + # Required field for connector id. + id: gitlab + # Required field for connector name. + name: GitLab + config: + # optional, default = https://www.gitlab.com + baseURL: https://www.gitlab.com + # Credentials can be string literals or pulled from the environment. + clientID: $GITLAB_APPLICATION_ID + clientSecret: $GITLAB_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback +``` diff --git a/Documentation/connectors/ldap.md b/Documentation/connectors/ldap.md new file mode 100644 index 00000000..0a0813c7 --- /dev/null +++ b/Documentation/connectors/ldap.md @@ -0,0 +1,284 @@ +# Authentication through LDAP + +## Overview + +The LDAP connector allows email/password based authentication, backed by a LDAP directory. + +The connector executes two primary queries: + +1. Finding the user based on the end user's credentials. +2. Searching for groups using the user entry. + +## Getting started + +The dex repo contains a basic LDAP setup using [OpenLDAP][openldap]. + +First start the LDAP server using the example script. This will run the OpenLDAP daemon and seed it with a initial set of users. + +``` +./scripts/slapd.sh +``` + +This script sets the LDAP daemon to debug mode, and is expected to print several error messages which are normal. Once the server is up, run dex. + +``` +./bin/dex serve examples/config-ldap.yaml +``` + +Then run the OAuth client in another terminal. + +``` +./bin/example-app +``` + +Go to [http://localhost:5555](http://localhost:5555), login and enter the username and password of the LDAP user: `janedoe@example.com`/`foo`. Add the "groups" scope as part of the initial redirect to add group information from the LDAP server. + +## Security considerations + +Dex attempts to bind with the backing LDAP server using the end user's _plain text password_. Though some LDAP implementations allow passing hashed passwords, dex doesn't support hashing and instead _strongly recommends that all administrators just use TLS_. This can often be achieved by using port 636 instead of 389, and administrators that choose 389 are actively leaking passwords. + +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 _users who configure LDAP login using 389 are not covered by any compatibility guarantees with future releases._ + +## Configuration + +User entries are expected to have an email attribute (configurable through `emailAttr`), and a display name attribute (configurable through `nameAttr`). `*Attr` attributes could be set to "DN" in situations where it is needed but not available elsewhere, and if "DN" attribute does not exist in the record. + +The following is an example config file that can be used by the LDAP connector to authenticate a user. + +```yaml +connectors: +- type: ldap + # Required field for connector id. + id: ldap + # Required field for connector name. + name: LDAP + config: + # Host and optional port of the LDAP server in the form "host:port". + # If the port is not supplied, it will be guessed based on "insecureNoSSL", + # and "startTLS" flags. 389 for insecure or StartTLS connections, 636 + # otherwise. + host: ldap.example.com:636 + + # Following field is required if the LDAP host is not using TLS (port 389). + # Because this option inherently leaks passwords to anyone on the same network + # as dex, THIS OPTION MAY BE REMOVED WITHOUT WARNING IN A FUTURE RELEASE. + # + # insecureNoSSL: true + + # If a custom certificate isn't provide, this option can be used to turn on + # TLS certificate checks. As noted, it is insecure and shouldn't be used outside + # of explorative phases. + # + # insecureSkipVerify: true + + # When connecting to the server, connect using the ldap:// protocol then issue + # a StartTLS command. If unspecified, connections will use the ldaps:// protocol + # + # startTLS: true + + # Path to a trusted root certificate file. Default: use the host's root CA. + rootCA: /etc/dex/ldap.ca + + # A raw certificate file can also be provided inline. + # rootCAData: ( base64 encoded PEM file ) + + # The DN and password for an application service account. The connector uses + # these credentials to search for users and groups. Not required if the LDAP + # server provides access for anonymous auth. + # Please note that if the bind password contains a `$`, it has to be saved in an + # environment variable which should be given as the value to `bindPW`. + bindDN: uid=seviceaccount,cn=users,dc=example,dc=com + bindPW: password + + # The attribute to display in the provided password prompt. If unset, will + # display "Username" + usernamePrompt: SSO Username + + # User search maps a username and password entered by a user to a LDAP entry. + userSearch: + # BaseDN to start the search from. It will translate to the query + # "(&(objectClass=person)(uid=))". + baseDN: cn=users,dc=example,dc=com + # Optional filter to apply when searching the directory. + filter: "(objectClass=person)" + + # username attribute used for comparing user entries. This will be translated + # and combined with the other filter as "(=)". + username: uid + # The following three fields are direct mappings of attributes on the user entry. + # String representation of the user. + idAttr: uid + # Required. Attribute to map to Email. + emailAttr: mail + # Maps to display name of users. No default value. + nameAttr: name + + # Group search queries for groups given a user entry. + groupSearch: + # BaseDN to start the search from. It will translate to the query + # "(&(objectClass=group)(member=))". + baseDN: cn=groups,dc=freeipa,dc=example,dc=com + # Optional filter to apply when searching the directory. + filter: "(objectClass=group)" + + # Following two fields are used to match a user to a group. It adds an additional + # requirement to the filter that an attribute in the group must match the user's + # attribute value. + userAttr: uid + groupAttr: member + + # Represents group name. + nameAttr: name +``` + +The LDAP connector first initializes a connection to the LDAP directory using the `bindDN` and `bindPW`. It then tries to search for the given `username` and bind as that user to verify their password. +Searches that return multiple entries are considered ambiguous and will return an error. + +## Example: Mapping a schema to a search config + +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 `ldapsearch`. For `rpm` based distros run: + +``` +sudo dnf install openldap-clients +``` + +For `apt-get`: + +``` +sudo apt-get install ldap-utils +``` + +For smaller user directories it may be practical to dump the entire contents and search by hand. + +``` +ldapsearch -x -h ldap.example.org -b 'dc=example,dc=org' | less +``` + +First, find a user entry. User entries declare users who can login to LDAP connector using username and password. + +``` +dn: uid=jdoe,cn=users,cn=compat,dc=example,dc=org +cn: Jane Doe +objectClass: posixAccount +objectClass: ipaOverrideTarget +objectClass: top +gidNumber: 200015 +gecos: Jane Doe +uidNumber: 200015 +loginShell: /bin/bash +homeDirectory: /home/jdoe +mail: jane.doe@example.com +uid: janedoe +``` + +Compose a user search which returns this user. + +```yaml +userSearch: + # The directory directly above the user entry. + baseDN: cn=users,cn=compat,dc=example,dc=org + filter: "(objectClass=posixAccount)" + + # Expect user to enter "janedoe" when logging in. + username: uid + + # Use the full DN as an ID. + idAttr: DN + + # When an email address is not available, use another value unique to the user, like uid. + emailAttr: mail + nameAttr: gecos +``` + +Second, find a group entry. + +``` +dn: cn=developers,cn=groups,cn=compat,dc=example,dc=org +memberUid: janedoe +memberUid: johndoe +gidNumber: 200115 +objectClass: posixGroup +objectClass: ipaOverrideTarget +objectClass: top +cn: developers +``` + +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's list of memberUid attributes. + +```yaml +groupSearch: + # The directory directly above the group entry. + baseDN: cn=groups,cn=compat,dc=example,dc=org + filter: "(objectClass=posixGroup)" + + # The group search needs to match the "uid" attribute on + # the user with the "memberUid" attribute on the group. + userAttr: uid + groupAttr: memberUid + + # Unique name of the group. + nameAttr: cn +``` +To extract group specific information the `DN` can be used in the `userAttr` field. + +``` +# Top level object example.coma in LDIF file. +dn: dc=example,dc=com +objectClass: top +objectClass: dcObject +objectClass: organization +dc: example +``` + +The following is an example of a group query would match any entry with member=: + +```yaml +groupSearch: + # BaseDN to start the search from. It will translate to the query + # "(&(objectClass=group)(member=))". + baseDN: cn=groups,cn=compat,dc=example,dc=com + # Optional filter to apply when searching the directory. + filter: "(objectClass=group)" + + userAttr: DN # Use "DN" here not "uid" + groupAttr: member + + nameAttr: name +``` + +## Example: Searching a FreeIPA server with groups + +The following configuration will allow the LDAP connector to search a FreeIPA directory using an LDAP filter. + +```yaml + +connectors: +- type: ldap + id: ldap + name: LDAP + config: + # host and port of the LDAP server in form "host:port". + host: freeipa.example.com:636 + # freeIPA server's CA + rootCA: ca.crt + userSearch: + # Would translate to the query "(&(objectClass=person)(uid=))". + baseDN: cn=users,dc=freeipa,dc=example,dc=com + filter: "(objectClass=posixAccount)" + username: uid + idAttr: uid + # Required. Attribute to map to Email. + emailAttr: mail + # Entity attribute to map to display name of users. + groupSearch: + # Would translate to the query "(&(objectClass=group)(member=))". + baseDN: cn=groups,dc=freeipa,dc=example,dc=com + filter: "(objectClass=group)" + userAttr: uid + groupAttr: member + nameAttr: name +``` + +If the search finds an entry, it will attempt to use the provided password to bind as that user entry. + +[openldap]: https://www.openldap.org/ diff --git a/Documentation/connectors/linkedin.md b/Documentation/connectors/linkedin.md new file mode 100644 index 00000000..646ee243 --- /dev/null +++ b/Documentation/connectors/linkedin.md @@ -0,0 +1,27 @@ +# Authentication through LinkedIn + +## Overview + +One of the login options for dex uses the LinkedIn OAuth2 flow to identify the end user through their LinkedIn account. + +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, __dex stores a readonly LinkedIn access token in its backing datastore.__ Users that reject dex's access through LinkedIn will also revoke all dex clients which authenticated them through LinkedIn. + +## Configuration + +Register a new application via `My Apps -> Create Application` ensuring the callback URL is `(dex issuer)/callback`. For example if dex is listening at the non-root path `https://auth.example.com/dex` the callback would be `https://auth.example.com/dex/callback`. + +The following is an example of a configuration for `examples/config-dev.yaml`: + +```yaml +connectors: + - type: linkedin + # Required field for connector id. + id: linkedin + # Required field for connector name. + name: LinkedIn + config: + # Credentials can be string literals or pulled from the environment. + clientID: $LINKEDIN_APPLICATION_ID + clientSecret: $LINKEDIN_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback +``` diff --git a/Documentation/connectors/microsoft.md b/Documentation/connectors/microsoft.md new file mode 100644 index 00000000..11024a6d --- /dev/null +++ b/Documentation/connectors/microsoft.md @@ -0,0 +1,112 @@ +# Authentication through Microsoft + +## Overview + +One of the login options for dex uses the Microsoft OAuth2 flow to identify the +end user through their Microsoft account. + +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, __dex stores a readonly +Microsoft access and refresh tokens in its backing datastore.__ Users that +reject dex's access through Microsoft will also revoke all dex clients which +authenticated them through Microsoft. + +### Caveats + +`groups` claim in dex is only supported when `tenant` is specified in Microsoft +connector config. 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: + + - when registering dex application on https://apps.dev.microsoft.com add + an explicit `Directory.Read.All` permission to the list of __Delegated + Permissions__ + - open the following link in your browser and log in under organization + administrator account: + +`https://login.microsoftonline.com//adminconsent?client_id=` + +## Configuration + +Register a new application on https://apps.dev.microsoft.com via `Add an app` +ensuring the callback URL is `(dex issuer)/callback`. For example if dex +is listening at the non-root path `https://auth.example.com/dex` the callback +would be `https://auth.example.com/dex/callback`. + +The following is an example of a configuration for `examples/config-dev.yaml`: + +```yaml +connectors: + - type: microsoft + # Required field for connector id. + id: microsoft + # Required field for connector name. + name: Microsoft + config: + # Credentials can be string literals or pulled from the environment. + clientID: $MICROSOFT_APPLICATION_ID + clientSecret: $MICROSOFT_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback +``` + +`tenant` 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 `tenant` parameter to one of the following: + +- `common`- both personal and business/school accounts can authenticate in dex + via Microsoft (default) +- `consumers` - only personal accounts can authenticate in dex +- `organizations` - only business/school accounts can authenticate in dex +- `` or `` - only accounts belonging to specific + tenant identified by either `` or `` can + authenticate in dex + +For example, the following snippet configures dex to only allow business/school +accounts: + +```yaml +connectors: + - type: microsoft + # Required field for connector id. + id: microsoft + # Required field for connector name. + name: Microsoft + config: + # Credentials can be string literals or pulled from the environment. + clientID: $MICROSOFT_APPLICATION_ID + clientSecret: $MICROSOFT_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback + tenant: organizations +``` + +### Groups + +When the `groups` claim is present in a request to dex __and__ `tenant` is +configured, dex will query Microsoft API to obtain a list of groups the user is +a member of. `onlySecurityGroups` configuration option restricts the list to +include only security groups. By default all groups (security, Office 365, +mailing lists) are included. + +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: + +```yaml +connectors: + - type: microsoft + # Required field for connector id. + id: microsoft + # Required field for connector name. + name: Microsoft + config: + # Credentials can be string literals or pulled from the environment. + clientID: $MICROSOFT_APPLICATION_ID + clientSecret: $MICROSOFT_CLIENT_SECRET + redirectURI: http://127.0.0.1:5556/dex/callback + tenant: myorg.onmicrosoft.com + groups: + - developers + - devops +``` diff --git a/Documentation/connectors/oidc.md b/Documentation/connectors/oidc.md new file mode 100644 index 00000000..76b4e457 --- /dev/null +++ b/Documentation/connectors/oidc.md @@ -0,0 +1,55 @@ +# Authentication through an OpenID Connect provider + +## Overview + +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 [_An overview of OpenID Connect_][oidc-doc]. + +Prominent examples of OpenID Connect providers include Google Accounts, Salesforce, and Azure AD v2 ([not v1][azure-ad-v1]). + +## Caveats + +This connector does not support the "groups" claim. Progress for this is tracked in [issue #1065][issue-1065]. + +When using refresh tokens, changes to the upstream claims aren't propegated to the id_token returned by dex. If a user's email changes, the "email" claim returned by dex won't change unless the user logs in again. Progress for this is tracked in [issue #863][issue-863]. + +## Configuration + +```yaml +connectors: +- type: oidc + id: google + name: Google + config: + # Canonical URL of the provider, also used for configuration discovery. + # This value MUST match the value returned in the provider config discovery. + # + # See: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig + issuer: https://accounts.google.com + + # Connector config values starting with a "$" will read from the environment. + clientID: $GOOGLE_CLIENT_ID + clientSecret: $GOOGLE_CLIENT_SECRET + + # Dex's issuer URL + "/callback" + redirectURI: http://127.0.0.1:5556/callback + + + # Some providers require passing client_secret via POST parameters instead + # of basic auth, despite the OAuth2 RFC discouraging it. Many of these + # cases are caught internally, but some may need to uncommented the + # following field. + # + # basicAuthUnsupported: true + + # Google supports whitelisting allowed domains when using G Suite + # (Google Apps). The following field can be set to a list of domains + # that can log in: + # + # hostedDomains: + # - example.com +``` + +[oidc-doc]: openid-connect.md +[issue-863]: https://github.com/coreos/dex/issues/863 +[issue-1065]: https://github.com/coreos/dex/issues/1065 +[azure-ad-v1]: https://github.com/coreos/go-oidc/issues/133 diff --git a/Documentation/connectors/saml.md b/Documentation/connectors/saml.md new file mode 100644 index 00000000..62cf6a7f --- /dev/null +++ b/Documentation/connectors/saml.md @@ -0,0 +1,105 @@ +# Authentication through SAML 2.0 + +## Overview + +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. + +The connector uses the value of the `NameID` element as the user's unique identifier which dex assumes is both unique and never changes. Use the `nameIDPolicyFormat` to ensure this is set to a value which satisfies these requirements. + +Unlike some clients which will process unprompted AuthnResponses, dex must send the initial AuthnRequest and validates the response's InResponseTo value. + +## Caveats + +__The connector doesn't support refresh tokens__ since the SAML 2.0 protocol doesn't provide a way to requery a provider without interaction. If the "offline_access" scope is requested, it will be ignored. + +The connector doesn't support signed AuthnRequests or encrypted attributes. + +## Configuration + +```yaml +connectors: +- type: saml + # Required field for connector id. + id: saml + # Required field for connector name. + name: SAML + config: + # SSO URL used for POST value. + ssoURL: https://saml.example.com/sso + + # CA to use when validating the signature of the SAML response. + ca: /path/to/ca.pem + + # Dex's callback URL. + # + # If the response assertion status value contains a Destination element, it + # must match this value exactly. + # + # This is also used as the expected audience for AudienceRestriction elements + # if entityIssuer isn't specified. + redirectURI: https://dex.example.com/callback + + # Name of attributes in the returned assertions to map to ID token claims. + usernameAttr: name + emailAttr: email + groupsAttr: groups # optional + + # CA's can also be provided inline as a base64'd blob. + # + # caData: ( RAW base64'd PEM encoded CA ) + + # To skip signature validation, uncomment the following field. This should + # only be used during testing and may be removed in the future. + # + # insecureSkipSignatureValidation: true + + # Optional: Manually specify dex's Issuer value. + # + # When provided dex will include this as the Issuer value during AuthnRequest. + # It will also override the redirectURI as the required audience when evaluating + # AudienceRestriction elements in the response. + entityIssuer: https://dex.example.com/callback + + # Optional: Issuer value expected in the SAML response. + ssoIssuer: https://saml.example.com/sso + + # Optional: Delimiter for splitting groups returned as a single string. + # + # By default, multiple groups are assumed to be represented as multiple + # attributes with the same name. + # + # If "groupsDelim" is provided groups are assumed to be represented as a + # single attribute and the delimiter is used to split the attribute's value + # into multiple groups. + groupsDelim: ", " + + # Optional: Requested format of the NameID. + # + # The NameID value is is mapped to the user ID of the user. This can be an + # abbreviated form of the full URI with just the last component. For example, + # if this value is set to "emailAddress" the format will resolve to: + # + # urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress + # + # If no value is specified, this value defaults to: + # + # urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + # + nameIDPolicyFormat: persistent +``` + +A minimal working configuration might look like: + +```yaml +connectors: +- type: saml + id: okta + name: Okta + config: + ssoURL: https://dev-111102.oktapreview.com/app/foo/exk91cb99lKkKSYoy0h7/sso/saml + ca: /etc/dex/saml-ca.pem + redirectURI: http://127.0.0.1:5556/dex/callback + usernameAttr: name + emailAttr: email + groupsAttr: groups +``` diff --git a/Documentation/github-connector.md b/Documentation/github-connector.md index d7a15b67..29a522f2 100644 --- a/Documentation/github-connector.md +++ b/Documentation/github-connector.md @@ -1,109 +1 @@ -# Authentication through GitHub - -## Overview - -One of the login options for dex uses the GitHub OAuth2 flow to identify the end user through their GitHub account. - -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, __dex stores a readonly GitHub access token in its backing datastore.__ Users that reject dex's access through GitHub will also revoke all dex clients which authenticated them through GitHub. - -## Caveats - -* A user must explicitly [request][github-request-org-access] an [organization][github-orgs] give dex [resource access][github-approve-org-access]. 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. - -## Configuration - -Register a new application with [GitHub][github-oauth2] ensuring the callback URL is `(dex issuer)/callback`. For example if dex is listening at the non-root path `https://auth.example.com/dex` the callback would be `https://auth.example.com/dex/callback`. - -The following is an example of a configuration for `examples/config-dev.yaml`: - -```yaml -connectors: -- type: github - # Required field for connector id. - id: github - # Required field for connector name. - name: GitHub - config: - # Credentials can be string literals or pulled from the environment. - clientID: $GITHUB_CLIENT_ID - clientSecret: $GITHUB_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback - # Optional organizations and teams, communicated through the "groups" scope. - # - # NOTE: This is an EXPERIMENTAL config option and will likely change. - # - # Legacy 'org' field. 'org' and 'orgs' cannot be used simultaneously. A user - # MUST be a member of the following org to authenticate with dex. - # org: my-organization - # - # Dex queries the following organizations for group information if the - # "groups" scope is provided. Group claims are formatted as "(org):(team)". - # For example if a user is part of the "engineering" team of the "coreos" - # org, the group claim would include "coreos:engineering". - # - # A user MUST be a member of at least one of the following orgs to - # authenticate with dex. - orgs: - - name: my-organization - # Include all teams as claims. - - name: my-organization-with-teams - # A white list of teams. Only include group claims for these teams. - teams: - - red-team - - blue-team -``` - -## GitHub Enterprise - -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: - -```yaml -connectors: -- type: github - # Required field for connector id. - id: github - # Required field for connector name. - name: GitHub - config: - # Required fields. Dex must be pre-registered with GitHub Enterprise - # to get the following values. - # Credentials can be string literals or pulled from the environment. - clientID: $GITHUB_CLIENT_ID - clientSecret: $GITHUB_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback - # Optional organizations and teams, communicated through the "groups" scope. - # - # NOTE: This is an EXPERIMENTAL config option and will likely change. - # - # Legacy 'org' field. 'org' and 'orgs' cannot be used simultaneously. A user - # MUST be a member of the following org to authenticate with dex. - # org: my-organization - # - # Dex queries the following organizations for group information if the - # "groups" scope is provided. Group claims are formatted as "(org):(team)". - # For example if a user is part of the "engineering" team of the "coreos" - # org, the group claim would include "coreos:engineering". - # - # A user MUST be a member of at least one of the following orgs to - # authenticate with dex. - orgs: - - name: my-organization - # Include all teams as claims. - - name: my-organization-with-teams - # A white list of teams. Only include group claims for these teams. - teams: - - red-team - - blue-team - # Required ONLY for GitHub Enterprise. - # This is the Hostname of the GitHub Enterprise account listed on the - # management console. Ensure this domain is routable on your network. - hostName: git.example.com - # ONLY for GitHub Enterprise. Optional field. - # Used to support self-signed or untrusted CA root certificates. - rootCA: /etc/dex/ca.crt -``` - -[github-oauth2]: https://github.com/settings/applications/new -[github-orgs]: https://developer.github.com/v3/orgs/ -[github-request-org-access]: https://help.github.com/articles/requesting-organization-approval-for-oauth-apps/ -[github-approve-org-access]: https://help.github.com/articles/approving-oauth-apps-for-your-organization/ +This document has moved to [connectors/github.md](connectors/github.md). diff --git a/Documentation/gitlab-connector.md b/Documentation/gitlab-connector.md index fc797e9f..b74c9495 100644 --- a/Documentation/gitlab-connector.md +++ b/Documentation/gitlab-connector.md @@ -1,29 +1 @@ -# Authentication through Gitlab - -## Overview - -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 [gitlab.com](gitlab.com), GitLab community or enterprise edition. - -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, __dex stores a readonly GitLab access token in its backing datastore.__ Users that reject dex's access through GitLab will also revoke all dex clients which authenticated them through GitLab. - -## Configuration - -Register a new application via `User Settings -> Applications` ensuring the callback URL is `(dex issuer)/callback`. For example if dex is listening at the non-root path `https://auth.example.com/dex` the callback would be `https://auth.example.com/dex/callback`. - -The following is an example of a configuration for `examples/config-dev.yaml`: - -```yaml -connectors: - - type: gitlab - # Required field for connector id. - id: gitlab - # Required field for connector name. - name: GitLab - config: - # optional, default = https://www.gitlab.com - baseURL: https://www.gitlab.com - # Credentials can be string literals or pulled from the environment. - clientID: $GITLAB_APPLICATION_ID - clientSecret: $GITLAB_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback -``` +This document has moved to [connectors/gitlab.md](connectors/gitlab.md). diff --git a/Documentation/ldap-connector.md b/Documentation/ldap-connector.md index 0a0813c7..f36d50d5 100644 --- a/Documentation/ldap-connector.md +++ b/Documentation/ldap-connector.md @@ -1,284 +1 @@ -# Authentication through LDAP - -## Overview - -The LDAP connector allows email/password based authentication, backed by a LDAP directory. - -The connector executes two primary queries: - -1. Finding the user based on the end user's credentials. -2. Searching for groups using the user entry. - -## Getting started - -The dex repo contains a basic LDAP setup using [OpenLDAP][openldap]. - -First start the LDAP server using the example script. This will run the OpenLDAP daemon and seed it with a initial set of users. - -``` -./scripts/slapd.sh -``` - -This script sets the LDAP daemon to debug mode, and is expected to print several error messages which are normal. Once the server is up, run dex. - -``` -./bin/dex serve examples/config-ldap.yaml -``` - -Then run the OAuth client in another terminal. - -``` -./bin/example-app -``` - -Go to [http://localhost:5555](http://localhost:5555), login and enter the username and password of the LDAP user: `janedoe@example.com`/`foo`. Add the "groups" scope as part of the initial redirect to add group information from the LDAP server. - -## Security considerations - -Dex attempts to bind with the backing LDAP server using the end user's _plain text password_. Though some LDAP implementations allow passing hashed passwords, dex doesn't support hashing and instead _strongly recommends that all administrators just use TLS_. This can often be achieved by using port 636 instead of 389, and administrators that choose 389 are actively leaking passwords. - -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 _users who configure LDAP login using 389 are not covered by any compatibility guarantees with future releases._ - -## Configuration - -User entries are expected to have an email attribute (configurable through `emailAttr`), and a display name attribute (configurable through `nameAttr`). `*Attr` attributes could be set to "DN" in situations where it is needed but not available elsewhere, and if "DN" attribute does not exist in the record. - -The following is an example config file that can be used by the LDAP connector to authenticate a user. - -```yaml -connectors: -- type: ldap - # Required field for connector id. - id: ldap - # Required field for connector name. - name: LDAP - config: - # Host and optional port of the LDAP server in the form "host:port". - # If the port is not supplied, it will be guessed based on "insecureNoSSL", - # and "startTLS" flags. 389 for insecure or StartTLS connections, 636 - # otherwise. - host: ldap.example.com:636 - - # Following field is required if the LDAP host is not using TLS (port 389). - # Because this option inherently leaks passwords to anyone on the same network - # as dex, THIS OPTION MAY BE REMOVED WITHOUT WARNING IN A FUTURE RELEASE. - # - # insecureNoSSL: true - - # If a custom certificate isn't provide, this option can be used to turn on - # TLS certificate checks. As noted, it is insecure and shouldn't be used outside - # of explorative phases. - # - # insecureSkipVerify: true - - # When connecting to the server, connect using the ldap:// protocol then issue - # a StartTLS command. If unspecified, connections will use the ldaps:// protocol - # - # startTLS: true - - # Path to a trusted root certificate file. Default: use the host's root CA. - rootCA: /etc/dex/ldap.ca - - # A raw certificate file can also be provided inline. - # rootCAData: ( base64 encoded PEM file ) - - # The DN and password for an application service account. The connector uses - # these credentials to search for users and groups. Not required if the LDAP - # server provides access for anonymous auth. - # Please note that if the bind password contains a `$`, it has to be saved in an - # environment variable which should be given as the value to `bindPW`. - bindDN: uid=seviceaccount,cn=users,dc=example,dc=com - bindPW: password - - # The attribute to display in the provided password prompt. If unset, will - # display "Username" - usernamePrompt: SSO Username - - # User search maps a username and password entered by a user to a LDAP entry. - userSearch: - # BaseDN to start the search from. It will translate to the query - # "(&(objectClass=person)(uid=))". - baseDN: cn=users,dc=example,dc=com - # Optional filter to apply when searching the directory. - filter: "(objectClass=person)" - - # username attribute used for comparing user entries. This will be translated - # and combined with the other filter as "(=)". - username: uid - # The following three fields are direct mappings of attributes on the user entry. - # String representation of the user. - idAttr: uid - # Required. Attribute to map to Email. - emailAttr: mail - # Maps to display name of users. No default value. - nameAttr: name - - # Group search queries for groups given a user entry. - groupSearch: - # BaseDN to start the search from. It will translate to the query - # "(&(objectClass=group)(member=))". - baseDN: cn=groups,dc=freeipa,dc=example,dc=com - # Optional filter to apply when searching the directory. - filter: "(objectClass=group)" - - # Following two fields are used to match a user to a group. It adds an additional - # requirement to the filter that an attribute in the group must match the user's - # attribute value. - userAttr: uid - groupAttr: member - - # Represents group name. - nameAttr: name -``` - -The LDAP connector first initializes a connection to the LDAP directory using the `bindDN` and `bindPW`. It then tries to search for the given `username` and bind as that user to verify their password. -Searches that return multiple entries are considered ambiguous and will return an error. - -## Example: Mapping a schema to a search config - -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 `ldapsearch`. For `rpm` based distros run: - -``` -sudo dnf install openldap-clients -``` - -For `apt-get`: - -``` -sudo apt-get install ldap-utils -``` - -For smaller user directories it may be practical to dump the entire contents and search by hand. - -``` -ldapsearch -x -h ldap.example.org -b 'dc=example,dc=org' | less -``` - -First, find a user entry. User entries declare users who can login to LDAP connector using username and password. - -``` -dn: uid=jdoe,cn=users,cn=compat,dc=example,dc=org -cn: Jane Doe -objectClass: posixAccount -objectClass: ipaOverrideTarget -objectClass: top -gidNumber: 200015 -gecos: Jane Doe -uidNumber: 200015 -loginShell: /bin/bash -homeDirectory: /home/jdoe -mail: jane.doe@example.com -uid: janedoe -``` - -Compose a user search which returns this user. - -```yaml -userSearch: - # The directory directly above the user entry. - baseDN: cn=users,cn=compat,dc=example,dc=org - filter: "(objectClass=posixAccount)" - - # Expect user to enter "janedoe" when logging in. - username: uid - - # Use the full DN as an ID. - idAttr: DN - - # When an email address is not available, use another value unique to the user, like uid. - emailAttr: mail - nameAttr: gecos -``` - -Second, find a group entry. - -``` -dn: cn=developers,cn=groups,cn=compat,dc=example,dc=org -memberUid: janedoe -memberUid: johndoe -gidNumber: 200115 -objectClass: posixGroup -objectClass: ipaOverrideTarget -objectClass: top -cn: developers -``` - -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's list of memberUid attributes. - -```yaml -groupSearch: - # The directory directly above the group entry. - baseDN: cn=groups,cn=compat,dc=example,dc=org - filter: "(objectClass=posixGroup)" - - # The group search needs to match the "uid" attribute on - # the user with the "memberUid" attribute on the group. - userAttr: uid - groupAttr: memberUid - - # Unique name of the group. - nameAttr: cn -``` -To extract group specific information the `DN` can be used in the `userAttr` field. - -``` -# Top level object example.coma in LDIF file. -dn: dc=example,dc=com -objectClass: top -objectClass: dcObject -objectClass: organization -dc: example -``` - -The following is an example of a group query would match any entry with member=: - -```yaml -groupSearch: - # BaseDN to start the search from. It will translate to the query - # "(&(objectClass=group)(member=))". - baseDN: cn=groups,cn=compat,dc=example,dc=com - # Optional filter to apply when searching the directory. - filter: "(objectClass=group)" - - userAttr: DN # Use "DN" here not "uid" - groupAttr: member - - nameAttr: name -``` - -## Example: Searching a FreeIPA server with groups - -The following configuration will allow the LDAP connector to search a FreeIPA directory using an LDAP filter. - -```yaml - -connectors: -- type: ldap - id: ldap - name: LDAP - config: - # host and port of the LDAP server in form "host:port". - host: freeipa.example.com:636 - # freeIPA server's CA - rootCA: ca.crt - userSearch: - # Would translate to the query "(&(objectClass=person)(uid=))". - baseDN: cn=users,dc=freeipa,dc=example,dc=com - filter: "(objectClass=posixAccount)" - username: uid - idAttr: uid - # Required. Attribute to map to Email. - emailAttr: mail - # Entity attribute to map to display name of users. - groupSearch: - # Would translate to the query "(&(objectClass=group)(member=))". - baseDN: cn=groups,dc=freeipa,dc=example,dc=com - filter: "(objectClass=group)" - userAttr: uid - groupAttr: member - nameAttr: name -``` - -If the search finds an entry, it will attempt to use the provided password to bind as that user entry. - -[openldap]: https://www.openldap.org/ +This document has moved to [connectors/ldap.md](connectors/ldap.md). diff --git a/Documentation/linkedin-connector.md b/Documentation/linkedin-connector.md index 646ee243..b2534520 100644 --- a/Documentation/linkedin-connector.md +++ b/Documentation/linkedin-connector.md @@ -1,27 +1 @@ -# Authentication through LinkedIn - -## Overview - -One of the login options for dex uses the LinkedIn OAuth2 flow to identify the end user through their LinkedIn account. - -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, __dex stores a readonly LinkedIn access token in its backing datastore.__ Users that reject dex's access through LinkedIn will also revoke all dex clients which authenticated them through LinkedIn. - -## Configuration - -Register a new application via `My Apps -> Create Application` ensuring the callback URL is `(dex issuer)/callback`. For example if dex is listening at the non-root path `https://auth.example.com/dex` the callback would be `https://auth.example.com/dex/callback`. - -The following is an example of a configuration for `examples/config-dev.yaml`: - -```yaml -connectors: - - type: linkedin - # Required field for connector id. - id: linkedin - # Required field for connector name. - name: LinkedIn - config: - # Credentials can be string literals or pulled from the environment. - clientID: $LINKEDIN_APPLICATION_ID - clientSecret: $LINKEDIN_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback -``` +This document has moved to [connectors/linkedin.md](connectors/linkedin.md). diff --git a/Documentation/microsoft-connector.md b/Documentation/microsoft-connector.md index 11024a6d..88be1d8c 100644 --- a/Documentation/microsoft-connector.md +++ b/Documentation/microsoft-connector.md @@ -1,112 +1 @@ -# Authentication through Microsoft - -## Overview - -One of the login options for dex uses the Microsoft OAuth2 flow to identify the -end user through their Microsoft account. - -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, __dex stores a readonly -Microsoft access and refresh tokens in its backing datastore.__ Users that -reject dex's access through Microsoft will also revoke all dex clients which -authenticated them through Microsoft. - -### Caveats - -`groups` claim in dex is only supported when `tenant` is specified in Microsoft -connector config. 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: - - - when registering dex application on https://apps.dev.microsoft.com add - an explicit `Directory.Read.All` permission to the list of __Delegated - Permissions__ - - open the following link in your browser and log in under organization - administrator account: - -`https://login.microsoftonline.com//adminconsent?client_id=` - -## Configuration - -Register a new application on https://apps.dev.microsoft.com via `Add an app` -ensuring the callback URL is `(dex issuer)/callback`. For example if dex -is listening at the non-root path `https://auth.example.com/dex` the callback -would be `https://auth.example.com/dex/callback`. - -The following is an example of a configuration for `examples/config-dev.yaml`: - -```yaml -connectors: - - type: microsoft - # Required field for connector id. - id: microsoft - # Required field for connector name. - name: Microsoft - config: - # Credentials can be string literals or pulled from the environment. - clientID: $MICROSOFT_APPLICATION_ID - clientSecret: $MICROSOFT_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback -``` - -`tenant` 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 `tenant` parameter to one of the following: - -- `common`- both personal and business/school accounts can authenticate in dex - via Microsoft (default) -- `consumers` - only personal accounts can authenticate in dex -- `organizations` - only business/school accounts can authenticate in dex -- `` or `` - only accounts belonging to specific - tenant identified by either `` or `` can - authenticate in dex - -For example, the following snippet configures dex to only allow business/school -accounts: - -```yaml -connectors: - - type: microsoft - # Required field for connector id. - id: microsoft - # Required field for connector name. - name: Microsoft - config: - # Credentials can be string literals or pulled from the environment. - clientID: $MICROSOFT_APPLICATION_ID - clientSecret: $MICROSOFT_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback - tenant: organizations -``` - -### Groups - -When the `groups` claim is present in a request to dex __and__ `tenant` is -configured, dex will query Microsoft API to obtain a list of groups the user is -a member of. `onlySecurityGroups` configuration option restricts the list to -include only security groups. By default all groups (security, Office 365, -mailing lists) are included. - -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: - -```yaml -connectors: - - type: microsoft - # Required field for connector id. - id: microsoft - # Required field for connector name. - name: Microsoft - config: - # Credentials can be string literals or pulled from the environment. - clientID: $MICROSOFT_APPLICATION_ID - clientSecret: $MICROSOFT_CLIENT_SECRET - redirectURI: http://127.0.0.1:5556/dex/callback - tenant: myorg.onmicrosoft.com - groups: - - developers - - devops -``` +This document has moved to [connectors/microsoft.md](connectors/microsoft.md). diff --git a/Documentation/oidc-connector.md b/Documentation/oidc-connector.md index 76b4e457..1d7e83c5 100644 --- a/Documentation/oidc-connector.md +++ b/Documentation/oidc-connector.md @@ -1,55 +1 @@ -# Authentication through an OpenID Connect provider - -## Overview - -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 [_An overview of OpenID Connect_][oidc-doc]. - -Prominent examples of OpenID Connect providers include Google Accounts, Salesforce, and Azure AD v2 ([not v1][azure-ad-v1]). - -## Caveats - -This connector does not support the "groups" claim. Progress for this is tracked in [issue #1065][issue-1065]. - -When using refresh tokens, changes to the upstream claims aren't propegated to the id_token returned by dex. If a user's email changes, the "email" claim returned by dex won't change unless the user logs in again. Progress for this is tracked in [issue #863][issue-863]. - -## Configuration - -```yaml -connectors: -- type: oidc - id: google - name: Google - config: - # Canonical URL of the provider, also used for configuration discovery. - # This value MUST match the value returned in the provider config discovery. - # - # See: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig - issuer: https://accounts.google.com - - # Connector config values starting with a "$" will read from the environment. - clientID: $GOOGLE_CLIENT_ID - clientSecret: $GOOGLE_CLIENT_SECRET - - # Dex's issuer URL + "/callback" - redirectURI: http://127.0.0.1:5556/callback - - - # Some providers require passing client_secret via POST parameters instead - # of basic auth, despite the OAuth2 RFC discouraging it. Many of these - # cases are caught internally, but some may need to uncommented the - # following field. - # - # basicAuthUnsupported: true - - # Google supports whitelisting allowed domains when using G Suite - # (Google Apps). The following field can be set to a list of domains - # that can log in: - # - # hostedDomains: - # - example.com -``` - -[oidc-doc]: openid-connect.md -[issue-863]: https://github.com/coreos/dex/issues/863 -[issue-1065]: https://github.com/coreos/dex/issues/1065 -[azure-ad-v1]: https://github.com/coreos/go-oidc/issues/133 +This document has moved to [connectors/oidc.md](connectors/oidc.md). diff --git a/Documentation/saml-connector.md b/Documentation/saml-connector.md index 62cf6a7f..d66e047f 100644 --- a/Documentation/saml-connector.md +++ b/Documentation/saml-connector.md @@ -1,105 +1 @@ -# Authentication through SAML 2.0 - -## Overview - -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. - -The connector uses the value of the `NameID` element as the user's unique identifier which dex assumes is both unique and never changes. Use the `nameIDPolicyFormat` to ensure this is set to a value which satisfies these requirements. - -Unlike some clients which will process unprompted AuthnResponses, dex must send the initial AuthnRequest and validates the response's InResponseTo value. - -## Caveats - -__The connector doesn't support refresh tokens__ since the SAML 2.0 protocol doesn't provide a way to requery a provider without interaction. If the "offline_access" scope is requested, it will be ignored. - -The connector doesn't support signed AuthnRequests or encrypted attributes. - -## Configuration - -```yaml -connectors: -- type: saml - # Required field for connector id. - id: saml - # Required field for connector name. - name: SAML - config: - # SSO URL used for POST value. - ssoURL: https://saml.example.com/sso - - # CA to use when validating the signature of the SAML response. - ca: /path/to/ca.pem - - # Dex's callback URL. - # - # If the response assertion status value contains a Destination element, it - # must match this value exactly. - # - # This is also used as the expected audience for AudienceRestriction elements - # if entityIssuer isn't specified. - redirectURI: https://dex.example.com/callback - - # Name of attributes in the returned assertions to map to ID token claims. - usernameAttr: name - emailAttr: email - groupsAttr: groups # optional - - # CA's can also be provided inline as a base64'd blob. - # - # caData: ( RAW base64'd PEM encoded CA ) - - # To skip signature validation, uncomment the following field. This should - # only be used during testing and may be removed in the future. - # - # insecureSkipSignatureValidation: true - - # Optional: Manually specify dex's Issuer value. - # - # When provided dex will include this as the Issuer value during AuthnRequest. - # It will also override the redirectURI as the required audience when evaluating - # AudienceRestriction elements in the response. - entityIssuer: https://dex.example.com/callback - - # Optional: Issuer value expected in the SAML response. - ssoIssuer: https://saml.example.com/sso - - # Optional: Delimiter for splitting groups returned as a single string. - # - # By default, multiple groups are assumed to be represented as multiple - # attributes with the same name. - # - # If "groupsDelim" is provided groups are assumed to be represented as a - # single attribute and the delimiter is used to split the attribute's value - # into multiple groups. - groupsDelim: ", " - - # Optional: Requested format of the NameID. - # - # The NameID value is is mapped to the user ID of the user. This can be an - # abbreviated form of the full URI with just the last component. For example, - # if this value is set to "emailAddress" the format will resolve to: - # - # urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress - # - # If no value is specified, this value defaults to: - # - # urn:oasis:names:tc:SAML:2.0:nameid-format:persistent - # - nameIDPolicyFormat: persistent -``` - -A minimal working configuration might look like: - -```yaml -connectors: -- type: saml - id: okta - name: Okta - config: - ssoURL: https://dev-111102.oktapreview.com/app/foo/exk91cb99lKkKSYoy0h7/sso/saml - ca: /etc/dex/saml-ca.pem - redirectURI: http://127.0.0.1:5556/dex/callback - usernameAttr: name - emailAttr: email - groupsAttr: groups -``` +This document has moved to [connectors/saml.md](connectors/saml.md). diff --git a/README.md b/README.md index 1352c642..146a26e6 100644 --- a/README.md +++ b/README.md @@ -62,14 +62,14 @@ More docs for running dex as a Kubernetes authenticator can be found [here](Docu * [gRPC API](Documentation/api.md) * [Using Kubernetes with dex](Documentation/kubernetes.md) * Identity provider logins - * [LDAP](Documentation/ldap-connector.md) - * [GitHub](Documentation/github-connector.md) - * [GitLab](Documentation/gitlab-connector.md) - * [SAML 2.0](Documentation/saml-connector.md) - * [OpenID Connect](Documentation/oidc-connector.md) (includes Google, Salesforce, Azure, etc.) - * [authproxy](Documentation/authproxy.md) (Apache2 mod_auth, etc.) - * [LinkedIn](Documentation/linkedin-connector.md) - * [Microsoft](Documentation/microsoft-connection.md) + * [LDAP](Documentation/connectors/ldap.md) + * [GitHub](Documentation/connectors/github.md) + * [GitLab](Documentation/connectors/gitlab.md) + * [SAML 2.0](Documentation/connectors/saml.md) + * [OpenID Connect](Documentation/connectors/oidc.md) (includes Google, Salesforce, Azure, etc.) + * [authproxy](Documentation/connectors/authproxy.md) (Apache2 mod_auth, etc.) + * [LinkedIn](Documentation/connectors/linkedin.md) + * [Microsoft](Documentation/connectors/microsoft.md) * Client libraries * [Go][go-oidc]