Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -3432,15 +3432,20 @@ func (a *ServerWithRoles) CreateSAMLAuthRequest(ctx context.Context, req types.S
}

// ValidateSAMLResponse validates SAML auth response.
func (a *ServerWithRoles) ValidateSAMLResponse(ctx context.Context, re string, connectorID string) (*SAMLAuthResponse, error) {
func (a *ServerWithRoles) ValidateSAMLResponse(ctx context.Context, samlResponse, connectorID, clientIP string) (*SAMLAuthResponse, error) {
isProxy := a.hasBuiltinRole(types.RoleProxy)
if !isProxy {
clientIP = "" // We only trust IP information coming from the Proxy.
}

// auth callback is it's own authz, no need to check extra permissions
resp, err := a.authServer.ValidateSAMLResponse(ctx, re, connectorID)
resp, err := a.authServer.ValidateSAMLResponse(ctx, samlResponse, connectorID, clientIP)
if err != nil {
return nil, trace.Wrap(err)
}

// Only the Proxy service can create web sessions via SAML connector.
if resp.Session != nil && !a.hasBuiltinRole(types.RoleProxy) {
if resp.Session != nil && !isProxy {
return nil, trace.AccessDenied("this request can be only executed by a proxy")
}

Expand Down
2 changes: 1 addition & 1 deletion lib/auth/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ type IdentityService interface {
// CreateSAMLAuthRequest creates SAML AuthnRequest
CreateSAMLAuthRequest(ctx context.Context, req types.SAMLAuthRequest) (*types.SAMLAuthRequest, error)
// ValidateSAMLResponse validates SAML auth response
ValidateSAMLResponse(ctx context.Context, re string, connectorID string) (*SAMLAuthResponse, error)
ValidateSAMLResponse(ctx context.Context, samlResponse, connectorID, clientIP string) (*SAMLAuthResponse, error)
// GetSAMLAuthRequest returns SAML auth request if found
GetSAMLAuthRequest(ctx context.Context, authRequestID string) (*types.SAMLAuthRequest, error)

Expand Down
5 changes: 3 additions & 2 deletions lib/auth/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,10 +774,11 @@ func (c *HTTPClient) ValidateOIDCAuthCallback(ctx context.Context, q url.Values)
}

// ValidateSAMLResponse validates response returned by SAML identity provider
func (c *HTTPClient) ValidateSAMLResponse(ctx context.Context, re string, connectorID string) (*SAMLAuthResponse, error) {
func (c *HTTPClient) ValidateSAMLResponse(ctx context.Context, samlResponse, connectorID, clientIP string) (*SAMLAuthResponse, error) {
out, err := c.PostJSON(ctx, c.Endpoint("saml", "requests", "validate"), ValidateSAMLResponseReq{
Response: re,
Response: samlResponse,
ConnectorID: connectorID,
ClientIP: clientIP,
})
if err != nil {
return nil, trace.Wrap(err)
Expand Down
13 changes: 9 additions & 4 deletions lib/auth/saml.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type SAMLService interface {
// CreateSAMLAuthRequest creates SAML AuthnRequest
CreateSAMLAuthRequest(ctx context.Context, req types.SAMLAuthRequest) (*types.SAMLAuthRequest, error)
// ValidateSAMLResponse validates SAML auth response
ValidateSAMLResponse(ctx context.Context, re string, connectorID string) (*SAMLAuthResponse, error)
ValidateSAMLResponse(ctx context.Context, samlResponse, connectorID, clientIP string) (*SAMLAuthResponse, error)
}

// UpsertSAMLConnector creates or updates a SAML connector.
Expand Down Expand Up @@ -168,12 +168,12 @@ func (a *Server) CreateSAMLAuthRequest(ctx context.Context, req types.SAMLAuthRe

// ValidateSAMLResponse delegates the method call to the samlAuthService if present,
// or returns a NotImplemented error if not present.
func (a *Server) ValidateSAMLResponse(ctx context.Context, re string, connectorID string) (*SAMLAuthResponse, error) {
func (a *Server) ValidateSAMLResponse(ctx context.Context, samlResponse, connectorID, clientIP string) (*SAMLAuthResponse, error) {
if a.samlAuthService == nil {
return nil, trace.Wrap(ErrSAMLRequiresEnterprise)
}

resp, err := a.samlAuthService.ValidateSAMLResponse(ctx, re, connectorID)
resp, err := a.samlAuthService.ValidateSAMLResponse(ctx, samlResponse, connectorID, clientIP)
return resp, trace.Wrap(err)
}

Expand Down Expand Up @@ -218,8 +218,13 @@ type SAMLAuthRequest struct {
// ValidateSAMLResponseReq is the request made by the proxy to validate
// and activate a login via SAML.
type ValidateSAMLResponseReq struct {
Response string `json:"response"`
// Response is SAML statements coming from the identity provider.
Response string `json:"response"`
// ConnectorID is ID of a SAML connector that should be used for this request.
ConnectorID string `json:"connector_id,omitempty"`
// ClientIP is IP of the logging in client, used in identity provider initiated login case,
// when we don't have original client's request with their IP stored.
ClientIP string `json:"client_ip,omitempty"`
}

// SAMLAuthRawResponse is returned when auth server validated callback parameters
Expand Down