From 85be8e726b5d43f0a21b44e53ff2a2e43d19b997 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:43:28 +0000 Subject: [PATCH] build(deps): bump github.com/libregraph/lico from 0.66.0 to 0.67.0 Bumps [github.com/libregraph/lico](https://github.com/libregraph/lico) from 0.66.0 to 0.67.0. - [Changelog](https://github.com/libregraph/lico/blob/master/CHANGELOG.md) - [Commits](https://github.com/libregraph/lico/compare/v0.66.0...v0.67.0) --- updated-dependencies: - dependency-name: github.com/libregraph/lico dependency-version: 0.67.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 3 +- go.sum | 7 +- vendor/github.com/gofrs/uuid/.gitignore | 15 - vendor/github.com/gofrs/uuid/LICENSE | 20 - vendor/github.com/gofrs/uuid/README.md | 117 ----- vendor/github.com/gofrs/uuid/codec.go | 234 --------- vendor/github.com/gofrs/uuid/fuzz.go | 48 -- vendor/github.com/gofrs/uuid/generator.go | 456 ------------------ vendor/github.com/gofrs/uuid/sql.go | 116 ----- vendor/github.com/gofrs/uuid/uuid.go | 285 ----------- .../github.com/libregraph/lico/CHANGELOG.md | 26 +- vendor/github.com/libregraph/lico/README.md | 10 +- .../lico/bootstrap/backends/ldap/ldap.go | 8 +- .../backends/libregraph/libregraph.go | 8 +- .../libregraph/lico/bootstrap/bootstrap.go | 8 + .../libregraph/lico/bootstrap/config.go | 1 + .../libregraph/lico/bootstrap/settings.go | 2 + .../libregraph/lico/config/config.go | 1 + .../lico/identifier-registration.yaml.in | 14 + .../libregraph/lico/identifier/api.go | 1 + .../lico/identifier/backends/ldap/ldap.go | 2 +- .../libregraph/lico/identifier/config.go | 1 + .../libregraph/lico/identifier/identifier.go | 31 +- .../lico/identifier/meta/branding.go | 1 + .../libregraph/lico/identifier/models.go | 2 +- .../libregraph/lico/identifier/user.go | 6 + .../lico/identity/clients/models.go | 62 ++- .../lico/identity/clients/registry.go | 15 +- .../libregraph/lico/identity/config.go | 3 + .../lico/identity/managers/identifier.go | 199 +++++++- .../libregraph/lico/oidc/provider/handlers.go | 4 +- vendor/github.com/libregraph/lico/scopes.go | 3 + vendor/modules.txt | 7 +- 33 files changed, 377 insertions(+), 1339 deletions(-) delete mode 100644 vendor/github.com/gofrs/uuid/.gitignore delete mode 100644 vendor/github.com/gofrs/uuid/LICENSE delete mode 100644 vendor/github.com/gofrs/uuid/README.md delete mode 100644 vendor/github.com/gofrs/uuid/codec.go delete mode 100644 vendor/github.com/gofrs/uuid/fuzz.go delete mode 100644 vendor/github.com/gofrs/uuid/generator.go delete mode 100644 vendor/github.com/gofrs/uuid/sql.go delete mode 100644 vendor/github.com/gofrs/uuid/uuid.go diff --git a/go.mod b/go.mod index aa9686dbb3..8d18ea99ba 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/kovidgoyal/imaging v1.8.21 github.com/leonelquinteros/gotext v1.7.3-0.20260422134830-b012b4ccae69 github.com/libregraph/idm v0.5.0 - github.com/libregraph/lico v0.66.0 + github.com/libregraph/lico v0.67.0 github.com/mna/pigeon v1.3.0 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/nats-io/nats-server/v2 v2.14.2 @@ -231,7 +231,6 @@ require ( github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/gofrs/flock v0.13.0 // indirect - github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect diff --git a/go.sum b/go.sum index 461be34566..55abd38231 100644 --- a/go.sum +++ b/go.sum @@ -482,9 +482,8 @@ github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= -github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid/v5 v5.4.0 h1:EfbpCTjqMuGyq5ZJwxqzn3Cbr2d0rUZU7v5ycAk/e/0= github.com/gofrs/uuid/v5 v5.4.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -773,8 +772,8 @@ github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLO github.com/lestrrat-go/option/v2 v2.0.0/go.mod h1:oSySsmzMoR0iRzCDCaUfsCzxQHUEuhOViQObyy7S6Vg= github.com/libregraph/idm v0.5.0 h1:tDMwKbAOZzdeDYMxVlY5PbSqRKO7dbAW9KT42A51WSk= github.com/libregraph/idm v0.5.0/go.mod h1:BGMwIQ/6orJSPVzJ1x6kgG2JyG9GY05YFmbsnaD80k0= -github.com/libregraph/lico v0.66.0 h1:7T6fD1YF0Ep9n0g4KN6dvWHTlDC3awrQpgsP5GdYCF4= -github.com/libregraph/lico v0.66.0/go.mod h1:QI7NfmAkAWQ2y97iVfLv10S8tcvPQjc630uyfHGjIOw= +github.com/libregraph/lico v0.67.0 h1:qsVjDVHyEGZxrKU9PEsdim7aKnEz5CVtG3VAbZ77hFU= +github.com/libregraph/lico v0.67.0/go.mod h1:kvfaHXyIlualEubTKszOizY65oGasC1oHmFpfQt4ugQ= github.com/libregraph/oidc-go v1.1.0 h1:RyudjL3UyQblqeBQI06W53PniWobqODeeyAy6v/HumA= github.com/libregraph/oidc-go v1.1.0/go.mod h1:qW9ubcXvZrfbbWZBaLMuk7bt5qAUMYyt9/NtXQt07Cw= github.com/linode/linodego v0.25.3/go.mod h1:GSBKPpjoQfxEfryoCRcgkuUOCuVtGHWhzI8OMdycNTE= diff --git a/vendor/github.com/gofrs/uuid/.gitignore b/vendor/github.com/gofrs/uuid/.gitignore deleted file mode 100644 index 666dbbb5bc..0000000000 --- a/vendor/github.com/gofrs/uuid/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# binary bundle generated by go-fuzz -uuid-fuzz.zip diff --git a/vendor/github.com/gofrs/uuid/LICENSE b/vendor/github.com/gofrs/uuid/LICENSE deleted file mode 100644 index 926d549870..0000000000 --- a/vendor/github.com/gofrs/uuid/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2013-2018 by Maxim Bublis - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/gofrs/uuid/README.md b/vendor/github.com/gofrs/uuid/README.md deleted file mode 100644 index 4f73bec82c..0000000000 --- a/vendor/github.com/gofrs/uuid/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# UUID - -[![License](https://img.shields.io/github/license/gofrs/uuid.svg)](https://github.com/gofrs/uuid/blob/master/LICENSE) -[![Build Status](https://travis-ci.org/gofrs/uuid.svg?branch=master)](https://travis-ci.org/gofrs/uuid) -[![GoDoc](http://godoc.org/github.com/gofrs/uuid?status.svg)](http://godoc.org/github.com/gofrs/uuid) -[![Coverage Status](https://codecov.io/gh/gofrs/uuid/branch/master/graphs/badge.svg?branch=master)](https://codecov.io/gh/gofrs/uuid/) -[![Go Report Card](https://goreportcard.com/badge/github.com/gofrs/uuid)](https://goreportcard.com/report/github.com/gofrs/uuid) - -Package uuid provides a pure Go implementation of Universally Unique Identifiers -(UUID) variant as defined in RFC-4122. This package supports both the creation -and parsing of UUIDs in different formats. - -This package supports the following UUID versions: -* Version 1, based on timestamp and MAC address (RFC-4122) -* Version 3, based on MD5 hashing of a named value (RFC-4122) -* Version 4, based on random numbers (RFC-4122) -* Version 5, based on SHA-1 hashing of a named value (RFC-4122) - -This package also supports experimental Universally Unique Identifier implementations based on a -[draft RFC](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html) that updates RFC-4122 -* Version 6, a k-sortable id based on timestamp, and field-compatible with v1 (draft-peabody-dispatch-new-uuid-format, RFC-4122) -* Version 7, a k-sortable id based on timestamp (draft-peabody-dispatch-new-uuid-format, RFC-4122) - -The v6 and v7 IDs are **not** considered a part of the stable API, and may be subject to behavior or API changes as part of minor releases -to this package. They will be updated as the draft RFC changes, and will become stable if and when the draft RFC is accepted. - -## Project History - -This project was originally forked from the -[github.com/satori/go.uuid](https://github.com/satori/go.uuid) repository after -it appeared to be no longer maintained, while exhibiting [critical -flaws](https://github.com/satori/go.uuid/issues/73). We have decided to take -over this project to ensure it receives regular maintenance for the benefit of -the larger Go community. - -We'd like to thank Maxim Bublis for his hard work on the original iteration of -the package. - -## License - -This source code of this package is released under the MIT License. Please see -the [LICENSE](https://github.com/gofrs/uuid/blob/master/LICENSE) for the full -content of the license. - -## Recommended Package Version - -We recommend using v2.0.0+ of this package, as versions prior to 2.0.0 were -created before our fork of the original package and have some known -deficiencies. - -## Installation - -It is recommended to use a package manager like `dep` that understands tagged -releases of a package, as well as semantic versioning. - -If you are unable to make use of a dependency manager with your project, you can -use the `go get` command to download it directly: - -```Shell -$ go get github.com/gofrs/uuid -``` - -## Requirements - -Due to subtests not being supported in older versions of Go, this package is -only regularly tested against Go 1.7+. This package may work perfectly fine with -Go 1.2+, but support for these older versions is not actively maintained. - -## Go 1.11 Modules - -As of v3.2.0, this repository no longer adopts Go modules, and v3.2.0 no longer has a `go.mod` file. As a result, v3.2.0 also drops support for the `github.com/gofrs/uuid/v3` import path. Only module-based consumers are impacted. With the v3.2.0 release, _all_ gofrs/uuid consumers should use the `github.com/gofrs/uuid` import path. - -An existing module-based consumer will continue to be able to build using the `github.com/gofrs/uuid/v3` import path using any valid consumer `go.mod` that worked prior to the publishing of v3.2.0, but any module-based consumer should start using the `github.com/gofrs/uuid` import path when possible and _must_ use the `github.com/gofrs/uuid` import path prior to upgrading to v3.2.0. - -Please refer to [Issue #61](https://github.com/gofrs/uuid/issues/61) and [Issue #66](https://github.com/gofrs/uuid/issues/66) for more details. - -## Usage - -Here is a quick overview of how to use this package. For more detailed -documentation, please see the [GoDoc Page](http://godoc.org/github.com/gofrs/uuid). - -```go -package main - -import ( - "log" - - "github.com/gofrs/uuid" -) - -// Create a Version 4 UUID, panicking on error. -// Use this form to initialize package-level variables. -var u1 = uuid.Must(uuid.NewV4()) - -func main() { - // Create a Version 4 UUID. - u2, err := uuid.NewV4() - if err != nil { - log.Fatalf("failed to generate UUID: %v", err) - } - log.Printf("generated Version 4 UUID %v", u2) - - // Parse a UUID from a string. - s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - u3, err := uuid.FromString(s) - if err != nil { - log.Fatalf("failed to parse UUID %q: %v", s, err) - } - log.Printf("successfully parsed UUID %v", u3) -} -``` - -## References - -* [RFC-4122](https://tools.ietf.org/html/rfc4122) -* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) -* [New UUID Formats RFC Draft (Peabody) Rev 04](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#) diff --git a/vendor/github.com/gofrs/uuid/codec.go b/vendor/github.com/gofrs/uuid/codec.go deleted file mode 100644 index 665026414c..0000000000 --- a/vendor/github.com/gofrs/uuid/codec.go +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "errors" - "fmt" -) - -// FromBytes returns a UUID generated from the raw byte slice input. -// It will return an error if the slice isn't 16 bytes long. -func FromBytes(input []byte) (UUID, error) { - u := UUID{} - err := u.UnmarshalBinary(input) - return u, err -} - -// FromBytesOrNil returns a UUID generated from the raw byte slice input. -// Same behavior as FromBytes(), but returns uuid.Nil instead of an error. -func FromBytesOrNil(input []byte) UUID { - uuid, err := FromBytes(input) - if err != nil { - return Nil - } - return uuid -} - -var errInvalidFormat = errors.New("uuid: invalid UUID format") - -func fromHexChar(c byte) byte { - switch { - case '0' <= c && c <= '9': - return c - '0' - case 'a' <= c && c <= 'f': - return c - 'a' + 10 - case 'A' <= c && c <= 'F': - return c - 'A' + 10 - } - return 255 -} - -// Parse parses the UUID stored in the string text. Parsing and supported -// formats are the same as UnmarshalText. -func (u *UUID) Parse(s string) error { - switch len(s) { - case 32: // hash - case 36: // canonical - case 34, 38: - if s[0] != '{' || s[len(s)-1] != '}' { - return fmt.Errorf("uuid: incorrect UUID format in string %q", s) - } - s = s[1 : len(s)-1] - case 41, 45: - if s[:9] != "urn:uuid:" { - return fmt.Errorf("uuid: incorrect UUID format in string %q", s[:9]) - } - s = s[9:] - default: - return fmt.Errorf("uuid: incorrect UUID length %d in string %q", len(s), s) - } - // canonical - if len(s) == 36 { - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return fmt.Errorf("uuid: incorrect UUID format in string %q", s) - } - for i, x := range [16]byte{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34, - } { - v1 := fromHexChar(s[x]) - v2 := fromHexChar(s[x+1]) - if v1|v2 == 255 { - return errInvalidFormat - } - u[i] = (v1 << 4) | v2 - } - return nil - } - // hash like - for i := 0; i < 32; i += 2 { - v1 := fromHexChar(s[i]) - v2 := fromHexChar(s[i+1]) - if v1|v2 == 255 { - return errInvalidFormat - } - u[i/2] = (v1 << 4) | v2 - } - return nil -} - -// FromString returns a UUID parsed from the input string. -// Input is expected in a form accepted by UnmarshalText. -func FromString(text string) (UUID, error) { - var u UUID - err := u.Parse(text) - return u, err -} - -// FromStringOrNil returns a UUID parsed from the input string. -// Same behavior as FromString(), but returns uuid.Nil instead of an error. -func FromStringOrNil(input string) UUID { - uuid, err := FromString(input) - if err != nil { - return Nil - } - return uuid -} - -// MarshalText implements the encoding.TextMarshaler interface. -// The encoding is the same as returned by the String() method. -func (u UUID) MarshalText() ([]byte, error) { - var buf [36]byte - encodeCanonical(buf[:], u) - return buf[:], nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// Following formats are supported: -// -// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", -// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", -// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" -// "6ba7b8109dad11d180b400c04fd430c8" -// "{6ba7b8109dad11d180b400c04fd430c8}", -// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8" -// -// ABNF for supported UUID text representation follows: -// -// URN := 'urn' -// UUID-NID := 'uuid' -// -// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | -// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | -// 'A' | 'B' | 'C' | 'D' | 'E' | 'F' -// -// hexoct := hexdig hexdig -// 2hexoct := hexoct hexoct -// 4hexoct := 2hexoct 2hexoct -// 6hexoct := 4hexoct 2hexoct -// 12hexoct := 6hexoct 6hexoct -// -// hashlike := 12hexoct -// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct -// -// plain := canonical | hashlike -// uuid := canonical | hashlike | braced | urn -// -// braced := '{' plain '}' | '{' hashlike '}' -// urn := URN ':' UUID-NID ':' plain -func (u *UUID) UnmarshalText(b []byte) error { - switch len(b) { - case 32: // hash - case 36: // canonical - case 34, 38: - if b[0] != '{' || b[len(b)-1] != '}' { - return fmt.Errorf("uuid: incorrect UUID format in string %q", b) - } - b = b[1 : len(b)-1] - case 41, 45: - if string(b[:9]) != "urn:uuid:" { - return fmt.Errorf("uuid: incorrect UUID format in string %q", b[:9]) - } - b = b[9:] - default: - return fmt.Errorf("uuid: incorrect UUID length %d in string %q", len(b), b) - } - if len(b) == 36 { - if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { - return fmt.Errorf("uuid: incorrect UUID format in string %q", b) - } - for i, x := range [16]byte{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34, - } { - v1 := fromHexChar(b[x]) - v2 := fromHexChar(b[x+1]) - if v1|v2 == 255 { - return errInvalidFormat - } - u[i] = (v1 << 4) | v2 - } - return nil - } - for i := 0; i < 32; i += 2 { - v1 := fromHexChar(b[i]) - v2 := fromHexChar(b[i+1]) - if v1|v2 == 255 { - return errInvalidFormat - } - u[i/2] = (v1 << 4) | v2 - } - return nil -} - -// MarshalBinary implements the encoding.BinaryMarshaler interface. -func (u UUID) MarshalBinary() ([]byte, error) { - return u.Bytes(), nil -} - -// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -// It will return an error if the slice isn't 16 bytes long. -func (u *UUID) UnmarshalBinary(data []byte) error { - if len(data) != Size { - return fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) - } - copy(u[:], data) - - return nil -} diff --git a/vendor/github.com/gofrs/uuid/fuzz.go b/vendor/github.com/gofrs/uuid/fuzz.go deleted file mode 100644 index ccf8d4ca29..0000000000 --- a/vendor/github.com/gofrs/uuid/fuzz.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2018 Andrei Tudor Călin -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -//go:build gofuzz -// +build gofuzz - -package uuid - -// Fuzz implements a simple fuzz test for FromString / UnmarshalText. -// -// To run: -// -// $ go get github.com/dvyukov/go-fuzz/... -// $ cd $GOPATH/src/github.com/gofrs/uuid -// $ go-fuzz-build github.com/gofrs/uuid -// $ go-fuzz -bin=uuid-fuzz.zip -workdir=./testdata -// -// If you make significant changes to FromString / UnmarshalText and add -// new cases to fromStringTests (in codec_test.go), please run -// -// $ go test -seed_fuzz_corpus -// -// to seed the corpus with the new interesting inputs, then run the fuzzer. -func Fuzz(data []byte) int { - _, err := FromString(string(data)) - if err != nil { - return 0 - } - return 1 -} diff --git a/vendor/github.com/gofrs/uuid/generator.go b/vendor/github.com/gofrs/uuid/generator.go deleted file mode 100644 index 44be9e1585..0000000000 --- a/vendor/github.com/gofrs/uuid/generator.go +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "crypto/md5" - "crypto/rand" - "crypto/sha1" - "encoding/binary" - "fmt" - "hash" - "io" - "net" - "sync" - "time" -) - -// Difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). -const epochStart = 122192928000000000 - -// EpochFunc is the function type used to provide the current time. -type EpochFunc func() time.Time - -// HWAddrFunc is the function type used to provide hardware (MAC) addresses. -type HWAddrFunc func() (net.HardwareAddr, error) - -// DefaultGenerator is the default UUID Generator used by this package. -var DefaultGenerator Generator = NewGen() - -// NewV1 returns a UUID based on the current timestamp and MAC address. -func NewV1() (UUID, error) { - return DefaultGenerator.NewV1() -} - -// NewV3 returns a UUID based on the MD5 hash of the namespace UUID and name. -func NewV3(ns UUID, name string) UUID { - return DefaultGenerator.NewV3(ns, name) -} - -// NewV4 returns a randomly generated UUID. -func NewV4() (UUID, error) { - return DefaultGenerator.NewV4() -} - -// NewV5 returns a UUID based on SHA-1 hash of the namespace UUID and name. -func NewV5(ns UUID, name string) UUID { - return DefaultGenerator.NewV5(ns, name) -} - -// NewV6 returns a k-sortable UUID based on a timestamp and 48 bits of -// pseudorandom data. The timestamp in a V6 UUID is the same as V1, with the bit -// order being adjusted to allow the UUID to be k-sortable. -// -// This is implemented based on revision 03 of the Peabody UUID draft, and may -// be subject to change pending further revisions. Until the final specification -// revision is finished, changes required to implement updates to the spec will -// not be considered a breaking change. They will happen as a minor version -// releases until the spec is final. -func NewV6() (UUID, error) { - return DefaultGenerator.NewV6() -} - -// NewV7 returns a k-sortable UUID based on the current millisecond precision -// UNIX epoch and 74 bits of pseudorandom data. It supports single-node batch generation (multiple UUIDs in the same timestamp) with a Monotonic Random counter. -// -// This is implemented based on revision 04 of the Peabody UUID draft, and may -// be subject to change pending further revisions. Until the final specification -// revision is finished, changes required to implement updates to the spec will -// not be considered a breaking change. They will happen as a minor version -// releases until the spec is final. -func NewV7() (UUID, error) { - return DefaultGenerator.NewV7() -} - -// Generator provides an interface for generating UUIDs. -type Generator interface { - NewV1() (UUID, error) - NewV3(ns UUID, name string) UUID - NewV4() (UUID, error) - NewV5(ns UUID, name string) UUID - NewV6() (UUID, error) - NewV7() (UUID, error) -} - -// Gen is a reference UUID generator based on the specifications laid out in -// RFC-4122 and DCE 1.1: Authentication and Security Services. This type -// satisfies the Generator interface as defined in this package. -// -// For consumers who are generating V1 UUIDs, but don't want to expose the MAC -// address of the node generating the UUIDs, the NewGenWithHWAF() function has been -// provided as a convenience. See the function's documentation for more info. -// -// The authors of this package do not feel that the majority of users will need -// to obfuscate their MAC address, and so we recommend using NewGen() to create -// a new generator. -type Gen struct { - clockSequenceOnce sync.Once - hardwareAddrOnce sync.Once - storageMutex sync.Mutex - - rand io.Reader - - epochFunc EpochFunc - hwAddrFunc HWAddrFunc - lastTime uint64 - clockSequence uint16 - hardwareAddr [6]byte -} - -// GenOption is a function type that can be used to configure a Gen generator. -type GenOption func(*Gen) - -// interface check -- build will fail if *Gen doesn't satisfy Generator -var _ Generator = (*Gen)(nil) - -// NewGen returns a new instance of Gen with some default values set. Most -// people should use this. -func NewGen() *Gen { - return NewGenWithHWAF(defaultHWAddrFunc) -} - -// NewGenWithHWAF builds a new UUID generator with the HWAddrFunc provided. Most -// consumers should use NewGen() instead. -// -// This is used so that consumers can generate their own MAC addresses, for use -// in the generated UUIDs, if there is some concern about exposing the physical -// address of the machine generating the UUID. -// -// The Gen generator will only invoke the HWAddrFunc once, and cache that MAC -// address for all the future UUIDs generated by it. If you'd like to switch the -// MAC address being used, you'll need to create a new generator using this -// function. -func NewGenWithHWAF(hwaf HWAddrFunc) *Gen { - return NewGenWithOptions(WithHWAddrFunc(hwaf)) -} - -// NewGenWithOptions returns a new instance of Gen with the options provided. -// Most people should use NewGen() or NewGenWithHWAF() instead. -// -// To customize the generator, you can pass in one or more GenOption functions. -// For example: -// -// gen := NewGenWithOptions( -// WithHWAddrFunc(myHWAddrFunc), -// WithEpochFunc(myEpochFunc), -// WithRandomReader(myRandomReader), -// ) -// -// NewGenWithOptions(WithHWAddrFunc(myHWAddrFunc)) is equivalent to calling -// NewGenWithHWAF(myHWAddrFunc) -// NewGenWithOptions() is equivalent to calling NewGen() -func NewGenWithOptions(opts ...GenOption) *Gen { - gen := &Gen{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: rand.Reader, - } - - for _, opt := range opts { - opt(gen) - } - - return gen -} - -// WithHWAddrFunc is a GenOption that allows you to provide your own HWAddrFunc -// function. -// When this option is nil, the defaultHWAddrFunc is used. -func WithHWAddrFunc(hwaf HWAddrFunc) GenOption { - return func(gen *Gen) { - if hwaf == nil { - hwaf = defaultHWAddrFunc - } - - gen.hwAddrFunc = hwaf - } -} - -// WithEpochFunc is a GenOption that allows you to provide your own EpochFunc -// function. -// When this option is nil, time.Now is used. -func WithEpochFunc(epochf EpochFunc) GenOption { - return func(gen *Gen) { - if epochf == nil { - epochf = time.Now - } - - gen.epochFunc = epochf - } -} - -// WithRandomReader is a GenOption that allows you to provide your own random -// reader. -// When this option is nil, the default rand.Reader is used. -func WithRandomReader(reader io.Reader) GenOption { - return func(gen *Gen) { - if reader == nil { - reader = rand.Reader - } - - gen.rand = reader - } -} - -// NewV1 returns a UUID based on the current timestamp and MAC address. -func (g *Gen) NewV1() (UUID, error) { - u := UUID{} - - timeNow, clockSeq, err := g.getClockSequence(false) - if err != nil { - return Nil, err - } - binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - - hardwareAddr, err := g.getHardwareAddr() - if err != nil { - return Nil, err - } - copy(u[10:], hardwareAddr) - - u.SetVersion(V1) - u.SetVariant(VariantRFC4122) - - return u, nil -} - -// NewV3 returns a UUID based on the MD5 hash of the namespace UUID and name. -func (g *Gen) NewV3(ns UUID, name string) UUID { - u := newFromHash(md5.New(), ns, name) - u.SetVersion(V3) - u.SetVariant(VariantRFC4122) - - return u -} - -// NewV4 returns a randomly generated UUID. -func (g *Gen) NewV4() (UUID, error) { - u := UUID{} - if _, err := io.ReadFull(g.rand, u[:]); err != nil { - return Nil, err - } - u.SetVersion(V4) - u.SetVariant(VariantRFC4122) - - return u, nil -} - -// NewV5 returns a UUID based on SHA-1 hash of the namespace UUID and name. -func (g *Gen) NewV5(ns UUID, name string) UUID { - u := newFromHash(sha1.New(), ns, name) - u.SetVersion(V5) - u.SetVariant(VariantRFC4122) - - return u -} - -// NewV6 returns a k-sortable UUID based on a timestamp and 48 bits of -// pseudorandom data. The timestamp in a V6 UUID is the same as V1, with the bit -// order being adjusted to allow the UUID to be k-sortable. -// -// This is implemented based on revision 03 of the Peabody UUID draft, and may -// be subject to change pending further revisions. Until the final specification -// revision is finished, changes required to implement updates to the spec will -// not be considered a breaking change. They will happen as a minor version -// releases until the spec is final. -func (g *Gen) NewV6() (UUID, error) { - var u UUID - - if _, err := io.ReadFull(g.rand, u[10:]); err != nil { - return Nil, err - } - - timeNow, clockSeq, err := g.getClockSequence(false) - if err != nil { - return Nil, err - } - - binary.BigEndian.PutUint32(u[0:], uint32(timeNow>>28)) // set time_high - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>12)) // set time_mid - binary.BigEndian.PutUint16(u[6:], uint16(timeNow&0xfff)) // set time_low (minus four version bits) - binary.BigEndian.PutUint16(u[8:], clockSeq&0x3fff) // set clk_seq_hi_res (minus two variant bits) - - u.SetVersion(V6) - u.SetVariant(VariantRFC4122) - - return u, nil -} - -// getClockSequence returns the epoch and clock sequence for V1,V6 and V7 UUIDs. -// -// When useUnixTSMs is false, it uses the Coordinated Universal Time (UTC) as a count of 100- -// -// nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of Gregorian reform to the Christian calendar). -func (g *Gen) getClockSequence(useUnixTSMs bool) (uint64, uint16, error) { - var err error - g.clockSequenceOnce.Do(func() { - buf := make([]byte, 2) - if _, err = io.ReadFull(g.rand, buf); err != nil { - return - } - g.clockSequence = binary.BigEndian.Uint16(buf) - }) - if err != nil { - return 0, 0, err - } - - g.storageMutex.Lock() - defer g.storageMutex.Unlock() - - var timeNow uint64 - if useUnixTSMs { - timeNow = uint64(g.epochFunc().UnixMilli()) - } else { - timeNow = g.getEpoch() - } - // Clock didn't change since last UUID generation. - // Should increase clock sequence. - if timeNow <= g.lastTime { - g.clockSequence++ - } - g.lastTime = timeNow - - return timeNow, g.clockSequence, nil -} - -// NewV7 returns a k-sortable UUID based on the current millisecond precision -// UNIX epoch and 74 bits of pseudorandom data. -// -// This is implemented based on revision 04 of the Peabody UUID draft, and may -// be subject to change pending further revisions. Until the final specification -// revision is finished, changes required to implement updates to the spec will -// not be considered a breaking change. They will happen as a minor version -// releases until the spec is final. -func (g *Gen) NewV7() (UUID, error) { - var u UUID - /* https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#name-uuid-version-7 - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | unix_ts_ms | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | unix_ts_ms | ver | rand_a | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |var| rand_b | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | rand_b | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - - ms, clockSeq, err := g.getClockSequence(true) - if err != nil { - return Nil, err - } - //UUIDv7 features a 48 bit timestamp. First 32bit (4bytes) represents seconds since 1970, followed by 2 bytes for the ms granularity. - u[0] = byte(ms >> 40) //1-6 bytes: big-endian unsigned number of Unix epoch timestamp - u[1] = byte(ms >> 32) - u[2] = byte(ms >> 24) - u[3] = byte(ms >> 16) - u[4] = byte(ms >> 8) - u[5] = byte(ms) - - //support batching by using a monotonic pseudo-random sequence - //The 6th byte contains the version and partially rand_a data. - //We will lose the most significant bites from the clockSeq (with SetVersion), but it is ok, we need the least significant that contains the counter to ensure the monotonic property - binary.BigEndian.PutUint16(u[6:8], clockSeq) // set rand_a with clock seq which is random and monotonic - - //override first 4bits of u[6]. - u.SetVersion(V7) - - //set rand_b 64bits of pseudo-random bits (first 2 will be overridden) - if _, err = io.ReadFull(g.rand, u[8:16]); err != nil { - return Nil, err - } - //override first 2 bits of byte[8] for the variant - u.SetVariant(VariantRFC4122) - - return u, nil -} - -// Returns the hardware address. -func (g *Gen) getHardwareAddr() ([]byte, error) { - var err error - g.hardwareAddrOnce.Do(func() { - var hwAddr net.HardwareAddr - if hwAddr, err = g.hwAddrFunc(); err == nil { - copy(g.hardwareAddr[:], hwAddr) - return - } - - // Initialize hardwareAddr randomly in case - // of real network interfaces absence. - if _, err = io.ReadFull(g.rand, g.hardwareAddr[:]); err != nil { - return - } - // Set multicast bit as recommended by RFC-4122 - g.hardwareAddr[0] |= 0x01 - }) - if err != nil { - return []byte{}, err - } - return g.hardwareAddr[:], nil -} - -// Returns the difference between UUID epoch (October 15, 1582) -// and current time in 100-nanosecond intervals. -func (g *Gen) getEpoch() uint64 { - return epochStart + uint64(g.epochFunc().UnixNano()/100) -} - -// Returns the UUID based on the hashing of the namespace UUID and name. -func newFromHash(h hash.Hash, ns UUID, name string) UUID { - u := UUID{} - h.Write(ns[:]) - h.Write([]byte(name)) - copy(u[:], h.Sum(nil)) - - return u -} - -var netInterfaces = net.Interfaces - -// Returns the hardware address. -func defaultHWAddrFunc() (net.HardwareAddr, error) { - ifaces, err := netInterfaces() - if err != nil { - return []byte{}, err - } - for _, iface := range ifaces { - if len(iface.HardwareAddr) >= 6 { - return iface.HardwareAddr, nil - } - } - return []byte{}, fmt.Errorf("uuid: no HW address found") -} diff --git a/vendor/github.com/gofrs/uuid/sql.go b/vendor/github.com/gofrs/uuid/sql.go deleted file mode 100644 index 01d5d88496..0000000000 --- a/vendor/github.com/gofrs/uuid/sql.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "database/sql" - "database/sql/driver" - "fmt" -) - -var _ driver.Valuer = UUID{} -var _ sql.Scanner = (*UUID)(nil) - -// Value implements the driver.Valuer interface. -func (u UUID) Value() (driver.Value, error) { - return u.String(), nil -} - -// Scan implements the sql.Scanner interface. -// A 16-byte slice will be handled by UnmarshalBinary, while -// a longer byte slice or a string will be handled by UnmarshalText. -func (u *UUID) Scan(src interface{}) error { - switch src := src.(type) { - case UUID: // support gorm convert from UUID to NullUUID - *u = src - return nil - - case []byte: - if len(src) == Size { - return u.UnmarshalBinary(src) - } - return u.UnmarshalText(src) - - case string: - uu, err := FromString(src) - *u = uu - return err - } - - return fmt.Errorf("uuid: cannot convert %T to UUID", src) -} - -// NullUUID can be used with the standard sql package to represent a -// UUID value that can be NULL in the database. -type NullUUID struct { - UUID UUID - Valid bool -} - -// Value implements the driver.Valuer interface. -func (u NullUUID) Value() (driver.Value, error) { - if !u.Valid { - return nil, nil - } - // Delegate to UUID Value function - return u.UUID.Value() -} - -// Scan implements the sql.Scanner interface. -func (u *NullUUID) Scan(src interface{}) error { - if src == nil { - u.UUID, u.Valid = Nil, false - return nil - } - - // Delegate to UUID Scan function - u.Valid = true - return u.UUID.Scan(src) -} - -var nullJSON = []byte("null") - -// MarshalJSON marshals the NullUUID as null or the nested UUID -func (u NullUUID) MarshalJSON() ([]byte, error) { - if !u.Valid { - return nullJSON, nil - } - var buf [38]byte - buf[0] = '"' - encodeCanonical(buf[1:37], u.UUID) - buf[37] = '"' - return buf[:], nil -} - -// UnmarshalJSON unmarshals a NullUUID -func (u *NullUUID) UnmarshalJSON(b []byte) error { - if string(b) == "null" { - u.UUID, u.Valid = Nil, false - return nil - } - if n := len(b); n >= 2 && b[0] == '"' { - b = b[1 : n-1] - } - err := u.UUID.UnmarshalText(b) - u.Valid = (err == nil) - return err -} diff --git a/vendor/github.com/gofrs/uuid/uuid.go b/vendor/github.com/gofrs/uuid/uuid.go deleted file mode 100644 index 5320fb5389..0000000000 --- a/vendor/github.com/gofrs/uuid/uuid.go +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright (C) 2013-2018 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Package uuid provides implementations of the Universally Unique Identifier -// (UUID), as specified in RFC-4122 and the Peabody RFC Draft (revision 03). -// -// RFC-4122[1] provides the specification for versions 1, 3, 4, and 5. The -// Peabody UUID RFC Draft[2] provides the specification for the new k-sortable -// UUIDs, versions 6 and 7. -// -// DCE 1.1[3] provides the specification for version 2, but version 2 support -// was removed from this package in v4 due to some concerns with the -// specification itself. Reading the spec, it seems that it would result in -// generating UUIDs that aren't very unique. In having read the spec it seemed -// that our implementation did not meet the spec. It also seems to be at-odds -// with RFC 4122, meaning we would need quite a bit of special code to support -// it. Lastly, there were no Version 2 implementations that we could find to -// ensure we were understanding the specification correctly. -// -// [1] https://tools.ietf.org/html/rfc4122 -// [2] https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03 -// [3] http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 -package uuid - -import ( - "encoding/binary" - "encoding/hex" - "fmt" - "time" -) - -// Size of a UUID in bytes. -const Size = 16 - -// UUID is an array type to represent the value of a UUID, as defined in RFC-4122. -type UUID [Size]byte - -// UUID versions. -const ( - _ byte = iota - V1 // Version 1 (date-time and MAC address) - _ // Version 2 (date-time and MAC address, DCE security version) [removed] - V3 // Version 3 (namespace name-based) - V4 // Version 4 (random) - V5 // Version 5 (namespace name-based) - V6 // Version 6 (k-sortable timestamp and random data, field-compatible with v1) [peabody draft] - V7 // Version 7 (k-sortable timestamp and random data) [peabody draft] - _ // Version 8 (k-sortable timestamp, meant for custom implementations) [peabody draft] [not implemented] -) - -// UUID layout variants. -const ( - VariantNCS byte = iota - VariantRFC4122 - VariantMicrosoft - VariantFuture -) - -// UUID DCE domains. -const ( - DomainPerson = iota - DomainGroup - DomainOrg -) - -// Timestamp is the count of 100-nanosecond intervals since 00:00:00.00, -// 15 October 1582 within a V1 UUID. This type has no meaning for other -// UUID versions since they don't have an embedded timestamp. -type Timestamp uint64 - -const _100nsPerSecond = 10000000 - -// Time returns the UTC time.Time representation of a Timestamp -func (t Timestamp) Time() (time.Time, error) { - secs := uint64(t) / _100nsPerSecond - nsecs := 100 * (uint64(t) % _100nsPerSecond) - - return time.Unix(int64(secs)-(epochStart/_100nsPerSecond), int64(nsecs)), nil -} - -// TimestampFromV1 returns the Timestamp embedded within a V1 UUID. -// Returns an error if the UUID is any version other than 1. -func TimestampFromV1(u UUID) (Timestamp, error) { - if u.Version() != 1 { - err := fmt.Errorf("uuid: %s is version %d, not version 1", u, u.Version()) - return 0, err - } - - low := binary.BigEndian.Uint32(u[0:4]) - mid := binary.BigEndian.Uint16(u[4:6]) - hi := binary.BigEndian.Uint16(u[6:8]) & 0xfff - - return Timestamp(uint64(low) + (uint64(mid) << 32) + (uint64(hi) << 48)), nil -} - -// TimestampFromV6 returns the Timestamp embedded within a V6 UUID. This -// function returns an error if the UUID is any version other than 6. -// -// This is implemented based on revision 03 of the Peabody UUID draft, and may -// be subject to change pending further revisions. Until the final specification -// revision is finished, changes required to implement updates to the spec will -// not be considered a breaking change. They will happen as a minor version -// releases until the spec is final. -func TimestampFromV6(u UUID) (Timestamp, error) { - if u.Version() != 6 { - return 0, fmt.Errorf("uuid: %s is version %d, not version 6", u, u.Version()) - } - - hi := binary.BigEndian.Uint32(u[0:4]) - mid := binary.BigEndian.Uint16(u[4:6]) - low := binary.BigEndian.Uint16(u[6:8]) & 0xfff - - return Timestamp(uint64(low) + (uint64(mid) << 12) + (uint64(hi) << 28)), nil -} - -// Nil is the nil UUID, as specified in RFC-4122, that has all 128 bits set to -// zero. -var Nil = UUID{} - -// Predefined namespace UUIDs. -var ( - NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) - NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) - NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) - NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) -) - -// IsNil returns if the UUID is equal to the nil UUID -func (u UUID) IsNil() bool { - return u == Nil -} - -// Version returns the algorithm version used to generate the UUID. -func (u UUID) Version() byte { - return u[6] >> 4 -} - -// Variant returns the UUID layout variant. -func (u UUID) Variant() byte { - switch { - case (u[8] >> 7) == 0x00: - return VariantNCS - case (u[8] >> 6) == 0x02: - return VariantRFC4122 - case (u[8] >> 5) == 0x06: - return VariantMicrosoft - case (u[8] >> 5) == 0x07: - fallthrough - default: - return VariantFuture - } -} - -// Bytes returns a byte slice representation of the UUID. -func (u UUID) Bytes() []byte { - return u[:] -} - -// encodeCanonical encodes the canonical RFC-4122 form of UUID u into the -// first 36 bytes dst. -func encodeCanonical(dst []byte, u UUID) { - const hextable = "0123456789abcdef" - dst[8] = '-' - dst[13] = '-' - dst[18] = '-' - dst[23] = '-' - for i, x := range [16]byte{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34, - } { - c := u[i] - dst[x] = hextable[c>>4] - dst[x+1] = hextable[c&0x0f] - } -} - -// String returns a canonical RFC-4122 string representation of the UUID: -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. -func (u UUID) String() string { - var buf [36]byte - encodeCanonical(buf[:], u) - return string(buf[:]) -} - -// Format implements fmt.Formatter for UUID values. -// -// The behavior is as follows: -// The 'x' and 'X' verbs output only the hex digits of the UUID, using a-f for 'x' and A-F for 'X'. -// The 'v', '+v', 's' and 'q' verbs return the canonical RFC-4122 string representation. -// The 'S' verb returns the RFC-4122 format, but with capital hex digits. -// The '#v' verb returns the "Go syntax" representation, which is a 16 byte array initializer. -// All other verbs not handled directly by the fmt package (like '%p') are unsupported and will return -// "%!verb(uuid.UUID=value)" as recommended by the fmt package. -func (u UUID) Format(f fmt.State, c rune) { - if c == 'v' && f.Flag('#') { - fmt.Fprintf(f, "%#v", [Size]byte(u)) - return - } - switch c { - case 'x', 'X': - b := make([]byte, 32) - hex.Encode(b, u[:]) - if c == 'X' { - toUpperHex(b) - } - _, _ = f.Write(b) - case 'v', 's', 'S': - b, _ := u.MarshalText() - if c == 'S' { - toUpperHex(b) - } - _, _ = f.Write(b) - case 'q': - b := make([]byte, 38) - b[0] = '"' - encodeCanonical(b[1:], u) - b[37] = '"' - _, _ = f.Write(b) - default: - // invalid/unsupported format verb - fmt.Fprintf(f, "%%!%c(uuid.UUID=%s)", c, u.String()) - } -} - -func toUpperHex(b []byte) { - for i, c := range b { - if 'a' <= c && c <= 'f' { - b[i] = c - ('a' - 'A') - } - } -} - -// SetVersion sets the version bits. -func (u *UUID) SetVersion(v byte) { - u[6] = (u[6] & 0x0f) | (v << 4) -} - -// SetVariant sets the variant bits. -func (u *UUID) SetVariant(v byte) { - switch v { - case VariantNCS: - u[8] = (u[8]&(0xff>>1) | (0x00 << 7)) - case VariantRFC4122: - u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) - case VariantMicrosoft: - u[8] = (u[8]&(0xff>>3) | (0x06 << 5)) - case VariantFuture: - fallthrough - default: - u[8] = (u[8]&(0xff>>3) | (0x07 << 5)) - } -} - -// Must is a helper that wraps a call to a function returning (UUID, error) -// and panics if the error is non-nil. It is intended for use in variable -// initializations such as -// -// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000")) -func Must(u UUID, err error) UUID { - if err != nil { - panic(err) - } - return u -} diff --git a/vendor/github.com/libregraph/lico/CHANGELOG.md b/vendor/github.com/libregraph/lico/CHANGELOG.md index e17627f1af..dde77f5fac 100644 --- a/vendor/github.com/libregraph/lico/CHANGELOG.md +++ b/vendor/github.com/libregraph/lico/CHANGELOG.md @@ -4,7 +4,31 @@ -## v0.66.0 (2025-04-28) +## v0.67.0 (2026-03-18) + +- Bump github.com/russellhaering/goxmldsig from 1.5.0 to 1.6.0 +- Run npx update-browserslist-db@latest +- Add signed JWT auto sign-in flow (LibreGraph.SignedLoginOK) +- Fix Go formatting treewide +- Add per-client external authorize redirect URIs +- Rework banner logo height to use named sizes instead of pixels +- Add configurable banner logo height via --identifier-default-banner-logo-height +- Bump docs to match Go 1.24 requirement +- Bump github.com/prometheus/client_golang from 1.15.1 to 1.23.2 +- Bump github.com/beevik/etree from 1.5.1 to 1.6.0 +- Bump golang.org/x/crypto from 0.37.0 to 0.45.0 +- chore: drop gofrs/uuid module usage and use google/uuid +- Update golangci-lint to version 2 +- Bump golang.org/x/oauth2 from 0.8.0 to 0.31.0 +- Bump golang.org/x/time from 0.3.0 to 0.13.0 +- Bump form-data from 4.0.0 to 4.0.4 in /identifier +- Bump golang.org/x/oauth2 from 0.8.0 to 0.27.0 +- Fix typos an add API section to README +- Fix form submission handler regression introduced in class-to-functional conversion +- Replace konnect-identifier-api-v1 with comprehensive LibreGraph Connect OpenAPI spec + + +## v0.66.0 (2025-05-12) - Remove built-in survey client from the licod runner - Bump caniuse-lite to latest diff --git a/vendor/github.com/libregraph/lico/README.md b/vendor/github.com/libregraph/lico/README.md index 8c5b4221d5..a8db42ef0c 100644 --- a/vendor/github.com/libregraph/lico/README.md +++ b/vendor/github.com/libregraph/lico/README.md @@ -40,7 +40,7 @@ combine the implementation details. ## Build dependencies -Make sure you have Go 1.18 or later installed. This project uses Go Modules. +Make sure you have Go 1.24 or later installed. This project uses Go Modules. Lico also includes a modern web app which requires a couple of additional build dependencies which are furthermore also assumed to be in your $PATH. @@ -51,7 +51,7 @@ build dependencies which are furthermore also assumed to be in your $PATH. To build Lico, a `Makefile` is provided, which requires [make](https://www.gnu.org/software/make/manual/make.html). -When building, third party dependencies will tried to be fetched from the Internet +When building, third party dependencies will be fetched from the Internet if not there already. ## Building from source @@ -99,7 +99,7 @@ this, Lico will generate a random key on startup. To run a functional OpenID Connect provider, an issuer identifier is required. The `iss` is a full qualified https:// URI pointing to the web server which serves the requests to Lico (example: https://example.com). Provide the -Issuer Identifier with the `--iss` parametter when starting Lico. +Issuer Identifier with the `--iss` parameter when starting Lico. Furthermore to allow clients to utilize the Lico services, clients need to be known/registered. For now Lico uses a static configuration file which @@ -149,6 +149,10 @@ The base URL of the frontend proxy is what will become the value of the `--iss` parameter when starting up Lico. OIDC requires the Issuer Identifier to be secure (https:// required). +## API Documentation + +The complete API specification is available in OpenAPI 3.0 format at [`docs/libregraph-connect-api-v1.yaml`](docs/libregraph-connect-api-v1.yaml), covering all OIDC, OAuth2, authentication, and SAML2 endpoints with detailed schemas and examples. + ### LibreGraph backend Generic backend support is available through the LibreGraph API. Any service can 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 7b8604d373..dbd7621307 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go +++ b/vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go @@ -144,6 +144,7 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { SignedOutEndpointURI: fullSignedOutEndpointURL, DefaultBannerLogo: config.IdentifierDefaultBannerLogo, + DefaultBannerLogoHeight: config.IdentifierDefaultBannerLogoHeight, DefaultSignInPageText: config.IdentifierDefaultSignInPageText, DefaultSignInPageLogoURI: config.IdentifierDefaultLogoTargetURI, DefaultUsernameHintText: config.IdentifierDefaultUsernameHintText, @@ -159,13 +160,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { return nil, fmt.Errorf("invalid --encryption-secret parameter value for identifier: %v", err) } + // Expose the identifier in the managers registry so other managers (e.g. + // signedlogin) can access it without creating a second instance. + bs.Managers().Set("identifier", activeIdentifier) + identityManagerConfig := &identity.Config{ SignInFormURI: fullSignInFormURL, SignedOutURI: fullSignedOutEndpointURL, Logger: logger, - ScopesSupported: config.Config.AllowedScopes, + ScopesSupported: config.Config.AllowedScopes, + AllowSignedLogin: config.Config.AllowClientSignedLogins, } identifierIdentityManager := managers.NewIdentifierIdentityManager(identityManagerConfig, activeIdentifier) 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 ded47b49c8..04c27218be 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go +++ b/vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go @@ -127,6 +127,7 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { SignedOutEndpointURI: fullSignedOutEndpointURL, DefaultBannerLogo: config.IdentifierDefaultBannerLogo, + DefaultBannerLogoHeight: config.IdentifierDefaultBannerLogoHeight, DefaultSignInPageText: config.IdentifierDefaultSignInPageText, DefaultSignInPageLogoURI: config.IdentifierDefaultLogoTargetURI, DefaultUsernameHintText: config.IdentifierDefaultUsernameHintText, @@ -142,13 +143,18 @@ func NewIdentityManager(bs bootstrap.Bootstrap) (identity.Manager, error) { return nil, fmt.Errorf("invalid --encryption-secret parameter value for identifier: %v", err) } + // Expose the identifier in the managers registry so other managers (e.g. + // signedlogin) can access it without creating a second instance. + bs.Managers().Set("identifier", activeIdentifier) + identityManagerConfig := &identity.Config{ SignInFormURI: fullSignInFormURL, SignedOutURI: fullSignedOutEndpointURL, Logger: logger, - ScopesSupported: config.Config.AllowedScopes, + ScopesSupported: config.Config.AllowedScopes, + AllowSignedLogin: config.Config.AllowClientSignedLogins, } identifierIdentityManager := managers.NewIdentifierIdentityManager(identityManagerConfig, activeIdentifier) diff --git a/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go b/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go index a06ac94671..14bd2b3ce8 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go +++ b/vendor/github.com/libregraph/lico/bootstrap/bootstrap.go @@ -206,6 +206,11 @@ func (bs *bootstrap) initialize(settings *Settings) error { logger.Infoln("client controlled guests are enabled") } + bs.config.Config.AllowClientSignedLogins = settings.AllowClientSignedLogins + if bs.config.Config.AllowClientSignedLogins { + logger.Infoln("client controlled signed logins are enabled") + } + bs.config.Config.AllowDynamicClientRegistration = settings.AllowDynamicClientRegistration if bs.config.Config.AllowDynamicClientRegistration { logger.Infoln("dynamic client registration is enabled") @@ -257,6 +262,9 @@ func (bs *bootstrap) initialize(settings *Settings) error { } bs.config.IdentifierDefaultBannerLogo = b } + if settings.IdentifierDefaultBannerLogoHeight != "" { + bs.config.IdentifierDefaultBannerLogoHeight = &settings.IdentifierDefaultBannerLogoHeight + } if settings.IdentifierDefaultSignInPageText != "" { bs.config.IdentifierDefaultSignInPageText = &settings.IdentifierDefaultSignInPageText } diff --git a/vendor/github.com/libregraph/lico/bootstrap/config.go b/vendor/github.com/libregraph/lico/bootstrap/config.go index 8abe40ffb3..f0ce082f84 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/config.go +++ b/vendor/github.com/libregraph/lico/bootstrap/config.go @@ -50,6 +50,7 @@ type Config struct { IdentifierAuthoritiesConf string IdentifierScopesConf string IdentifierDefaultBannerLogo []byte + IdentifierDefaultBannerLogoHeight *string IdentifierDefaultSignInPageText *string IdentifierDefaultLogoTargetURI *string IdentifierDefaultUsernameHintText *string diff --git a/vendor/github.com/libregraph/lico/bootstrap/settings.go b/vendor/github.com/libregraph/lico/bootstrap/settings.go index 549831ff56..0a4b050a84 100644 --- a/vendor/github.com/libregraph/lico/bootstrap/settings.go +++ b/vendor/github.com/libregraph/lico/bootstrap/settings.go @@ -35,6 +35,7 @@ type Settings struct { TrustedProxy []string AllowScope []string AllowClientGuests bool + AllowClientSignedLogins bool AllowDynamicClientRegistration bool EncryptionSecretFile string Listen string @@ -43,6 +44,7 @@ type Settings struct { IdentifierRegistrationConf string IdentifierScopesConf string IdentifierDefaultBannerLogo string + IdentifierDefaultBannerLogoHeight string IdentifierDefaultSignInPageText string IdentifierDefaultLogoTargetURI string IdentifierDefaultUsernameHintText string diff --git a/vendor/github.com/libregraph/lico/config/config.go b/vendor/github.com/libregraph/lico/config/config.go index 4f5d7d36e3..5c803d610d 100644 --- a/vendor/github.com/libregraph/lico/config/config.go +++ b/vendor/github.com/libregraph/lico/config/config.go @@ -38,5 +38,6 @@ type Config struct { AllowedScopes []string AllowClientGuests bool + AllowClientSignedLogins bool AllowDynamicClientRegistration bool } diff --git a/vendor/github.com/libregraph/lico/identifier-registration.yaml.in b/vendor/github.com/libregraph/lico/identifier-registration.yaml.in index 31796a7a7a..30eab192fe 100644 --- a/vendor/github.com/libregraph/lico/identifier-registration.yaml.in +++ b/vendor/github.com/libregraph/lico/identifier-registration.yaml.in @@ -21,6 +21,20 @@ clients: # origins: # - https://my-host:8509 +# - id: playground-trusted.js +# name: Trusted OIDC Playground with External Login +# trusted: yes +# application_type: web +# redirect_uris: +# - https://my-host:8509/ +# origins: +# - https://my-host:8509 +# external_authorize_redirect_uris: +# # Default external login URI used for any scope. +# - https://my-external-login:8443/authorize +# # Scope-specific URI used when the given scope is requested. +# - MyApp.Special:https://my-external-login:8443/authorize-special + # - id: playground-trusted.js # name: Trusted Insecure OIDC Playground # trusted: yes diff --git a/vendor/github.com/libregraph/lico/identifier/api.go b/vendor/github.com/libregraph/lico/identifier/api.go index 74c158e036..6a849b2880 100644 --- a/vendor/github.com/libregraph/lico/identifier/api.go +++ b/vendor/github.com/libregraph/lico/identifier/api.go @@ -48,6 +48,7 @@ func (i Identifier) writeHelloResponse(rw http.ResponseWriter, req *http.Request State: r.State, Branding: &meta.Branding{ BannerLogo: i.defaultBannerLogo, + BannerLogoHeight: i.defaultBannerLogoHeight, UsernameHintText: i.Config.DefaultUsernameHintText, SignInPageText: i.Config.DefaultSignInPageText, SignInPageLogoURI: i.Config.DefaultSignInPageLogoURI, diff --git a/vendor/github.com/libregraph/lico/identifier/backends/ldap/ldap.go b/vendor/github.com/libregraph/lico/identifier/backends/ldap/ldap.go index 3413106a6a..00fca317d4 100644 --- a/vendor/github.com/libregraph/lico/identifier/backends/ldap/ldap.go +++ b/vendor/github.com/libregraph/lico/identifier/backends/ldap/ldap.go @@ -29,7 +29,7 @@ import ( "time" "github.com/go-ldap/ldap/v3" - uuid "github.com/gofrs/uuid" + uuid "github.com/google/uuid" "github.com/libregraph/oidc-go" "github.com/sirupsen/logrus" "golang.org/x/time/rate" diff --git a/vendor/github.com/libregraph/lico/identifier/config.go b/vendor/github.com/libregraph/lico/identifier/config.go index 2750f599b8..4e9618efbf 100644 --- a/vendor/github.com/libregraph/lico/identifier/config.go +++ b/vendor/github.com/libregraph/lico/identifier/config.go @@ -47,6 +47,7 @@ type Config struct { SignedOutEndpointURI *url.URL DefaultBannerLogo []byte + DefaultBannerLogoHeight *string DefaultSignInPageText *string DefaultSignInPageLogoURI *string DefaultUsernameHintText *string diff --git a/vendor/github.com/libregraph/lico/identifier/identifier.go b/vendor/github.com/libregraph/lico/identifier/identifier.go index fefc05959b..708d11569c 100644 --- a/vendor/github.com/libregraph/lico/identifier/identifier.go +++ b/vendor/github.com/libregraph/lico/identifier/identifier.go @@ -85,7 +85,8 @@ type Identifier struct { meta *meta.Meta - defaultBannerLogo *string + defaultBannerLogo *string + defaultBannerLogoHeight *string onSetLogonCallbacks []func(ctx context.Context, rw http.ResponseWriter, user identity.User) error onUnsetLogonCallbacks []func(ctx context.Context, rw http.ResponseWriter) error @@ -157,6 +158,7 @@ func NewIdentifier(c *Config) (*Identifier, error) { } i.defaultBannerLogo = &defaultBannerLogo } + i.defaultBannerLogoHeight = c.DefaultBannerLogoHeight i.meta.Scopes.Extend(c.Backend.ScopesMeta()) @@ -267,27 +269,26 @@ func (i *Identifier) ErrorPage(rw http.ResponseWriter, code int, title string, m utils.WriteErrorPage(rw, code, title, message) } -// SetUserToLogonCookie serializes the provided user into an encrypted string -// and sets it as cookie on the provided http.ResponseWriter. -func (i *Identifier) SetUserToLogonCookie(ctx context.Context, rw http.ResponseWriter, user *IdentifiedUser) error { +// WriteLogonCookie serializes the provided user into an encrypted string and +// sets it as a logon cookie without firing any callbacks. Use this when the +// cookie must be written mid-flow (e.g. inside an authorize handler) where +// the caller is responsible for updating browser state separately. +func (i *Identifier) WriteLogonCookie(rw http.ResponseWriter, user *IdentifiedUser) error { loggedOn, logonAt := user.LoggedOn() if !loggedOn { return fmt.Errorf("refused to set cookie for not logged on user") } - // Add standard claims. claims := jwt.Claims{ Issuer: user.BackendName(), Audience: audienceMarker, Subject: user.Subject(), IssuedAt: jwt.NewNumericDate(logonAt), } - // Add expiration, if set. if user.expiresAfter != nil { claims.Expiry = jwt.NewNumericDate(*user.expiresAfter) } - // Additional claims. userClaims := map[string]interface{}(user.Claims()) if sessionRef := user.SessionRef(); sessionRef != nil { userClaims[SessionIDClaim] = *sessionRef @@ -302,25 +303,27 @@ func (i *Identifier) SetUserToLogonCookie(ctx context.Context, rw http.ResponseW userClaims[LockedScopesClaim] = strings.Join(lockedScopes, " ") } - // Serialize and encrypt cookie value. serialized, err := jwt.Encrypted(i.encrypter).Claims(claims).Claims(userClaims).CompactSerialize() if err != nil { return err } - // Set cookie. - err = i.setLogonCookie(rw, serialized) - if err != nil { + return i.setLogonCookie(rw, serialized) +} + +// SetUserToLogonCookie serializes the provided user into an encrypted string, +// sets it as cookie on the provided http.ResponseWriter, and fires the +// onSetLogon callbacks. +func (i *Identifier) SetUserToLogonCookie(ctx context.Context, rw http.ResponseWriter, user *IdentifiedUser) error { + if err := i.WriteLogonCookie(rw, user); err != nil { return err } // Trigger callbacks. for _, f := range i.onSetLogonCallbacks { - err = f(ctx, rw, user) - if err != nil { + if err := f(ctx, rw, user); err != nil { return err } } - return nil } diff --git a/vendor/github.com/libregraph/lico/identifier/meta/branding.go b/vendor/github.com/libregraph/lico/identifier/meta/branding.go index f6778da89e..227ee6aa32 100644 --- a/vendor/github.com/libregraph/lico/identifier/meta/branding.go +++ b/vendor/github.com/libregraph/lico/identifier/meta/branding.go @@ -20,6 +20,7 @@ package meta // Branding is a container to hold identifier branding meta data. type Branding struct { BannerLogo *string `json:"bannerLogo,omitempty"` + BannerLogoHeight *string `json:"bannerLogoHeight,omitempty"` SignInPageText *string `json:"signinPageText,omitempty"` UsernameHintText *string `json:"usernameHintText,omitempty"` SignInPageLogoURI *string `json:"signinPageLogoURI,omitempty"` diff --git a/vendor/github.com/libregraph/lico/identifier/models.go b/vendor/github.com/libregraph/lico/identifier/models.go index 34d02abf90..6cfb310fb4 100644 --- a/vendor/github.com/libregraph/lico/identifier/models.go +++ b/vendor/github.com/libregraph/lico/identifier/models.go @@ -158,7 +158,7 @@ type Consent struct { } // Scopes returns the associated consents approved scopes filtered by the -//provided requested scopes and the full unfiltered approved scopes table. +// provided requested scopes and the full unfiltered approved scopes table. func (c *Consent) Scopes(requestedScopes map[string]bool) (map[string]bool, map[string]bool) { scopes := make(map[string]bool) if c.RawScope != "" { diff --git a/vendor/github.com/libregraph/lico/identifier/user.go b/vendor/github.com/libregraph/lico/identifier/user.go index 97db734c6e..fb3fdd81d8 100644 --- a/vendor/github.com/libregraph/lico/identifier/user.go +++ b/vendor/github.com/libregraph/lico/identifier/user.go @@ -146,6 +146,12 @@ func (u *IdentifiedUser) LoggedOn() (bool, time.Time) { return !u.logonAt.IsZero(), u.logonAt } +// SetLogonAt sets the logon timestamp, marking the user as logged on. Used by +// flows that authenticate without a password challenge (e.g. signed login). +func (u *IdentifiedUser) SetLogonAt(t time.Time) { + u.logonAt = t +} + // SessionRef returns the accociated users underlaying session reference. func (u *IdentifiedUser) SessionRef() *string { return u.sessionRef diff --git a/vendor/github.com/libregraph/lico/identity/clients/models.go b/vendor/github.com/libregraph/lico/identity/clients/models.go index 5a167e5a77..663c814239 100644 --- a/vendor/github.com/libregraph/lico/identity/clients/models.go +++ b/vendor/github.com/libregraph/lico/identity/clients/models.go @@ -23,6 +23,8 @@ import ( "crypto/subtle" "encoding/base64" "fmt" + "net/url" + "strings" "time" "github.com/golang-jwt/jwt/v5" @@ -52,7 +54,8 @@ type ClientRegistration struct { TrustedScopes []string `yaml:"trusted_scopes" json:"-"` Insecure bool `yaml:"insecure" json:"-"` - ImplicitScopes []string `yaml:"implicit_scopes" json:"-"` + ImplicitScopes []string `yaml:"implicit_scopes" json:"-"` + ExternalAuthorizeRedirectURIs []string `yaml:"external_authorize_redirect_uris,flow" json:"-"` Dynamic bool `yaml:"-" json:"-"` IDIssuedAt time.Time `yaml:"-" json:"-"` @@ -81,6 +84,23 @@ type ClientRegistration struct { // Validate validates the associated client registration data and returns error // if the data is not valid. func (cr *ClientRegistration) Validate() error { + for _, entry := range cr.ExternalAuthorizeRedirectURIs { + uri := entry + // Strip scope prefix if present using the colon heuristic. + if idx := strings.Index(entry, ":"); idx > 0 { + rest := entry[idx+1:] + if !strings.HasPrefix(rest, "//") { + uri = rest + } + } + parsed, err := url.Parse(uri) + if err != nil || parsed.Scheme == "" || parsed.Host == "" { + return fmt.Errorf("invalid external_authorize_redirect_uri: %v", entry) + } + if parsed.Scheme != "https" { + return fmt.Errorf("external_authorize_redirect_uri must use https: %v", entry) + } + } return nil } @@ -200,6 +220,46 @@ func (cr *ClientRegistration) ApplyImplicitScopes(scopes map[string]bool) error return nil } +// GetExternalAuthorizeRedirectURI returns the external authorize redirect URI +// for the given scopes. A scope-specific match takes precedence over the +// default. Returns empty string if none is configured. +func (cr *ClientRegistration) GetExternalAuthorizeRedirectURI(scopes map[string]bool) string { + if len(cr.ExternalAuthorizeRedirectURIs) == 0 { + return "" + } + + var defaultURI string + scopedURIs := make(map[string]string) + for _, entry := range cr.ExternalAuthorizeRedirectURIs { + if idx := strings.Index(entry, ":"); idx > 0 { + rest := entry[idx+1:] + // If the remainder starts with "//", this is a plain URL with + // no scope prefix (e.g. https://...). + if !strings.HasPrefix(rest, "//") { + scopedURIs[entry[:idx]] = rest + continue + } + } + if defaultURI == "" { + defaultURI = entry + } + } + + // Try to find a scope-specific match. + if scopes != nil { + for scope, ok := range scopes { + if !ok { + continue + } + if u, found := scopedURIs[scope]; found { + return u + } + } + } + + return defaultURI +} + func (cr *ClientRegistration) makeSecret(secret []byte) (string, string, error) { // Create random secret. HMAC the client name with it to get the subject. if secret == nil { diff --git a/vendor/github.com/libregraph/lico/identity/clients/registry.go b/vendor/github.com/libregraph/lico/identity/clients/registry.go index c30a08304a..b380e598e2 100644 --- a/vendor/github.com/libregraph/lico/identity/clients/registry.go +++ b/vendor/github.com/libregraph/lico/identity/clients/registry.go @@ -89,13 +89,14 @@ func NewRegistry(ctx context.Context, trustedURI *url.URL, registrationConfFilep validateErr := client.Validate() registerErr := r.Register(client) fields := logrus.Fields{ - "client_id": client.ID, - "with_client_secret": client.Secret != "", - "trusted": client.Trusted, - "insecure": client.Insecure, - "application_type": client.ApplicationType, - "redirect_uris": client.RedirectURIs, - "origins": client.Origins, + "client_id": client.ID, + "with_client_secret": client.Secret != "", + "trusted": client.Trusted, + "insecure": client.Insecure, + "application_type": client.ApplicationType, + "redirect_uris": client.RedirectURIs, + "origins": client.Origins, + "external_authorize_redirect_uris": client.ExternalAuthorizeRedirectURIs, } if validateErr != nil { diff --git a/vendor/github.com/libregraph/lico/identity/config.go b/vendor/github.com/libregraph/lico/identity/config.go index 12fbca20dc..21ab87aaee 100644 --- a/vendor/github.com/libregraph/lico/identity/config.go +++ b/vendor/github.com/libregraph/lico/identity/config.go @@ -30,5 +30,8 @@ type Config struct { ScopesSupported []string + // AllowSignedLogin enables the signed JWT auto sign-in flow. + AllowSignedLogin bool + Logger logrus.FieldLogger } diff --git a/vendor/github.com/libregraph/lico/identity/managers/identifier.go b/vendor/github.com/libregraph/lico/identity/managers/identifier.go index 156d274398..c186a3fa19 100644 --- a/vendor/github.com/libregraph/lico/identity/managers/identifier.go +++ b/vendor/github.com/libregraph/lico/identity/managers/identifier.go @@ -23,12 +23,16 @@ import ( "net/http" "net/url" "strings" + "sync" + "time" + "github.com/golang-jwt/jwt/v5" "github.com/gorilla/mux" "github.com/libregraph/oidc-go" "github.com/longsleep/rndm" "github.com/sirupsen/logrus" + konnect "github.com/libregraph/lico" "github.com/libregraph/lico/identifier" "github.com/libregraph/lico/identity" "github.com/libregraph/lico/identity/clients" @@ -47,9 +51,17 @@ type IdentifierIdentityManager struct { scopesSupported []string claimsSupported []string - identifier *identifier.Identifier - clients *clients.Registry - logger logrus.FieldLogger + identifier *identifier.Identifier + clients *clients.Registry + guestManager identity.Manager + logger logrus.FieldLogger + + allowSignedLogin bool + + // JTI replay prevention store for the signed login flow. + jtiMu sync.Mutex + jtiStore map[string]time.Time + jtiMaxAge time.Duration } type identifierUser struct { @@ -108,8 +120,11 @@ func NewIdentifierIdentityManager(c *identity.Config, i *identifier.Identifier) oidc.EmailVerifiedClaim, }, - identifier: i, - logger: c.Logger, + identifier: i, + logger: c.Logger, + allowSignedLogin: c.AllowSignedLogin, + jtiStore: make(map[string]time.Time), + jtiMaxAge: 10 * time.Minute, } return im @@ -119,9 +134,26 @@ func NewIdentifierIdentityManager(c *identity.Config, i *identifier.Identifier) func (im *IdentifierIdentityManager) RegisterManagers(mgrs *managers.Managers) error { im.clients = mgrs.Must("clients").(*clients.Registry) + // Wire guest manager as fallback if available. + if guestManager, ok := mgrs.Get("guest"); ok && guestManager != nil { + im.guestManager = guestManager.(identity.Manager) + } + return im.identifier.RegisterManagers(mgrs) } +// getSignInFormURI returns the sign-in form URI for the given client and +// scopes. If the client has a configured external authorize redirect URI, it +// is returned. Otherwise the default sign-in form URI is used. +func (im *IdentifierIdentityManager) getSignInFormURI(clientID string, scopes map[string]bool) string { + if registration, ok := im.clients.Get(context.Background(), clientID); ok && registration != nil { + if uri := registration.GetExternalAuthorizeRedirectURI(scopes); uri != "" { + return uri + } + } + return im.signInFormURI +} + // Authenticate implements the identity.Manager interface. func (im *IdentifierIdentityManager) Authenticate(ctx context.Context, rw http.ResponseWriter, req *http.Request, ar *payload.AuthenticationRequest, next identity.Manager) (identity.AuthRecord, error) { var user *identifierUser @@ -132,7 +164,14 @@ func (im *IdentifierIdentityManager) Authenticate(ctx context.Context, rw http.R return nil, ar.NewError(authenticationErrorID, req.Form.Get("error_description")) } + // When signed login is enabled and a signed JWT request is present, handle + // the signed login flow directly and bypass any existing session cookie. + if im.allowSignedLogin && ar.Scopes[konnect.ScopeSignedLoginOK] && ar.Request != nil { + return im.authenticateSignedLogin(ctx, rw, req, ar) + } + u, _ := im.identifier.GetUserFromLogonCookie(ctx, req, ar.MaxAge, true) + if u != nil { // TODO(longsleep): Add other user meta data. user = asIdentifierUser(u) @@ -254,7 +293,7 @@ func (im *IdentifierIdentityManager) Authenticate(ctx context.Context, rw http.R query.Set("claims_scope", strings.Join(claimsScopes, " ")) } } - u, _ := url.Parse(im.signInFormURI) + u, _ := url.Parse(im.getSignInFormURI(ar.ClientID, ar.Scopes)) u.RawQuery = query.Encode() utils.WriteRedirect(rw, http.StatusFound, u, nil, false) @@ -278,6 +317,11 @@ func (im *IdentifierIdentityManager) Authenticate(ctx context.Context, rw http.R // Authorize implements the identity.Manager interface. func (im *IdentifierIdentityManager) Authorize(ctx context.Context, rw http.ResponseWriter, req *http.Request, ar *payload.AuthenticationRequest, auth identity.AuthRecord) (identity.AuthRecord, error) { + // Route signed login authorizations through their own path. + if im.allowSignedLogin && ar.Scopes[konnect.ScopeSignedLoginOK] && ar.Request != nil { + return im.authorizeSignedLogin(ctx, rw, req, ar, auth) + } + promptConsent := false var approvedScopes map[string]bool @@ -407,6 +451,149 @@ func (im *IdentifierIdentityManager) Authorize(ctx context.Context, rw http.Resp return auth, nil } +// checkAndRecordJTI checks the JTI claim for replay and records it if new. +func (im *IdentifierIdentityManager) checkAndRecordJTI(ar *payload.AuthenticationRequest) error { + roc, ok := ar.Request.Claims.(*payload.RequestObjectClaims) + if !ok { + return nil + } + + jti := roc.ID + if jti == "" { + return fmt.Errorf("IdentifierIdentityManager: missing or invalid jti claim") + } + + now := time.Now() + exp := now.Add(im.jtiMaxAge) + + // Use the JWT expiry as TTL if shorter than the max age. + if expTime, err := roc.GetExpirationTime(); err == nil && expTime != nil { + if expTime.Time.Before(exp) { + exp = expTime.Time + } + } + + im.jtiMu.Lock() + defer im.jtiMu.Unlock() + + // Purge expired entries. + for k, v := range im.jtiStore { + if now.After(v) { + delete(im.jtiStore, k) + } + } + + if _, exists := im.jtiStore[jti]; exists { + return fmt.Errorf("IdentifierIdentityManager: replayed jti") + } + + im.jtiStore[jti] = exp + return nil +} + +// authenticateSignedLogin handles the signed JWT auto sign-in flow. +func (im *IdentifierIdentityManager) authenticateSignedLogin(ctx context.Context, rw http.ResponseWriter, req *http.Request, ar *payload.AuthenticationRequest) (identity.AuthRecord, error) { + if ar.Request.Method == jwt.SigningMethodNone { + return nil, ar.NewBadRequest(oidc.ErrorCodeOIDCInvalidRequestObject, "IdentifierIdentityManager: request object must be signed") + } + + roc, ok := ar.Request.Claims.(*payload.RequestObjectClaims) + if !ok || roc.Claims == nil || ar.Claims == nil || ar.Claims.IDToken == nil { + return nil, ar.NewError(oidc.ErrorCodeOAuth2InvalidRequest, "IdentifierIdentityManager: missing claims in request object") + } + + // Extract the login hint from the signed claims. + loginHint, ok := ar.Claims.IDToken.GetStringValue(oidc.PreferredUsernameClaim) + if !ok || loginHint == "" { + return nil, ar.NewBadRequest(oidc.ErrorCodeOAuth2InvalidRequest, "IdentifierIdentityManager: missing preferred_username claim") + } + + // JTI replay prevention. + if err := im.checkAndRecordJTI(ar); err != nil { + return nil, ar.NewBadRequest(oidc.ErrorCodeOAuth2InvalidRequest, err.Error()) + } + + // Look up user from the scoped backend. + u, err := im.identifier.GetUserFromID(ctx, loginHint, nil, ar.Scopes) + if err != nil { + im.logger.WithError(err).Errorln("IdentifierIdentityManager: signed login backend error") + return nil, ar.NewError(oidc.ErrorCodeOAuth2ServerError, "IdentifierIdentityManager: backend error") + } + if u == nil { + return nil, ar.NewError(oidc.ErrorCodeOAuth2AccessDenied, "IdentifierIdentityManager: user not found") + } + + user := asIdentifierUser(u) + + if err := ar.Verify(user.Subject()); err != nil { + return nil, err + } + + // Set logon time and write a session cookie so that subsequent + // authorization requests (silent renew, re-auth) succeed via the normal + // cookie path without requiring a new signed JWT each time. + authTime := time.Now() + u.SetLogonAt(authTime) + if cookieErr := im.identifier.WriteLogonCookie(rw, u); cookieErr != nil { + im.logger.WithError(cookieErr).Warnln("IdentifierIdentityManager: failed to set logon cookie") + } + + auth := identity.NewAuthRecord(im, user.Subject(), nil, nil, nil) + auth.SetUser(user) + auth.SetAuthTime(authTime) + return auth, nil +} + +// authorizeSignedLogin handles scope approval for the signed JWT auto sign-in flow. +func (im *IdentifierIdentityManager) authorizeSignedLogin(ctx context.Context, rw http.ResponseWriter, req *http.Request, ar *payload.AuthenticationRequest, auth identity.AuthRecord) (identity.AuthRecord, error) { + if ar.Request == nil { + return nil, ar.NewError(oidc.ErrorCodeOIDCInvalidRequestObject, "IdentifierIdentityManager: authorize without request object") + } + + roc, ok := ar.Request.Claims.(*payload.RequestObjectClaims) + if !ok { + return nil, ar.NewBadRequest(oidc.ErrorCodeOAuth2InvalidRequest, "IdentifierIdentityManager: authorize with invalid claims request") + } + + securedDetails := roc.Secure() + if securedDetails == nil { + return nil, ar.NewBadRequest(oidc.ErrorCodeOIDCInvalidRequestObject, "IdentifierIdentityManager: authorize without secure client") + } + + clientDetails, err := im.clients.Lookup(req.Context(), ar.ClientID, "", ar.RedirectURI, "", true) + if err != nil { + return nil, ar.NewError(oidc.ErrorCodeOAuth2AccessDenied, err.Error()) + } + if clientDetails.ID != securedDetails.ID { + return nil, ar.NewError(oidc.ErrorCodeOAuth2AccessDenied, "client mismatch") + } + + var approvedScopes map[string]bool + if clientDetails.Trusted && securedDetails.TrustedScopes == nil { + approvedScopes = ar.Scopes + } else { + // Approve openid plus any scope in the client's trusted_scopes list. + approvedScopes = make(map[string]bool) + for _, scope := range securedDetails.TrustedScopes { + if ar.Scopes[scope] { + approvedScopes[scope] = true + } + } + if ar.Scopes[oidc.ScopeOpenID] { + approvedScopes[oidc.ScopeOpenID] = true + } + + // Ensure the signed-login scope was approved. + if !approvedScopes[konnect.ScopeSignedLoginOK] { + return nil, ar.NewBadRequest(oidc.ErrorCodeOAuth2InvalidRequest, "IdentifierIdentityManager: client does not authorize "+konnect.ScopeSignedLoginOK+" scope") + } + } + + auth.AuthorizeScopes(approvedScopes) + auth.AuthorizeClaims(ar.Claims) + return auth, nil +} + // EndSession implements the identity.Manager interface. func (im *IdentifierIdentityManager) EndSession(ctx context.Context, rw http.ResponseWriter, req *http.Request, esr *payload.EndSessionRequest) error { var err error diff --git a/vendor/github.com/libregraph/lico/oidc/provider/handlers.go b/vendor/github.com/libregraph/lico/oidc/provider/handlers.go index b65a30f741..d9d0c51686 100644 --- a/vendor/github.com/libregraph/lico/oidc/provider/handlers.go +++ b/vendor/github.com/libregraph/lico/oidc/provider/handlers.go @@ -90,6 +90,7 @@ func (p *Provider) JwksHandler(rw http.ResponseWriter, req *http.Request) { func (p *Provider) AuthorizeHandler(rw http.ResponseWriter, req *http.Request) { var err error var auth identity.AuthRecord + var nextManager identity.Manager addResponseHeaders(rw.Header()) @@ -173,7 +174,8 @@ func (p *Provider) AuthorizeHandler(rw http.ResponseWriter, req *http.Request) { // Authorization Server Authenticates End-User // http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthenticates - auth, err = p.identityManager.Authenticate(ctx, rw, req, ar, p.guestManager) + nextManager = p.guestManager + auth, err = p.identityManager.Authenticate(ctx, rw, req, ar, nextManager) if err != nil { goto done } diff --git a/vendor/github.com/libregraph/lico/scopes.go b/vendor/github.com/libregraph/lico/scopes.go index 6469ac5308..6934f7bc01 100644 --- a/vendor/github.com/libregraph/lico/scopes.go +++ b/vendor/github.com/libregraph/lico/scopes.go @@ -28,4 +28,7 @@ const ( // ScopeGuestOK is the string value for the built-in Guest OK scope. ScopeGuestOK = "LibreGraph.GuestOK" + + // ScopeSignedLoginOK is the string value for the built-in Signed Login OK scope. + ScopeSignedLoginOK = "LibreGraph.SignedLoginOK" ) diff --git a/vendor/modules.txt b/vendor/modules.txt index edc8e37799..54bf99e9f5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -682,9 +682,6 @@ github.com/goccy/go-yaml/token # github.com/gofrs/flock v0.13.0 ## explicit; go 1.24.0 github.com/gofrs/flock -# github.com/gofrs/uuid v4.4.0+incompatible -## explicit -github.com/gofrs/uuid # github.com/gogo/protobuf v1.3.2 ## explicit; go 1.15 github.com/gogo/protobuf/gogoproto @@ -969,8 +966,8 @@ 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.66.0 -## explicit; go 1.23.0 +# github.com/libregraph/lico v0.67.0 +## explicit; go 1.24.0 github.com/libregraph/lico github.com/libregraph/lico/bootstrap github.com/libregraph/lico/bootstrap/backends/guest