mirror of
https://github.com/jech/galene.git
synced 2024-12-22 15:25:48 +01:00
Attempt all keys when validating stateless tokens.
This commit is contained in:
parent
f3ceb05033
commit
3a6d924374
3 changed files with 19 additions and 17 deletions
2
CHANGES
2
CHANGES
|
@ -19,6 +19,8 @@ Galene 0.9 (unreleased)
|
|||
* Added a new command "/stopshare".
|
||||
* Added a new permission "message" and new commands "shutup" and "unshutup".
|
||||
* Fixed a bug that could allow an ordinary user to clear the chat.
|
||||
* Changed stateless token validation to attempt all keys rather than
|
||||
just the first matching one.
|
||||
|
||||
14 April 2024: Galene 0.8.2
|
||||
|
||||
|
|
7
README
7
README
|
@ -309,21 +309,18 @@ specify either an authorisation server or an authorisation portal.
|
|||
"kty": "oct",
|
||||
"alg": "HS256",
|
||||
"k": "MYz3IfCq4Yq-UmPdNqWEOdPl4C_m9imHHs9uveDUJGQ",
|
||||
"kid": "20211030"
|
||||
}, {
|
||||
"kty": "EC",
|
||||
"alg": "ES256",
|
||||
"crv": "P-256",
|
||||
"x": "dElK9qBNyCpRXdvJsn4GdjrFzScSzpkz_I0JhKbYC88",
|
||||
"y": "pBhVb37haKvwEoleoW3qxnT4y5bK35_RTP7_RmFKR6Q",
|
||||
"kid": "20211101"
|
||||
}]
|
||||
"authServer": "https://auth.example.org",
|
||||
}
|
||||
|
||||
The `kid` field serves to distinguish among multiple keys, and must match
|
||||
the value provided by the authorisation server. If the server doesn't
|
||||
provide a `kid`, the first key with a matching `alg` field will be used.
|
||||
If multiple keys are provided, then they will all be tried in turn (the
|
||||
kid field, if provided, is ignored).
|
||||
|
||||
If an authorisation server is specified, then the default client, after it
|
||||
prompts for a password, will request a token from the authorisation server
|
||||
|
|
27
token/jwt.go
27
token/jwt.go
|
@ -28,7 +28,7 @@ func parseBase64(k string, d map[string]interface{}) ([]byte, error) {
|
|||
return vv, nil
|
||||
}
|
||||
|
||||
func ParseKey(key map[string]interface{}) (interface{}, error) {
|
||||
func ParseKey(key map[string]any) (any, error) {
|
||||
kty, ok := key["kty"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("kty not found")
|
||||
|
@ -96,17 +96,16 @@ func ParseKey(key map[string]interface{}) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func getKey(header map[string]interface{}, keys []map[string]interface{}) (interface{}, error) {
|
||||
alg, _ := header["alg"].(string)
|
||||
kid, _ := header["kid"].(string)
|
||||
for _, k := range keys {
|
||||
kid2, _ := k["kid"].(string)
|
||||
alg2, _ := k["alg"].(string)
|
||||
if (kid == "" || kid == kid2) && alg == alg2 {
|
||||
return ParseKey(k)
|
||||
func ParseKeys(keys []map[string]any) ([]jwt.VerificationKey, error) {
|
||||
ks := make([]jwt.VerificationKey, len(keys))
|
||||
for i, ky := range keys {
|
||||
k, err := ParseKey(ky)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ks[i] = k
|
||||
}
|
||||
return nil, errors.New("key not found")
|
||||
return ks, nil
|
||||
}
|
||||
|
||||
func toStringArray(a interface{}) ([]string, bool) {
|
||||
|
@ -128,11 +127,15 @@ func toStringArray(a interface{}) ([]string, bool) {
|
|||
|
||||
// parseJWT tries to parse a string as a JWT.
|
||||
// It returns (nil, nil) if the string does not look like a JWT.
|
||||
func parseJWT(token string, keys []map[string]interface{}) (*JWT, error) {
|
||||
func parseJWT(token string, keys []map[string]any) (*JWT, error) {
|
||||
t, err := jwt.Parse(
|
||||
token,
|
||||
func(t *jwt.Token) (interface{}, error) {
|
||||
return getKey(t.Header, keys)
|
||||
ks, err := ParseKeys(keys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jwt.VerificationKeySet{Keys: ks}, nil
|
||||
},
|
||||
jwt.WithExpirationRequired(),
|
||||
jwt.WithIssuedAt(),
|
||||
|
|
Loading…
Reference in a new issue