fix: rp verification process (#95)

* fix: rp verification process

* types

* comments

* fix cli client
This commit is contained in:
Livio Amstutz 2021-06-23 11:08:54 +02:00 committed by GitHub
parent 400f5c4de4
commit 850faa159d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 175 additions and 55 deletions

View file

@ -2,10 +2,17 @@ package oidc
import (
"context"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"gopkg.in/square/go-jose.v2"
)
const (
KeyUseSignature = "sig"
)
//KeySet represents a set of JSON Web Keys
// - remotely fetch via discovery and jwks_uri -> `remoteKeySet`
// - held by the OP itself in storage -> `openIDKeySet`
@ -15,16 +22,51 @@ type KeySet interface {
VerifySignature(ctx context.Context, jws *jose.JSONWebSignature) (payload []byte, err error)
}
//CheckKey searches the given JSON Web Keys for the requested key ID
//and verifies the JSON Web Signature with the found key
//GetKeyIDAndAlg returns the `kid` and `alg` claim from the JWS header
func GetKeyIDAndAlg(jws *jose.JSONWebSignature) (string, string) {
keyID := ""
alg := ""
for _, sig := range jws.Signatures {
keyID = sig.Header.KeyID
alg = sig.Header.Algorithm
break
}
return keyID, alg
}
//FindKey searches the given JSON Web Keys for the requested key ID, usage and key type
//
//will return false but no error if key ID is not found
func CheckKey(keyID string, jws *jose.JSONWebSignature, keys ...jose.JSONWebKey) ([]byte, error, bool) {
//will return the key immediately if matches exact (id, usage, type)
//
//will return false none or multiple match
func FindKey(keyID, use, expectedAlg string, keys ...jose.JSONWebKey) (jose.JSONWebKey, bool) {
var validKeys []jose.JSONWebKey
for _, key := range keys {
if keyID == "" || key.KeyID == keyID {
payload, err := jws.Verify(&key)
return payload, err, true
if key.KeyID == keyID && key.Use == use && algToKeyType(key.Key, expectedAlg) {
if keyID != "" {
return key, true
}
validKeys = append(validKeys, key)
}
}
return nil, nil, false
if len(validKeys) == 1 {
return validKeys[0], true
}
return jose.JSONWebKey{}, false
}
func algToKeyType(key interface{}, alg string) bool {
switch alg[0] {
case 'R', 'P':
_, ok := key.(*rsa.PublicKey)
return ok
case 'E':
_, ok := key.(*ecdsa.PublicKey)
return ok
case 'O':
_, ok := key.(*ed25519.PublicKey)
return ok
default:
return false
}
}