Merge pull request #902 from ericchiang/saml-stable
*: promote SAML to stable
This commit is contained in:
		@@ -12,7 +12,7 @@ The following is the exhaustive list of scopes supported by dex:
 | 
			
		||||
| `email` | ID token claims should include the end user's email and if that email was verified by an upstream provider. |
 | 
			
		||||
| `profile` | ID token claims should include the username of the end user. |
 | 
			
		||||
| `groups` | ID token claims should include a list of groups the end user is a member of. |
 | 
			
		||||
| `offline_access` | Token response should include a refresh token. |
 | 
			
		||||
| `offline_access` | Token response should include a refresh token. Doesn't work in combinations with some connectors, notability the [SAML connector][saml-connector] ignores this scope. |
 | 
			
		||||
| `audience:server:client_id:( client-id )` | Dynamic scope indicating that the ID token should be issued on behalf of another client. See the _"Cross-client trust and authorized party"_ section below. |
 | 
			
		||||
 | 
			
		||||
## Custom claims
 | 
			
		||||
@@ -67,5 +67,6 @@ The ID token claims will then include the following audience and authorized part
 | 
			
		||||
}
 | 
			
		||||
``` 
 | 
			
		||||
 | 
			
		||||
[saml-connector]: saml-connector.md
 | 
			
		||||
[core-claims]: https://openid.net/specs/openid-connect-core-1_0.html#IDToken
 | 
			
		||||
[standard-claims]: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,7 @@ At the app, go to the "Sign On" tab and then click "View Setup Instructions". Us
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
connectors:
 | 
			
		||||
- type: samlExperimental
 | 
			
		||||
- type: saml
 | 
			
		||||
  id: saml
 | 
			
		||||
  name: Okta
 | 
			
		||||
  config:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,23 +2,23 @@
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
The experimental SAML provider allows authentication through the SAML 2.0 HTTP POST binding.
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
There are known issues with the XML signature validation for this connector. In addition work is still being done to ensure this connector implements best security practices for SAML 2.0.
 | 
			
		||||
__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.
 | 
			
		||||
 | 
			
		||||
The connector doesn't support refresh tokens since the SAML 2.0 protocol doesn't provide a way to requery a provider without interaction. Ensure that the "offline_access" scope is not requested in client apps.
 | 
			
		||||
 | 
			
		||||
## Configuration
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
connectors:
 | 
			
		||||
- type: samlExperimental # will be changed to "saml" later without support for the "samlExperimental" value
 | 
			
		||||
- type: saml
 | 
			
		||||
  # Required field for connector id.
 | 
			
		||||
  id: saml
 | 
			
		||||
  # Required field for connector name.
 | 
			
		||||
@@ -27,9 +27,23 @@ connectors:
 | 
			
		||||
    # SSO URL used for POST value.
 | 
			
		||||
    ssoURL: https://saml.example.com/sso
 | 
			
		||||
 | 
			
		||||
    # CA to use when validating the SAML response.
 | 
			
		||||
    # 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 )
 | 
			
		||||
@@ -39,37 +53,31 @@ connectors:
 | 
			
		||||
    #
 | 
			
		||||
    # insecureSkipSignatureValidation: true
 | 
			
		||||
 | 
			
		||||
    # Optional: Issuer value for AuthnRequest
 | 
			
		||||
    # Must be contained within the "AudienceRestriction" attribute in all responses
 | 
			
		||||
    # If not set, redirectURI will be used for audience validation
 | 
			
		||||
    # 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 for SAML Response
 | 
			
		||||
    # Optional: Issuer value expected in the SAML response.
 | 
			
		||||
    ssoIssuer: https://saml.example.com/sso
 | 
			
		||||
 | 
			
		||||
    # Dex's callback URL. Must match the "Destination" attribute of all responses
 | 
			
		||||
    # exactly.
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    # 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.
 | 
			
		||||
    #
 | 
			
		||||
    # groupsDelim: ", "
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # Requested format of the NameID. The NameID value is is mapped to the ID Token
 | 
			
		||||
    # 'sub' claim.  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:
 | 
			
		||||
    # 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
 | 
			
		||||
    #
 | 
			
		||||
@@ -78,8 +86,20 @@ connectors:
 | 
			
		||||
    #     urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
 | 
			
		||||
    #
 | 
			
		||||
    nameIDPolicyFormat: persistent
 | 
			
		||||
 | 
			
		||||
    # Optional issuer used for validating the SAML response. If provided the
 | 
			
		||||
    # connector will validate the Issuer in the response.
 | 
			
		||||
    # issuer: https://saml.example.com
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ More docs for running dex as a Kubernetes authenticator can be found [here](Docu
 | 
			
		||||
  * [LDAP](Documentation/ldap-connector.md)
 | 
			
		||||
  * [GitHub](Documentation/github-connector.md)
 | 
			
		||||
  * [GitLab](Documentation/gitlab-connector.md)
 | 
			
		||||
  * [SAML 2.0 (experimental)](Documentation/saml-connector.md)
 | 
			
		||||
  * [SAML 2.0](Documentation/saml-connector.md)
 | 
			
		||||
  * [OpenID Connect](Documentation/oidc-connector.md) (includes Google, Salesforce, Azure, etc.)
 | 
			
		||||
* Client libraries
 | 
			
		||||
  * [Go][go-oidc]
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,9 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"golang.org/x/crypto/bcrypt"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/coreos/dex/connector"
 | 
			
		||||
	"github.com/coreos/dex/connector/github"
 | 
			
		||||
	"github.com/coreos/dex/connector/gitlab"
 | 
			
		||||
@@ -179,12 +179,14 @@ type ConnectorConfig interface {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var connectors = map[string]func() ConnectorConfig{
 | 
			
		||||
	"mockCallback":     func() ConnectorConfig { return new(mock.CallbackConfig) },
 | 
			
		||||
	"mockPassword":     func() ConnectorConfig { return new(mock.PasswordConfig) },
 | 
			
		||||
	"ldap":             func() ConnectorConfig { return new(ldap.Config) },
 | 
			
		||||
	"github":           func() ConnectorConfig { return new(github.Config) },
 | 
			
		||||
	"gitlab":           func() ConnectorConfig { return new(gitlab.Config) },
 | 
			
		||||
	"oidc":             func() ConnectorConfig { return new(oidc.Config) },
 | 
			
		||||
	"mockCallback": func() ConnectorConfig { return new(mock.CallbackConfig) },
 | 
			
		||||
	"mockPassword": func() ConnectorConfig { return new(mock.PasswordConfig) },
 | 
			
		||||
	"ldap":         func() ConnectorConfig { return new(ldap.Config) },
 | 
			
		||||
	"github":       func() ConnectorConfig { return new(github.Config) },
 | 
			
		||||
	"gitlab":       func() ConnectorConfig { return new(gitlab.Config) },
 | 
			
		||||
	"oidc":         func() ConnectorConfig { return new(oidc.Config) },
 | 
			
		||||
	"saml":         func() ConnectorConfig { return new(saml.Config) },
 | 
			
		||||
	// Keep around for backwards compatibility.
 | 
			
		||||
	"samlExperimental": func() ConnectorConfig { return new(saml.Config) },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -648,7 +648,7 @@ func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client s
 | 
			
		||||
	reqRefresh := func() bool {
 | 
			
		||||
		// Ensure the connector supports refresh tokens.
 | 
			
		||||
		//
 | 
			
		||||
		// Connectors like `samlExperimental` do not implement RefreshConnector.
 | 
			
		||||
		// Connectors like `saml` do not implement RefreshConnector.
 | 
			
		||||
		conn, ok := s.connectors[authCode.ConnectorID]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			s.logger.Errorf("connector ID not found: %q", authCode.ConnectorID)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user