diff --git a/changelog/unreleased/enhancement-strict-same-site-cookie.md b/changelog/unreleased/enhancement-strict-same-site-cookie.md new file mode 100644 index 00000000000..94b29161161 --- /dev/null +++ b/changelog/unreleased/enhancement-strict-same-site-cookie.md @@ -0,0 +1,12 @@ +Enhancement: Make IDP cookies same site strict + +To enhance the security of our application and prevent Cross-Site Request Forgery (CSRF) attacks, we have updated the +SameSite attribute of the build in Identity Provider (IDP) cookies to Strict. + +This change restricts the browser from sending these cookies with any cross-site requests, +thereby limiting the exposure of the user's session to potential threats. + +This update does not impact the existing functionality of the application but provides an additional layer of security +where needed. + +https://github.com/owncloud/ocis/pull/8716 diff --git a/go.mod b/go.mod index f0c3e65baad..027fcfb92eb 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/justinas/alice v1.2.0 github.com/leonelquinteros/gotext v1.5.3-0.20230317130943-71a59c05b2c1 github.com/libregraph/idm v0.4.1-0.20231213140724-56a222fb4215 - github.com/libregraph/lico v0.61.2 + github.com/libregraph/lico v0.61.3-0.20240322112242-72cf9221d3a7 github.com/mitchellh/mapstructure v1.5.0 github.com/mna/pigeon v1.2.1 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 diff --git a/go.sum b/go.sum index 31f2346717c..817ffe67a3d 100644 --- a/go.sum +++ b/go.sum @@ -1618,8 +1618,8 @@ github.com/leonelquinteros/gotext v1.5.3-0.20230317130943-71a59c05b2c1 h1:k56sFO github.com/leonelquinteros/gotext v1.5.3-0.20230317130943-71a59c05b2c1/go.mod h1:AT4NpQrOmyj1L/+hLja6aR0lk81yYYL4ePnj2kp7d6M= github.com/libregraph/idm v0.4.1-0.20231213140724-56a222fb4215 h1:Yw/I6l/0S/zDq2Hnibvwy8cVLpMaBwDe0aUSv/FNU6U= github.com/libregraph/idm v0.4.1-0.20231213140724-56a222fb4215/go.mod h1:h/B7mB5OqrsrobydErMGewHxonYDKjGOaJsFabXyRo8= -github.com/libregraph/lico v0.61.2 h1:sU8eQ2E9Uq5wnTkD33YX5+gRj59MkPLgDVoB72L1q8w= -github.com/libregraph/lico v0.61.2/go.mod h1:TgZGBAYzVRQSRdBC8PgGQKjYhtXuTr6UCM3ZZyGTleQ= +github.com/libregraph/lico v0.61.3-0.20240322112242-72cf9221d3a7 h1:fcPgiBu7DGyGeokE0Qk+S+GW/3n+QWu1dIjw0TqadhI= +github.com/libregraph/lico v0.61.3-0.20240322112242-72cf9221d3a7/go.mod h1:TgZGBAYzVRQSRdBC8PgGQKjYhtXuTr6UCM3ZZyGTleQ= github.com/libregraph/oidc-go v1.0.0 h1:l2tE/EwLyLXVy0B5BuVKgIFX9pNpz/5J3x5IBw0KEhc= github.com/libregraph/oidc-go v1.0.0/go.mod h1:7TRHrY/H1Vg6JqFjV0oAe1+kN+mGFBqXYvclSyvhRyc= github.com/linode/linodego v0.25.3/go.mod h1:GSBKPpjoQfxEfryoCRcgkuUOCuVtGHWhzI8OMdycNTE= diff --git a/services/idp/pkg/backends/cs3/bootstrap/cs3.go b/services/idp/pkg/backends/cs3/bootstrap/cs3.go index 24bc638d11f..10c093a3976 100644 --- a/services/idp/pkg/backends/cs3/bootstrap/cs3.go +++ b/services/idp/pkg/backends/cs3/bootstrap/cs3.go @@ -25,6 +25,7 @@ import ( "github.com/libregraph/lico/identifier" "github.com/libregraph/lico/identity" "github.com/libregraph/lico/identity/managers" + cs3 "github.com/owncloud/ocis/v2/services/idp/pkg/backends/cs3/identifier" ) @@ -88,12 +89,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { activeIdentifier, err := identifier.NewIdentifier(&identifier.Config{ Config: config.Config, - BaseURI: config.IssuerIdentifierURI, - PathPrefix: bs.MakeURIPath(bootstrap.APITypeSignin, ""), - StaticFolder: config.IdentifierClientPath, - LogonCookieName: "__Secure-KKT", // Kopano-Konnect-Token - ScopesConf: config.IdentifierScopesConf, - WebAppDisabled: config.IdentifierClientDisabled, + BaseURI: config.IssuerIdentifierURI, + PathPrefix: bs.MakeURIPath(bootstrap.APITypeSignin, ""), + StaticFolder: config.IdentifierClientPath, + ScopesConf: config.IdentifierScopesConf, + WebAppDisabled: config.IdentifierClientDisabled, + + LogonCookieName: "__Secure-KKT", // Kopano-Konnect-Token + LogonCookieSameSite: config.CookieSameSite, + + ConsentCookieSameSite: config.CookieSameSite, + + StateCookieSameSite: config.CookieSameSite, AuthorizationEndpointURI: fullAuthorizationEndpointURL, SignedOutEndpointURI: fullSignedOutEndpointURL, diff --git a/services/idp/pkg/config/config.go b/services/idp/pkg/config/config.go index 26971979917..2c3fcf91ba2 100644 --- a/services/idp/pkg/config/config.go +++ b/services/idp/pkg/config/config.go @@ -2,6 +2,7 @@ package config import ( "context" + "net/http" "github.com/owncloud/ocis/v2/ocis-pkg/shared" ) @@ -112,6 +113,7 @@ type Settings struct { CookieBackendURI string CookieNames []string + CookieSameSite http.SameSite AccessTokenDurationSeconds uint64 `yaml:"access_token_duration_seconds" env:"IDP_ACCESS_TOKEN_EXPIRATION" desc:"'Access token lifespan in seconds (time before an access token is expired).'" introductionVersion:"pre5.0"` IDTokenDurationSeconds uint64 `yaml:"id_token_duration_seconds" env:"IDP_ID_TOKEN_EXPIRATION" desc:"ID token lifespan in seconds (time before an ID token is expired)." introductionVersion:"pre5.0"` diff --git a/services/idp/pkg/config/defaults/defaultconfig.go b/services/idp/pkg/config/defaults/defaultconfig.go index ac0d15bf5d1..aa908a86560 100644 --- a/services/idp/pkg/config/defaults/defaultconfig.go +++ b/services/idp/pkg/config/defaults/defaultconfig.go @@ -1,6 +1,7 @@ package defaults import ( + "net/http" "path/filepath" "strings" @@ -64,6 +65,7 @@ func DefaultConfig() *config.Config { ValidationKeysPath: "", CookieBackendURI: "", CookieNames: nil, + CookieSameSite: http.SameSiteStrictMode, AccessTokenDurationSeconds: 60 * 5, // 5 minutes IDTokenDurationSeconds: 60 * 5, // 5 minutes RefreshTokenDurationSeconds: 60 * 60 * 24 * 30, // 30 days diff --git a/vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go b/vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go index 4d3cd379fe3..943a55e7033 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go +++ b/vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go @@ -127,12 +127,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { activeIdentifier, err := identifier.NewIdentifier(&identifier.Config{ Config: config.Config, - BaseURI: config.IssuerIdentifierURI, - PathPrefix: bs.MakeURIPath(bootstrap.APITypeSignin, ""), - StaticFolder: config.IdentifierClientPath, - LogonCookieName: "__Secure-KKT", // Kopano-Konnect-Token - ScopesConf: config.IdentifierScopesConf, - WebAppDisabled: config.IdentifierClientDisabled, + BaseURI: config.IssuerIdentifierURI, + PathPrefix: bs.MakeURIPath(bootstrap.APITypeSignin, ""), + StaticFolder: config.IdentifierClientPath, + ScopesConf: config.IdentifierScopesConf, + WebAppDisabled: config.IdentifierClientDisabled, + + LogonCookieName: "__Secure-KKT", // Kopano-Konnect-Token + LogonCookieSameSite: config.CookieSameSite, + + ConsentCookieSameSite: config.CookieSameSite, + + StateCookieSameSite: config.CookieSameSite, AuthorizationEndpointURI: fullAuthorizationEndpointURL, SignedOutEndpointURI: fullSignedOutEndpointURL, diff --git a/vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go b/vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go index 6ba682eee34..0fe760c0418 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go +++ b/vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go @@ -110,12 +110,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { activeIdentifier, err := identifier.NewIdentifier(&identifier.Config{ Config: config.Config, - BaseURI: config.IssuerIdentifierURI, - PathPrefix: bs.MakeURIPath(bootstrap.APITypeSignin, ""), - StaticFolder: config.IdentifierClientPath, - LogonCookieName: "__Secure-KKT", // Kopano-Konnect-Token - ScopesConf: config.IdentifierScopesConf, - WebAppDisabled: config.IdentifierClientDisabled, + BaseURI: config.IssuerIdentifierURI, + PathPrefix: bs.MakeURIPath(bootstrap.APITypeSignin, ""), + StaticFolder: config.IdentifierClientPath, + ScopesConf: config.IdentifierScopesConf, + WebAppDisabled: config.IdentifierClientDisabled, + + LogonCookieName: "__Secure-KKT", // Kopano-Konnect-Token + LogonCookieSameSite: config.CookieSameSite, + + ConsentCookieSameSite: config.CookieSameSite, + + StateCookieSameSite: config.CookieSameSite, AuthorizationEndpointURI: fullAuthorizationEndpointURL, SignedOutEndpointURI: fullSignedOutEndpointURL, diff --git a/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go b/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go index 29785a19cd7..9002c169047 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go +++ b/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go @@ -26,6 +26,7 @@ import ( "fmt" "io/ioutil" "net" + "net/http" "net/url" "os" "path/filepath" @@ -58,6 +59,7 @@ const ( DefaultSigningKeyBits = 2048 DefaultGuestIdentityManagerName = "guest" + DefaultCookieSameSite = http.SameSiteNoneMode ) // Bootstrap is a data structure to hold configuration required to start @@ -332,6 +334,12 @@ func (bs *bootstrap) initialize(settings *Settings) error { } bs.config.DyamicClientSecretDurationSeconds = settings.DyamicClientSecretDurationSeconds + // add setting to allow setting the same site attribute of the cookies + bs.config.CookieSameSite = settings.CookieSameSite + if bs.config.CookieSameSite == 0 { + bs.config.CookieSameSite = DefaultCookieSameSite + } + return nil } @@ -472,11 +480,13 @@ func (bs *bootstrap) setupOIDCProvider(ctx context.Context) (*oidcProvider.Provi CheckSessionIframePath: bs.MakeURIPath(APITypeKonnect, "/session/check-session.html"), RegistrationPath: registrationPath, - BrowserStateCookiePath: bs.MakeURIPath(APITypeKonnect, "/session/"), - BrowserStateCookieName: "__Secure-KKBS", // Kopano-Konnect-Browser-State + BrowserStateCookiePath: bs.MakeURIPath(APITypeKonnect, "/session/"), + BrowserStateCookieName: "__Secure-KKBS", // Kopano-Konnect-Browser-State + BrowserStateCookieSameSite: bs.config.CookieSameSite, - SessionCookiePath: sessionCookiePath, - SessionCookieName: "__Secure-KKCS", // Kopano-Konnect-Client-Session + SessionCookiePath: sessionCookiePath, + SessionCookieName: "__Secure-KKCS", // Kopano-Konnect-Client-Session + SessionCookieSameSite: bs.config.CookieSameSite, AccessTokenDuration: time.Duration(bs.config.AccessTokenDurationSeconds) * time.Second, IDTokenDuration: time.Duration(bs.config.IDTokenDurationSeconds) * time.Second, diff --git a/vendor/github.com/libregraph/lico/bootstrap/config.go b/vendor/github.com/libregraph/lico/bootstrap/config.go index 56e184c1bd2..de42e711e01 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/config.go +++ b/vendor/github.com/libregraph/lico/bootstrap/config.go @@ -21,6 +21,7 @@ import ( "crypto" "crypto/tls" "crypto/x509" + "net/http" "net/url" "github.com/golang-jwt/jwt/v4" @@ -64,4 +65,6 @@ type Config struct { IDTokenDurationSeconds uint64 RefreshTokenDurationSeconds uint64 DyamicClientSecretDurationSeconds uint64 + + CookieSameSite http.SameSite } diff --git a/vendor/github.com/libregraph/lico/bootstrap/settings.go b/vendor/github.com/libregraph/lico/bootstrap/settings.go index 1a87a35e1f7..a5cdc434c42 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/settings.go +++ b/vendor/github.com/libregraph/lico/bootstrap/settings.go @@ -17,6 +17,10 @@ package bootstrap +import ( + "net/http" +) + // Settings is a typed application config which represents the user accessible // boostrap settings params. type Settings struct { @@ -48,6 +52,7 @@ type Settings struct { ValidationKeysPath string CookieBackendURI string CookieNames []string + CookieSameSite http.SameSite AccessTokenDurationSeconds uint64 IDTokenDurationSeconds uint64 RefreshTokenDurationSeconds uint64 diff --git a/vendor/github.com/libregraph/lico/identifier/config.go b/vendor/github.com/libregraph/lico/identifier/config.go index f5741d9b43d..715560f40ef 100644 --- a/vendor/github.com/libregraph/lico/identifier/config.go +++ b/vendor/github.com/libregraph/lico/identifier/config.go @@ -18,6 +18,7 @@ package identifier import ( + "net/http" "net/url" "github.com/libregraph/lico/config" @@ -28,9 +29,15 @@ import ( type Config struct { Config *config.Config - BaseURI *url.URL - LogonCookieName string - ScopesConf string + BaseURI *url.URL + ScopesConf string + + LogonCookieName string + LogonCookieSameSite http.SameSite + + ConsentCookieSameSite http.SameSite + + StateCookieSameSite http.SameSite PathPrefix string StaticFolder string diff --git a/vendor/github.com/libregraph/lico/identifier/cookie.go b/vendor/github.com/libregraph/lico/identifier/cookie.go index 7ab74b432fa..4c57cb14668 100644 --- a/vendor/github.com/libregraph/lico/identifier/cookie.go +++ b/vendor/github.com/libregraph/lico/identifier/cookie.go @@ -37,7 +37,7 @@ func (i *Identifier) setLogonCookie(rw http.ResponseWriter, value string) error Path: i.pathPrefix + "/identifier/_/", Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: i.logonCookieSameSite, } http.SetCookie(rw, &cookie) @@ -55,7 +55,7 @@ func (i *Identifier) removeLogonCookie(rw http.ResponseWriter) error { Path: i.pathPrefix + "/identifier/_/", Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: i.logonCookieSameSite, Expires: farPastExpiryTime, } @@ -78,7 +78,7 @@ func (i *Identifier) setConsentCookie(rw http.ResponseWriter, cr *ConsentRequest Path: i.pathPrefix + "/identifier/_/", Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: i.consentCookieSameSite, } http.SetCookie(rw, &cookie) @@ -106,7 +106,7 @@ func (i *Identifier) removeConsentCookie(rw http.ResponseWriter, req *http.Reque Path: i.pathPrefix + "/identifier/_/", Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: i.consentCookieSameSite, Expires: farPastExpiryTime, } @@ -150,7 +150,7 @@ func (i *Identifier) setStateCookie(rw http.ResponseWriter, scope string, state Path: i.pathPrefix + "/identifier/" + scope, Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: i.stateCookieSameSite, } http.SetCookie(rw, &cookie) @@ -178,7 +178,7 @@ func (i *Identifier) removeStateCookie(rw http.ResponseWriter, req *http.Request Path: i.pathPrefix + "/identifier/" + scope, Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: i.stateCookieSameSite, Expires: farPastExpiryTime, } diff --git a/vendor/github.com/libregraph/lico/identifier/identifier.go b/vendor/github.com/libregraph/lico/identifier/identifier.go index 60e4326b0ac..d34bc998e13 100644 --- a/vendor/github.com/libregraph/lico/identifier/identifier.go +++ b/vendor/github.com/libregraph/lico/identifier/identifier.go @@ -32,8 +32,10 @@ import ( "github.com/gorilla/mux" "github.com/longsleep/rndm" "github.com/sirupsen/logrus" - jose "gopkg.in/square/go-jose.v2" - jwt "gopkg.in/square/go-jose.v2/jwt" + "gopkg.in/square/go-jose.v2" + "gopkg.in/square/go-jose.v2/jwt" + + "github.com/libregraph/oidc-go" konnect "github.com/libregraph/lico" "github.com/libregraph/lico/identifier/backends" @@ -44,7 +46,6 @@ import ( "github.com/libregraph/lico/identity/clients" "github.com/libregraph/lico/managers" "github.com/libregraph/lico/utils" - "github.com/libregraph/oidc-go" ) // audienceMarker defines the value which gets included in logon cookies. Valid @@ -62,10 +63,16 @@ type Identifier struct { baseURI *url.URL pathPrefix string staticFolder string - logonCookieName string scopesConf string webappIndexHTML []byte + logonCookieName string + logonCookieSameSite http.SameSite + + consentCookieSameSite http.SameSite + + stateCookieSameSite http.SameSite + authorizationEndpointURI *url.URL signedOutEndpointURI *url.URL oauth2CbEndpointURI *url.URL @@ -114,10 +121,16 @@ func NewIdentifier(c *Config) (*Identifier, error) { baseURI: c.BaseURI, pathPrefix: c.PathPrefix, staticFolder: staticFolder, - logonCookieName: c.LogonCookieName, scopesConf: c.ScopesConf, webappIndexHTML: webappIndexHTML, + logonCookieName: c.LogonCookieName, + logonCookieSameSite: c.LogonCookieSameSite, + + consentCookieSameSite: c.ConsentCookieSameSite, + + stateCookieSameSite: c.StateCookieSameSite, + authorizationEndpointURI: c.AuthorizationEndpointURI, signedOutEndpointURI: c.SignedOutEndpointURI, oauth2CbEndpointURI: oauth2CbEndpointURI, diff --git a/vendor/github.com/libregraph/lico/oidc/provider/config.go b/vendor/github.com/libregraph/lico/oidc/provider/config.go index 4a3e15404f1..1f695ddc094 100644 --- a/vendor/github.com/libregraph/lico/oidc/provider/config.go +++ b/vendor/github.com/libregraph/lico/oidc/provider/config.go @@ -18,6 +18,7 @@ package provider import ( + "net/http" "time" "github.com/libregraph/lico/config" @@ -37,11 +38,13 @@ type Config struct { CheckSessionIframePath string RegistrationPath string - BrowserStateCookiePath string - BrowserStateCookieName string + BrowserStateCookiePath string + BrowserStateCookieName string + BrowserStateCookieSameSite http.SameSite - SessionCookiePath string - SessionCookieName string + SessionCookiePath string + SessionCookieName string + SessionCookieSameSite http.SameSite AccessTokenDuration time.Duration IDTokenDuration time.Duration diff --git a/vendor/github.com/libregraph/lico/oidc/provider/cookie.go b/vendor/github.com/libregraph/lico/oidc/provider/cookie.go index cb25a944f74..3279a57c0f9 100644 --- a/vendor/github.com/libregraph/lico/oidc/provider/cookie.go +++ b/vendor/github.com/libregraph/lico/oidc/provider/cookie.go @@ -29,7 +29,7 @@ func (p *Provider) setBrowserStateCookie(rw http.ResponseWriter, value string) e Path: p.browserStateCookiePath, Secure: true, HttpOnly: false, // This Cookie is intended to be read by Javascript. - SameSite: http.SameSiteNoneMode, + SameSite: p.browserStateCookieSameSite, } http.SetCookie(rw, &cookie) @@ -43,7 +43,7 @@ func (p *Provider) removeBrowserStateCookie(rw http.ResponseWriter) error { Path: p.browserStateCookiePath, Secure: true, HttpOnly: false, // This Cookie is intended to be read by Javascript. - SameSite: http.SameSiteNoneMode, + SameSite: p.browserStateCookieSameSite, Expires: farPastExpiryTime, } @@ -60,7 +60,7 @@ func (p *Provider) setSessionCookie(rw http.ResponseWriter, value string) error Path: p.sessionCookiePath, Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: p.sessionCookieSameSite, } http.SetCookie(rw, &cookie) @@ -83,7 +83,7 @@ func (p *Provider) removeSessionCookie(rw http.ResponseWriter) error { Path: p.sessionCookiePath, Secure: true, HttpOnly: true, - SameSite: http.SameSiteNoneMode, + SameSite: p.sessionCookieSameSite, Expires: farPastExpiryTime, } diff --git a/vendor/github.com/libregraph/lico/oidc/provider/provider.go b/vendor/github.com/libregraph/lico/oidc/provider/provider.go index 82fdf004a5b..e0e03948532 100644 --- a/vendor/github.com/libregraph/lico/oidc/provider/provider.go +++ b/vendor/github.com/libregraph/lico/oidc/provider/provider.go @@ -73,11 +73,13 @@ type Provider struct { validationKeys map[string]crypto.PublicKey certificates map[string][]*x509.Certificate - browserStateCookiePath string - browserStateCookieName string + browserStateCookiePath string + browserStateCookieName string + browserStateCookieSameSite http.SameSite - sessionCookiePath string - sessionCookieName string + sessionCookiePath string + sessionCookieName string + sessionCookieSameSite http.SameSite accessTokenDuration time.Duration idTokenDuration time.Duration @@ -105,11 +107,13 @@ func NewProvider(c *Config) (*Provider, error) { validationKeys: make(map[string]crypto.PublicKey), certificates: make(map[string][]*x509.Certificate), - browserStateCookiePath: c.BrowserStateCookiePath, - browserStateCookieName: c.BrowserStateCookieName, + browserStateCookiePath: c.BrowserStateCookiePath, + browserStateCookieName: c.BrowserStateCookieName, + browserStateCookieSameSite: c.BrowserStateCookieSameSite, - sessionCookiePath: c.SessionCookiePath, - sessionCookieName: c.SessionCookieName, + sessionCookiePath: c.SessionCookiePath, + sessionCookieName: c.SessionCookieName, + sessionCookieSameSite: c.SessionCookieSameSite, accessTokenDuration: c.AccessTokenDuration, idTokenDuration: c.IDTokenDuration, diff --git a/vendor/modules.txt b/vendor/modules.txt index f36591b8ec2..1edd479dce4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1265,7 +1265,7 @@ github.com/libregraph/idm/server github.com/libregraph/idm/server/handler github.com/libregraph/idm/server/handler/boltdb github.com/libregraph/idm/server/handler/ldif -# github.com/libregraph/lico v0.61.2 +# github.com/libregraph/lico v0.61.3-0.20240322112242-72cf9221d3a7 ## explicit; go 1.18 github.com/libregraph/lico github.com/libregraph/lico/bootstrap