mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-07-13 00:52:01 -04:00
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] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
eee040d066
commit
85be8e726b
3
go.mod
3
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
|
||||
|
||||
7
go.sum
7
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=
|
||||
|
||||
15
vendor/github.com/gofrs/uuid/.gitignore
generated
vendored
15
vendor/github.com/gofrs/uuid/.gitignore
generated
vendored
@@ -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
|
||||
20
vendor/github.com/gofrs/uuid/LICENSE
generated
vendored
20
vendor/github.com/gofrs/uuid/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
|
||||
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.
|
||||
117
vendor/github.com/gofrs/uuid/README.md
generated
vendored
117
vendor/github.com/gofrs/uuid/README.md
generated
vendored
@@ -1,117 +0,0 @@
|
||||
# UUID
|
||||
|
||||
[](https://github.com/gofrs/uuid/blob/master/LICENSE)
|
||||
[](https://travis-ci.org/gofrs/uuid)
|
||||
[](http://godoc.org/github.com/gofrs/uuid)
|
||||
[](https://codecov.io/gh/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#)
|
||||
234
vendor/github.com/gofrs/uuid/codec.go
generated
vendored
234
vendor/github.com/gofrs/uuid/codec.go
generated
vendored
@@ -1,234 +0,0 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// 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
|
||||
}
|
||||
48
vendor/github.com/gofrs/uuid/fuzz.go
generated
vendored
48
vendor/github.com/gofrs/uuid/fuzz.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2018 Andrei Tudor Călin <mail@acln.ro>
|
||||
//
|
||||
// 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
|
||||
}
|
||||
456
vendor/github.com/gofrs/uuid/generator.go
generated
vendored
456
vendor/github.com/gofrs/uuid/generator.go
generated
vendored
@@ -1,456 +0,0 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// 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")
|
||||
}
|
||||
116
vendor/github.com/gofrs/uuid/sql.go
generated
vendored
116
vendor/github.com/gofrs/uuid/sql.go
generated
vendored
@@ -1,116 +0,0 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// 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
|
||||
}
|
||||
285
vendor/github.com/gofrs/uuid/uuid.go
generated
vendored
285
vendor/github.com/gofrs/uuid/uuid.go
generated
vendored
@@ -1,285 +0,0 @@
|
||||
// Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
|
||||
//
|
||||
// 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
|
||||
}
|
||||
26
vendor/github.com/libregraph/lico/CHANGELOG.md
generated
vendored
26
vendor/github.com/libregraph/lico/CHANGELOG.md
generated
vendored
@@ -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
|
||||
|
||||
10
vendor/github.com/libregraph/lico/README.md
generated
vendored
10
vendor/github.com/libregraph/lico/README.md
generated
vendored
@@ -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
|
||||
|
||||
8
vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go
generated
vendored
8
vendor/github.com/libregraph/lico/bootstrap/backends/ldap/ldap.go
generated
vendored
@@ -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)
|
||||
|
||||
8
vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go
generated
vendored
8
vendor/github.com/libregraph/lico/bootstrap/backends/libregraph/libregraph.go
generated
vendored
@@ -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)
|
||||
|
||||
8
vendor/github.com/libregraph/lico/bootstrap/bootstrap.go
generated
vendored
8
vendor/github.com/libregraph/lico/bootstrap/bootstrap.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
1
vendor/github.com/libregraph/lico/bootstrap/config.go
generated
vendored
1
vendor/github.com/libregraph/lico/bootstrap/config.go
generated
vendored
@@ -50,6 +50,7 @@ type Config struct {
|
||||
IdentifierAuthoritiesConf string
|
||||
IdentifierScopesConf string
|
||||
IdentifierDefaultBannerLogo []byte
|
||||
IdentifierDefaultBannerLogoHeight *string
|
||||
IdentifierDefaultSignInPageText *string
|
||||
IdentifierDefaultLogoTargetURI *string
|
||||
IdentifierDefaultUsernameHintText *string
|
||||
|
||||
2
vendor/github.com/libregraph/lico/bootstrap/settings.go
generated
vendored
2
vendor/github.com/libregraph/lico/bootstrap/settings.go
generated
vendored
@@ -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
|
||||
|
||||
1
vendor/github.com/libregraph/lico/config/config.go
generated
vendored
1
vendor/github.com/libregraph/lico/config/config.go
generated
vendored
@@ -38,5 +38,6 @@ type Config struct {
|
||||
|
||||
AllowedScopes []string
|
||||
AllowClientGuests bool
|
||||
AllowClientSignedLogins bool
|
||||
AllowDynamicClientRegistration bool
|
||||
}
|
||||
|
||||
14
vendor/github.com/libregraph/lico/identifier-registration.yaml.in
generated
vendored
14
vendor/github.com/libregraph/lico/identifier-registration.yaml.in
generated
vendored
@@ -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
|
||||
|
||||
1
vendor/github.com/libregraph/lico/identifier/api.go
generated
vendored
1
vendor/github.com/libregraph/lico/identifier/api.go
generated
vendored
@@ -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,
|
||||
|
||||
2
vendor/github.com/libregraph/lico/identifier/backends/ldap/ldap.go
generated
vendored
2
vendor/github.com/libregraph/lico/identifier/backends/ldap/ldap.go
generated
vendored
@@ -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"
|
||||
|
||||
1
vendor/github.com/libregraph/lico/identifier/config.go
generated
vendored
1
vendor/github.com/libregraph/lico/identifier/config.go
generated
vendored
@@ -47,6 +47,7 @@ type Config struct {
|
||||
SignedOutEndpointURI *url.URL
|
||||
|
||||
DefaultBannerLogo []byte
|
||||
DefaultBannerLogoHeight *string
|
||||
DefaultSignInPageText *string
|
||||
DefaultSignInPageLogoURI *string
|
||||
DefaultUsernameHintText *string
|
||||
|
||||
31
vendor/github.com/libregraph/lico/identifier/identifier.go
generated
vendored
31
vendor/github.com/libregraph/lico/identifier/identifier.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
1
vendor/github.com/libregraph/lico/identifier/meta/branding.go
generated
vendored
1
vendor/github.com/libregraph/lico/identifier/meta/branding.go
generated
vendored
@@ -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"`
|
||||
|
||||
2
vendor/github.com/libregraph/lico/identifier/models.go
generated
vendored
2
vendor/github.com/libregraph/lico/identifier/models.go
generated
vendored
@@ -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 != "" {
|
||||
|
||||
6
vendor/github.com/libregraph/lico/identifier/user.go
generated
vendored
6
vendor/github.com/libregraph/lico/identifier/user.go
generated
vendored
@@ -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
|
||||
|
||||
62
vendor/github.com/libregraph/lico/identity/clients/models.go
generated
vendored
62
vendor/github.com/libregraph/lico/identity/clients/models.go
generated
vendored
@@ -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 {
|
||||
|
||||
15
vendor/github.com/libregraph/lico/identity/clients/registry.go
generated
vendored
15
vendor/github.com/libregraph/lico/identity/clients/registry.go
generated
vendored
@@ -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 {
|
||||
|
||||
3
vendor/github.com/libregraph/lico/identity/config.go
generated
vendored
3
vendor/github.com/libregraph/lico/identity/config.go
generated
vendored
@@ -30,5 +30,8 @@ type Config struct {
|
||||
|
||||
ScopesSupported []string
|
||||
|
||||
// AllowSignedLogin enables the signed JWT auto sign-in flow.
|
||||
AllowSignedLogin bool
|
||||
|
||||
Logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
199
vendor/github.com/libregraph/lico/identity/managers/identifier.go
generated
vendored
199
vendor/github.com/libregraph/lico/identity/managers/identifier.go
generated
vendored
@@ -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
|
||||
|
||||
4
vendor/github.com/libregraph/lico/oidc/provider/handlers.go
generated
vendored
4
vendor/github.com/libregraph/lico/oidc/provider/handlers.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
3
vendor/github.com/libregraph/lico/scopes.go
generated
vendored
3
vendor/github.com/libregraph/lico/scopes.go
generated
vendored
@@ -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"
|
||||
)
|
||||
|
||||
7
vendor/modules.txt
vendored
7
vendor/modules.txt
vendored
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user