Skip to content

Commit fb9e009

Browse files
committed
oidc: add Config.InsecureSkipSignatureCheck
Includes a big warning for why this is usually a bad idea. Fixes #350
1 parent 366ac4a commit fb9e009

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

oidc/verify.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,17 @@ type Config struct {
107107

108108
// Time function to check Token expiry. Defaults to time.Now
109109
Now func() time.Time
110+
111+
// InsecureSkipSignatureCheck causes this package to skip JWT signature validation.
112+
// It's intended for special cases where providers (such as Azure), use the "none"
113+
// algorithm.
114+
//
115+
// This option can only be enabled safely when the ID Token is received directly
116+
// from the provider after the token exchange.
117+
//
118+
// This option MUST NOT be used when receiving an ID Token from sources other
119+
// than the token endpoint.
120+
InsecureSkipSignatureCheck bool
110121
}
111122

112123
// Verifier returns an IDTokenVerifier that uses the provider's key set to verify JWTs.
@@ -196,11 +207,6 @@ func resolveDistributedClaim(ctx context.Context, verifier *IDTokenVerifier, src
196207
// token, err := verifier.Verify(ctx, rawIDToken)
197208
//
198209
func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDToken, error) {
199-
jws, err := jose.ParseSigned(rawIDToken)
200-
if err != nil {
201-
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
202-
}
203-
204210
// Throw out tokens with invalid claims before trying to verify the token. This lets
205211
// us do cheap checks before possibly re-syncing keys.
206212
payload, err := parseJWT(rawIDToken)
@@ -288,6 +294,15 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
288294
}
289295
}
290296

297+
if v.config.InsecureSkipSignatureCheck {
298+
return t, nil
299+
}
300+
301+
jws, err := jose.ParseSigned(rawIDToken)
302+
if err != nil {
303+
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
304+
}
305+
291306
switch len(jws.Signatures) {
292307
case 0:
293308
return nil, fmt.Errorf("oidc: id token not signed")

oidc/verify_test.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package oidc
33
import (
44
"context"
55
"crypto"
6+
"encoding/base64"
67
"errors"
78
"io"
89
"net/http"
@@ -122,6 +123,24 @@ func TestVerify(t *testing.T) {
122123
},
123124
signKey: newRSAKey(t),
124125
},
126+
{
127+
name: "unsigned token",
128+
idToken: `{"iss":"https://foo"}`,
129+
config: Config{
130+
SkipClientIDCheck: true,
131+
SkipExpiryCheck: true,
132+
},
133+
wantErr: true,
134+
},
135+
{
136+
name: "unsigned token InsecureSkipSignatureCheck",
137+
idToken: `{"iss":"https://foo"}`,
138+
config: Config{
139+
SkipClientIDCheck: true,
140+
SkipExpiryCheck: true,
141+
InsecureSkipSignatureCheck: true,
142+
},
143+
},
125144
}
126145
for _, test := range tests {
127146
t.Run(test.name, test.run)
@@ -537,7 +556,14 @@ type verificationTest struct {
537556
}
538557

539558
func (v verificationTest) runGetToken(t *testing.T) (*IDToken, error) {
540-
token := v.signKey.sign(t, []byte(v.idToken))
559+
var token string
560+
if v.signKey != nil {
561+
token = v.signKey.sign(t, []byte(v.idToken))
562+
} else {
563+
token = base64.RawURLEncoding.EncodeToString([]byte(`{alg: "none"}`))
564+
token += "."
565+
token += base64.RawURLEncoding.EncodeToString([]byte(v.idToken))
566+
}
541567

542568
ctx, cancel := context.WithCancel(context.Background())
543569
defer cancel()
@@ -547,10 +573,10 @@ func (v verificationTest) runGetToken(t *testing.T) (*IDToken, error) {
547573
issuer = v.issuer
548574
}
549575
var ks KeySet
550-
if v.verificationKey == nil {
551-
ks = &StaticKeySet{PublicKeys: []crypto.PublicKey{v.signKey.pub}}
552-
} else {
576+
if v.verificationKey != nil {
553577
ks = &StaticKeySet{PublicKeys: []crypto.PublicKey{v.verificationKey.pub}}
578+
} else if v.signKey != nil {
579+
ks = &StaticKeySet{PublicKeys: []crypto.PublicKey{v.signKey.pub}}
554580
}
555581
verifier := NewVerifier(issuer, ks, &v.config)
556582

0 commit comments

Comments
 (0)