Merge branch 'main' into feat/issue#574

This commit is contained in:
Kotaro Otaka 2024-04-15 23:04:43 +09:00 committed by GitHub
commit 9e700d2f38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 146 additions and 106 deletions

View file

@ -10,7 +10,7 @@ import (
"strings"
"time"
jose "github.com/go-jose/go-jose/v3"
"github.com/go-jose/go-jose/v4"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v3/pkg/crypto"
httphelper "github.com/zitadel/oidc/v3/pkg/http"
@ -97,7 +97,12 @@ func CallEndSessionEndpoint(ctx context.Context, request any, authFn any, caller
ctx, span := Tracer.Start(ctx, "CallEndSessionEndpoint")
defer span.End()
req, err := httphelper.FormRequest(ctx, caller.GetEndSessionEndpoint(), request, Encoder, authFn)
endpoint := caller.GetEndSessionEndpoint()
if endpoint == "" {
return nil, fmt.Errorf("end session %w", ErrEndpointNotSet)
}
req, err := httphelper.FormRequest(ctx, endpoint, request, Encoder, authFn)
if err != nil {
return nil, err
}
@ -143,7 +148,12 @@ func CallRevokeEndpoint(ctx context.Context, request any, authFn any, caller Rev
ctx, span := Tracer.Start(ctx, "CallRevokeEndpoint")
defer span.End()
req, err := httphelper.FormRequest(ctx, caller.GetRevokeEndpoint(), request, Encoder, authFn)
endpoint := caller.GetRevokeEndpoint()
if endpoint == "" {
return fmt.Errorf("revoke %w", ErrEndpointNotSet)
}
req, err := httphelper.FormRequest(ctx, endpoint, request, Encoder, authFn)
if err != nil {
return err
}
@ -218,7 +228,12 @@ func CallDeviceAuthorizationEndpoint(ctx context.Context, request *oidc.ClientCr
ctx, span := Tracer.Start(ctx, "CallDeviceAuthorizationEndpoint")
defer span.End()
req, err := httphelper.FormRequest(ctx, caller.GetDeviceAuthorizationEndpoint(), request, Encoder, authFn)
endpoint := caller.GetDeviceAuthorizationEndpoint()
if endpoint == "" {
return nil, fmt.Errorf("device authorization %w", ErrEndpointNotSet)
}
req, err := httphelper.FormRequest(ctx, endpoint, request, Encoder, authFn)
if err != nil {
return nil, err
}

5
pkg/client/errors.go Normal file
View file

@ -0,0 +1,5 @@
package client
import "errors"
var ErrEndpointNotSet = errors.New("endpoint not set")

View file

@ -5,7 +5,7 @@ import (
"net/http"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"golang.org/x/oauth2"
"github.com/zitadel/oidc/v3/pkg/client"

View file

@ -7,7 +7,7 @@ import (
"net/http"
"sync"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/zitadel/oidc/v3/pkg/client"
httphelper "github.com/zitadel/oidc/v3/pkg/http"

View file

@ -9,7 +9,7 @@ import (
"net/url"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/go-jose/go-jose/v4"
"github.com/google/uuid"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"

View file

@ -4,7 +4,7 @@ import (
"context"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/zitadel/oidc/v3/pkg/client"
"github.com/zitadel/oidc/v3/pkg/oidc"

View file

@ -5,7 +5,7 @@ import (
"testing"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
tu "github.com/zitadel/oidc/v3/internal/testutil"

View file

@ -6,7 +6,7 @@ import (
"net/http"
"time"
"github.com/go-jose/go-jose/v3"
"github.com/go-jose/go-jose/v4"
"github.com/zitadel/oidc/v3/pkg/client"
httphelper "github.com/zitadel/oidc/v3/pkg/http"
"github.com/zitadel/oidc/v3/pkg/oidc"

View file

@ -8,7 +8,7 @@ import (
"fmt"
"hash"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
)
var ErrUnsupportedAlgorithm = errors.New("unsupported signing algorithm")

View file

@ -4,7 +4,7 @@ import (
"encoding/json"
"errors"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
)
func Sign(object any, signer jose.Signer) (string, error) {

View file

@ -1,5 +1,7 @@
package oidc
import "encoding/json"
// DeviceAuthorizationRequest implements
// https://www.rfc-editor.org/rfc/rfc8628#section-3.1,
// 3.1 Device Authorization Request.
@ -20,6 +22,26 @@ type DeviceAuthorizationResponse struct {
Interval int `json:"interval,omitempty"`
}
func (resp *DeviceAuthorizationResponse) UnmarshalJSON(data []byte) error {
type Alias DeviceAuthorizationResponse
aux := &struct {
// workaround misspelling of verification_uri
// https://stackoverflow.com/q/76696956/5690223
// https://developers.google.com/identity/protocols/oauth2/limited-input-device?hl=fr#success-response
VerificationURL string `json:"verification_url"`
*Alias
}{
Alias: (*Alias)(resp),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
if resp.VerificationURI == "" {
resp.VerificationURI = aux.VerificationURL
}
return nil
}
// DeviceAccessTokenRequest implements
// https://www.rfc-editor.org/rfc/rfc8628#section-3.4,
// Device Access Token Request.

View file

@ -0,0 +1,30 @@
package oidc
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDeviceAuthorizationResponse_UnmarshalJSON(t *testing.T) {
jsonStr := `{
"device_code": "deviceCode",
"user_code": "userCode",
"verification_url": "http://example.com/verify",
"expires_in": 3600,
"interval": 5
}`
expected := &DeviceAuthorizationResponse{
DeviceCode: "deviceCode",
UserCode: "userCode",
VerificationURI: "http://example.com/verify",
ExpiresIn: 3600,
Interval: 5,
}
var resp DeviceAuthorizationResponse
err := resp.UnmarshalJSON([]byte(jsonStr))
assert.NoError(t, err)
assert.Equal(t, expected, &resp)
}

View file

@ -7,7 +7,7 @@ import (
"crypto/rsa"
"errors"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
)
const (

View file

@ -7,7 +7,7 @@ import (
"reflect"
"testing"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
)
func TestFindKey(t *testing.T) {

View file

@ -5,7 +5,7 @@ import (
"os"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"golang.org/x/oauth2"
"github.com/muhlemmer/gu"

View file

@ -6,7 +6,7 @@ import (
"slices"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
)
const (

View file

@ -4,7 +4,7 @@ import (
"testing"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/stretchr/testify/assert"
"golang.org/x/text/language"
)

View file

@ -9,7 +9,7 @@ import (
"strings"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/muhlemmer/gu"
"github.com/zitadel/schema"
"golang.org/x/text/language"

View file

@ -10,7 +10,7 @@ import (
"strings"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
str "github.com/zitadel/oidc/v3/pkg/strings"
)
@ -148,8 +148,13 @@ func CheckAuthorizedParty(claims Claims, clientID string) error {
}
func CheckSignature(ctx context.Context, token string, payload []byte, claims ClaimsSignature, supportedSigAlgs []string, set KeySet) error {
jws, err := jose.ParseSigned(token)
jws, err := jose.ParseSigned(token, toJoseSignatureAlgorithms(supportedSigAlgs))
if err != nil {
if strings.HasPrefix(err.Error(), "go-jose/go-jose: unexpected signature algorithm") {
// TODO(v4): we should wrap errors instead of returning static ones.
// This is a workaround so we keep returning the same error for now.
return ErrSignatureUnsupportedAlg
}
return ErrParse
}
if len(jws.Signatures) == 0 {
@ -159,12 +164,6 @@ func CheckSignature(ctx context.Context, token string, payload []byte, claims Cl
return ErrSignatureMultiple
}
sig := jws.Signatures[0]
if len(supportedSigAlgs) == 0 {
supportedSigAlgs = []string{"RS256"}
}
if !str.Contains(supportedSigAlgs, sig.Header.Algorithm) {
return fmt.Errorf("%w: id token signed with unsupported algorithm, expected %q got %q", ErrSignatureUnsupportedAlg, supportedSigAlgs, sig.Header.Algorithm)
}
signedPayload, err := set.VerifySignature(ctx, jws)
if err != nil {
@ -180,6 +179,18 @@ func CheckSignature(ctx context.Context, token string, payload []byte, claims Cl
return nil
}
// TODO(v4): Use the new jose.SignatureAlgorithm type directly, instead of string.
func toJoseSignatureAlgorithms(algorithms []string) []jose.SignatureAlgorithm {
out := make([]jose.SignatureAlgorithm, len(algorithms))
for i := range algorithms {
out[i] = jose.SignatureAlgorithm(algorithms[i])
}
if len(out) == 0 {
out = append(out, jose.RS256)
}
return out
}
func CheckExpiration(claims Claims, offset time.Duration) error {
expiration := claims.GetExpiration()
if !time.Now().Add(offset).Before(expiration) {

View file

@ -4,7 +4,7 @@ import (
"context"
"net/http"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
httphelper "github.com/zitadel/oidc/v3/pkg/http"
"github.com/zitadel/oidc/v3/pkg/oidc"

View file

@ -6,7 +6,7 @@ import (
"net/http/httptest"
"testing"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

View file

@ -4,7 +4,7 @@ import (
"context"
"net/http"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
httphelper "github.com/zitadel/oidc/v3/pkg/http"
)

View file

@ -7,7 +7,7 @@ import (
"net/http/httptest"
"testing"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"

View file

@ -4,7 +4,7 @@ import (
"context"
"testing"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/golang/mock/gomock"
"github.com/zitadel/schema"

View file

@ -8,7 +8,7 @@ import (
context "context"
reflect "reflect"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
gomock "github.com/golang/mock/gomock"
)

View file

@ -7,7 +7,7 @@ package mock
import (
reflect "reflect"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
gomock "github.com/golang/mock/gomock"
)

View file

@ -9,7 +9,7 @@ import (
reflect "reflect"
time "time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
gomock "github.com/golang/mock/gomock"
oidc "github.com/zitadel/oidc/v3/pkg/oidc"
op "github.com/zitadel/oidc/v3/pkg/op"

View file

@ -8,7 +8,7 @@ import (
"time"
"github.com/go-chi/chi/v5"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/rs/cors"
"github.com/zitadel/schema"
"go.opentelemetry.io/otel"

View file

@ -3,7 +3,7 @@ package op
import (
"errors"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
)
var ErrSignerCreationFailed = errors.New("signer creation failed")

View file

@ -5,7 +5,7 @@ import (
"errors"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/zitadel/oidc/v3/pkg/oidc"
)

View file

@ -6,7 +6,7 @@ import (
"fmt"
"time"
jose "github.com/go-jose/go-jose/v3"
jose "github.com/go-jose/go-jose/v4"
"github.com/zitadel/oidc/v3/pkg/oidc"
)