@@ -2,6 +2,9 @@ package oidc
6 "path/filepath"
9 "path/filepath"
@@ -195,6 +198,21 @@ var _ = Describe("ProviderVerifier", func() {
195 Expect(idToken.Subject).To(Equal(claims.Subject))
198 Expect(idToken.Subject).To(Equal(claims.Subject))
197 Entry("with the default opts and claims", &verifierTableInput{}),
200 Entry("with the default opts and claims", &verifierTableInput{}),
201+ Entry("with skip discovery and an allowed signing algorithm", &verifierTableInput{
202+ modifyOpts: func(p *ProviderVerifierOptions) {
203+ p.SkipDiscovery = true
204+ p.JWKsURL = m.JWKSEndpoint()
205+ p.SupportedSigningAlgs = []string{"RS256"}
208+ Entry("with skip discovery and a disallowed signing algorithm", &verifierTableInput{
209+ modifyOpts: func(p *ProviderVerifierOptions) {
210+ p.SkipDiscovery = true
211+ p.JWKsURL = m.JWKSEndpoint()
212+ p.SupportedSigningAlgs = []string{"HS256"}
214+ expectedError: "failed to verify token: oidc: malformed jwt: unexpected signature algorithm \"RS256\"; expected [\"HS256\"]",
198 Entry("when the audience is mismatched", &verifierTableInput{
216 Entry("when the audience is mismatched", &verifierTableInput{
199 modifyClaims: func(j *jwt.RegisteredClaims) {
217 modifyClaims: func(j *jwt.RegisteredClaims) {
200 j.Audience = jwt.ClaimStrings{"OtherClient"}
218 j.Audience = jwt.ClaimStrings{"OtherClient"}
@@ -230,4 +248,78 @@ var _ = Describe("ProviderVerifier", func() {
230 expectedError: "failed to verify token: oidc: token is expired",
248 expectedError: "failed to verify token: oidc: token is expired",
252+ Describe("intersectSigningAlgs", func() {
253+ DescribeTable("when determining allowed signing algorithms", func(discoveredSigningAlgs, configuredSigningAlgs, expected []string, expectedError string) {
254+ actual, err := intersectSigningAlgs(discoveredSigningAlgs, configuredSigningAlgs)
255+ Expect(actual).To(Equal(expected))
256+ if len(expectedError) > 0 {
257+ Expect(err).To(HaveOccurred())
258+ Expect(err.Error()).To(Equal(expectedError))
261+ Entry("returns discovered values when no configured values are provided", []string{"RS256", "HS256"}, []string(nil), []string{"RS256", "HS256"}, ""),
262+ Entry("returns configured values when no discovered values are provided", []string(nil), []string{"RS256"}, []string{"RS256"}, ""),
263+ Entry("returns the configured order of the intersection", []string{"RS256", "HS256", "EdDSA"}, []string{"EdDSA", "RS256"}, []string{"EdDSA", "RS256"}, ""),
264+ Entry("returns an error when there is no intersection", []string{"RS256", "HS256"}, []string{"EdDSA"}, nil, "no supported signing algorithms in common between provider and configuration: discovered=[RS256 HS256], configured=[EdDSA]"),
268+ It("uses the intersection between discovered and configured signing algorithms", func() {
269+ customServer, err := mockoidc.NewServer(nil)
270+ Expect(err).ToNot(HaveOccurred())
271+ customServer.AddMiddleware(newConfiguredSigningAlgsIssuerMiddleware(customServer, []string{"RS256", "HS256"}))
273+ listener, err := net.Listen("tcp", "127.0.0.1:0")
274+ Expect(err).ToNot(HaveOccurred())
276+ Expect(customServer.Start(listener, nil)).To(Succeed())
278+ Expect(customServer.Shutdown()).To(Succeed())
281+ pv, err := NewProviderVerifier(context.Background(), ProviderVerifierOptions{
282+ AudienceClaims: []string{"aud"},
283+ ClientID: customServer.Config().ClientID,
284+ ExtraAudiences: []string{},
285+ IssuerURL: customServer.Issuer(),
286+ SupportedSigningAlgs: []string{"HS256"},
288+ Expect(err).ToNot(HaveOccurred())
290+ rawIDToken, err := customServer.Keypair.SignJWT(jwt.RegisteredClaims{
291+ Audience: jwt.ClaimStrings{customServer.Config().ClientID},
292+ Issuer: customServer.Issuer(),
293+ ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
294+ IssuedAt: jwt.NewNumericDate(time.Now()),
297+ Expect(err).ToNot(HaveOccurred())
299+ _, err = pv.Verifier().Verify(context.Background(), rawIDToken)
300+ Expect(err).To(MatchError(HavePrefix("failed to verify token: oidc: malformed jwt: unexpected signature algorithm \"RS256\"; expected [\"HS256\"]")))
304+func newConfiguredSigningAlgsIssuerMiddleware(m *mockoidc.MockOIDC, supportedSigningAlgs []string) func(http.Handler) http.Handler {
305+ return func(next http.Handler) http.Handler {
306+ return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
307+ provider := providerJSON{
309+ AuthURL: m.AuthorizationEndpoint(),
310+ TokenURL: m.TokenEndpoint(),
311+ JWKsURL: m.JWKSEndpoint(),
312+ UserInfoURL: m.UserinfoEndpoint(),
313+ SupportedSigningAlgs: supportedSigningAlgs,
316+ data, err := json.Marshal(provider)
318+ rw.WriteHeader(http.StatusInternalServerError)
322+ _, _ = rw.Write(data)