Skip to content

Commit 752fcad

Browse files
committed
oidc: verify signature before parsing token
This change updates the verification logic of this library to always verify the signature of the token before validating the payload. See associated issue. #464
1 parent b7e896c commit 752fcad

File tree

2 files changed

+22
-36
lines changed

2 files changed

+22
-36
lines changed

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
go: ['1.22', '1.23']
15+
go: ['1.23', '1.24']
1616
name: Linux Go ${{ matrix.go }}
1717
steps:
1818
- uses: actions/checkout@v4

verify.go

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package oidc
22

33
import (
4-
"bytes"
54
"context"
65
"encoding/base64"
76
"encoding/json"
8-
"errors"
97
"fmt"
108
"io/ioutil"
119
"net/http"
@@ -211,12 +209,29 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
211209
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
212210
}
213211

214-
// Throw out tokens with invalid claims before trying to verify the token. This lets
215-
// us do cheap checks before possibly re-syncing keys.
216-
payload, err := parseJWT(rawIDToken)
212+
switch len(jws.Signatures) {
213+
case 0:
214+
return nil, fmt.Errorf("oidc: id token not signed")
215+
case 1:
216+
default:
217+
return nil, fmt.Errorf("oidc: multiple signatures on id token not supported")
218+
}
219+
220+
sig := jws.Signatures[0]
221+
supportedSigAlgs := v.config.SupportedSigningAlgs
222+
if len(supportedSigAlgs) == 0 {
223+
supportedSigAlgs = []string{RS256}
224+
}
225+
226+
if !contains(supportedSigAlgs, sig.Header.Algorithm) {
227+
return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", supportedSigAlgs, sig.Header.Algorithm)
228+
}
229+
230+
payload, err := v.keySet.VerifySignature(ctx, rawIDToken)
217231
if err != nil {
218-
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
232+
return nil, fmt.Errorf("failed to verify signature: %v", err)
219233
}
234+
220235
var token idToken
221236
if err := json.Unmarshal(payload, &token); err != nil {
222237
return nil, fmt.Errorf("oidc: failed to unmarshal claims: %v", err)
@@ -296,36 +311,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
296311
}
297312
}
298313

299-
switch len(jws.Signatures) {
300-
case 0:
301-
return nil, fmt.Errorf("oidc: id token not signed")
302-
case 1:
303-
default:
304-
return nil, fmt.Errorf("oidc: multiple signatures on id token not supported")
305-
}
306-
307-
sig := jws.Signatures[0]
308-
supportedSigAlgs := v.config.SupportedSigningAlgs
309-
if len(supportedSigAlgs) == 0 {
310-
supportedSigAlgs = []string{RS256}
311-
}
312-
313-
if !contains(supportedSigAlgs, sig.Header.Algorithm) {
314-
return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", supportedSigAlgs, sig.Header.Algorithm)
315-
}
316-
317314
t.sigAlgorithm = sig.Header.Algorithm
318-
319-
gotPayload, err := v.keySet.VerifySignature(ctx, rawIDToken)
320-
if err != nil {
321-
return nil, fmt.Errorf("failed to verify signature: %v", err)
322-
}
323-
324-
// Ensure that the payload returned by the square actually matches the payload parsed earlier.
325-
if !bytes.Equal(gotPayload, payload) {
326-
return nil, errors.New("oidc: internal error, payload parsed did not match previous payload")
327-
}
328-
329315
return t, nil
330316
}
331317

0 commit comments

Comments
 (0)