Skip to content

Commit

Permalink
feat(saml): saml 2.0 implementation (ory#1928)
Browse files Browse the repository at this point in the history
Signed-off-by: ThibaultHerard <[email protected]>

Co-authored-by: sebferrer <[email protected]>
Co-authored-by: alexGNX <[email protected]>
  • Loading branch information
3 people committed May 9, 2022
1 parent b682689 commit 6a10e28
Show file tree
Hide file tree
Showing 62 changed files with 3,167 additions and 2 deletions.
11 changes: 11 additions & 0 deletions driver/registery_default_saml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package driver

import "github.com/ory/kratos/selfservice/flow/saml"

func (m *RegistryDefault) SAMLHandler() *saml.Handler {
if m.selfserviceSAMLHandler == nil {
m.selfserviceSAMLHandler = saml.NewHandler(m)
}

return m.selfserviceSAMLHandler
}
6 changes: 6 additions & 0 deletions driver/registry_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ import (
"github.com/ory/kratos/hash"
"github.com/ory/kratos/schema"
"github.com/ory/kratos/selfservice/flow/recovery"
"github.com/ory/kratos/selfservice/flow/saml"
"github.com/ory/kratos/selfservice/flow/settings"
"github.com/ory/kratos/selfservice/flow/verification"
"github.com/ory/kratos/selfservice/hook"
"github.com/ory/kratos/selfservice/strategy/link"
"github.com/ory/kratos/selfservice/strategy/profile"
samlstrategy "github.com/ory/kratos/selfservice/strategy/saml/strategy"
"github.com/ory/kratos/x"

"github.com/cenkalti/backoff"
Expand Down Expand Up @@ -118,6 +120,8 @@ type RegistryDefault struct {
selfserviceLoginHandler *login.Handler
selfserviceLoginRequestErrorHandler *login.ErrorHandler

selfserviceSAMLHandler *saml.Handler

selfserviceSettingsHandler *settings.Handler
selfserviceSettingsErrorHandler *settings.ErrorHandler
selfserviceSettingsExecutor *settings.HookExecutor
Expand Down Expand Up @@ -150,6 +154,7 @@ func (m *RegistryDefault) Audit() *logrusx.Logger {

func (m *RegistryDefault) RegisterPublicRoutes(ctx context.Context, router *x.RouterPublic) {
m.LoginHandler().RegisterPublicRoutes(router)
m.SAMLHandler().RegisterPublicRoutes(router)
m.RegistrationHandler().RegisterPublicRoutes(router)
m.LogoutHandler().RegisterPublicRoutes(router)
m.SettingsHandler().RegisterPublicRoutes(router)
Expand Down Expand Up @@ -274,6 +279,7 @@ func (m *RegistryDefault) selfServiceStrategies() []interface{} {
m.selfserviceStrategies = []interface{}{
password2.NewStrategy(m),
oidc.NewStrategy(m),
samlstrategy.NewStrategy(m),
profile.NewStrategy(m),
link.NewStrategy(m),
totp.NewStrategy(m),
Expand Down
4 changes: 2 additions & 2 deletions driver/registry_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ func TestDefaultRegistry_AllStrategies(t *testing.T) {
_, reg := internal.NewFastRegistryWithMocks(t)

t.Run("case=all login strategies", func(t *testing.T) {
expects := []string{"password", "oidc", "totp", "webauthn", "lookup_secret"}
expects := []string{"password", "oidc", "saml", "totp", "webauthn", "lookup_secret"}
s := reg.AllLoginStrategies()
require.Len(t, s, len(expects))
for k, e := range expects {
Expand All @@ -695,7 +695,7 @@ func TestDefaultRegistry_AllStrategies(t *testing.T) {
})

t.Run("case=all registration strategies", func(t *testing.T) {
expects := []string{"password", "oidc", "webauthn"}
expects := []string{"password", "oidc", "saml", "webauthn"}
s := reg.AllRegistrationStrategies()
require.Len(t, s, len(expects))
for k, e := range expects {
Expand Down
251 changes: 251 additions & 0 deletions embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,225 @@
}
}
},
"selfServiceSAMLProvider": {
"type": "object",
"properties": {
"id": {
"title":"ID of the IdentityProvider",
"type": "string",
"examples": [
"activedirectory1"
]
},
"label": {
"title": "Optional string which will be used when generating labels for UI buttons.",
"type": "string",
"examples": [
"Microsoft Active Directory"
]
},
"public_cert_path": {
"title": "Public Certificate Path",
"description": "The Public Certificate for your SAML Messages",
"type": "string",
"format": "uri",
"examples": [
"file://path/to/cert",
"https://foo.bar.com/path/to/cert"
]
},
"private_key_path": {
"title": "Private Key Path",
"description": "The Private Key for your SAML Messages",
"type": "string",
"format": "uri",
"examples": [
"file://path/to/key",
"https://foo.bar.com/path/to/key"
]
},
"mapper_url": {
"title": "Jsonnet Mapper URL",
"description": "Location for the jsonnet mapping between provider's data and Ory Kratos data",
"type": "string",
"format": "uri",
"examples": [
"file://path/to/oidc.jsonnet",
"https://foo.bar.com/path/to/oidc.jsonnet",
"base64://bG9jYWwgc3ViamVjdCA9I..."
]
},
"idp_information": {
"type": "object",
"properties": {
"idp_metadata_url": {
"title": "IDP Metadata URL",
"description": "The URL of the metadata of the IDP",
"type": "string",
"examples": [
"https://path/to/metadata"
]
},
"idp_certificate_path": {
"title": "IDP Certificate Path",
"description": "The path to the certificate of the IDP",
"type": "string",
"examples": [
"file://path/to/certificate",
"https://foo.bar.com/path/to/certificate"
]
},
"idp_logout_url": {
"title": "IDP Logout URL",
"description": "The URL of the SLO API of the IDP",
"type": "string",
"examples": [
"https://path/to/logout"
]
},
"idp_sso_url": {
"title": "IDP SSO URL",
"description": "The URL of the SSO Handler at the IDP",
"type": "string",
"examples": [
"https://path/to/sso"
]
},
"idp_entity_id": {
"title": "The EntityID of the IDP",
"description": "It is a unique identifier representing the IDP in saml requests",
"type": "string",
"examples": [
"https://samltest.id/saml/idp"
]
}
},
"allOf": [
{
"if": {
"properties": {
"idp_metadata_url": {
"const": {}
}
}
},
"then": {
"required": [
"idp_logout_url",
"idp_certificate_path",
"idp_entity_id"
]
},
"else":{
"properties": {
"idp_certificate_path": {
"const": {}
},
"idp_logout_url": {
"const": {}
},
"idp_entity_id":{
"const":{}
},
"idp_sso_url":{
"const":{}
}
}
}
}
]
},
"attributes_map": {
"type": "object",
"properties": {
"id": {
"title": "ID",
"description": "Name of the IDP attribute representing user ID on Kratos",
"type": "string",
"examples": [
"file://path/to/oidc.jsonnet",
"https://foo.bar.com/path/to/oidc.jsonnet",
"base64://bG9jYWwgc3ViamVjdCA9I..."
]
},
"firstname": {
"title": "Firstname",
"description": "Name of the IDP attribute representing user firstname on Kratos",
"type": "string",
"examples": [
"John"
]
},
"lastname": {
"title": "Lastname",
"description": "Name of the IDP attribute representing user lastname on Kratos",
"type": "string",
"examples": [
"Doe"
]
},
"nickname": {
"title": "Nickname",
"description": "Name of the IDP attribute representing user username on Kratos",
"type": "string",
"examples": [
"JohnDoe1337"
]
},
"gender": {
"title": "Gender",
"description": "Name of the IDP attribute representing user's gender on Kratos",
"type": "string",
"examples": [
"Male",
"Female",
"Non-binary"
]
},
"birthdate": {
"title": "Birthdate",
"description": "Name of the IDP attribute representing user birthdate on Kratos",
"type": "string",
"examples": [
"08/23/1978"
]
},
"picture": {
"title": "Picture",
"description": "Name of the IDP attribute representing user picture on Kratos",
"type": "string",
"examples": [
"https://imagepicture.jpg"
]
},
"email": {
"title": "Email",
"description": "Name of the IDP attribute representing user email on Kratos",
"type": "string",
"examples": [
"[email protected]"
]
},
"phone_number": {
"title": "Phone Number",
"description": "Name of the IDP attribute representing user phone number on Kratos",
"type": "string",
"examples": [
"+33678984320"
]
}
}
}
},
"additionalProperties": false,
"required": [
"id",
"label",
"public_cert_path",
"private_key_path",
"mapper_url"
]
},
"selfServiceOIDCProvider": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -770,6 +989,9 @@
"oidc": {
"$ref": "#/definitions/selfServiceAfterRegistrationMethod"
},
"saml": {
"$ref": "#/definitions/selfServiceAfterRegistrationMethod"
},
"hooks": {
"$ref": "#/definitions/selfServiceHooks"
}
Expand Down Expand Up @@ -1394,6 +1616,35 @@
]
}
},
"saml": {
"type": "object",
"title": "Specify SAML configuration",
"showEnvVarBlockForObject": true,
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"title": "Enables SAML Authentication Method",
"default": false
},
"config": {
"type": "object",
"additionalProperties": false,
"properties": {
"providers": {
"title": "SAML Provider",
"description": "All information required to implement a SAML authentication",
"type": "array",
"items": {
"$ref": "#/definitions/selfServiceSAMLProvider"
}
}
}


}
}
},
"oidc": {
"type": "object",
"title": "Specify OpenID Connect and OAuth2 Configuration",
Expand Down
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ require (
github.com/Masterminds/sprig/v3 v3.0.0
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0
github.com/avast/retry-go/v3 v3.1.1
github.com/beevik/etree v1.1.0
github.com/bradleyjkemp/cupaloy/v2 v2.6.0
github.com/bwmarrin/discordgo v0.23.0
github.com/bxcodec/faker/v3 v3.3.1
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/cortesi/modd v0.0.0-20210323234521-b35eddab86cc
github.com/crewjam/saml v0.4.6
github.com/davecgh/go-spew v1.1.1
github.com/davidrjonas/semver-cli v0.0.0-20190116233701-ee19a9a0dda6
github.com/dgraph-io/ristretto v0.1.0
Expand Down Expand Up @@ -96,6 +98,7 @@ require (
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023
gotest.tools v2.2.0+incompatible
)

require (
Expand Down Expand Up @@ -133,6 +136,7 @@ require (
github.com/cortesi/moddwatch v0.0.0-20210222043437-a6aaad86a36e // indirect
github.com/cortesi/termlog v0.0.0-20210222042314-a1eec763abec // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/crewjam/httperr v0.2.0 // indirect
github.com/docker/cli v20.10.11+incompatible // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.9+incompatible // indirect
Expand Down Expand Up @@ -182,6 +186,7 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/certificate-transparency-go v1.1.2-0.20210511102531-373a877eec92 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gorilla/css v1.0.0 // indirect
Expand Down Expand Up @@ -226,6 +231,7 @@ require (
github.com/magiconair/properties v1.8.5 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/markbates/hmax v1.0.0 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.12 // indirect
Expand Down Expand Up @@ -259,6 +265,7 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/russellhaering/goxmldsig v1.1.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761 // indirect
github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 // indirect
Expand Down
Loading

0 comments on commit 6a10e28

Please sign in to comment.