From 0ab5ea5a57fafd6cf0e1b5d0154bdd29771af7f8 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 27 Sep 2021 11:58:28 +0200 Subject: [PATCH] refactor: remove utils pkg BREAKING CHANGE: utils package has been removed in favor of specific new packages (http, crypto, strings) --- example/client/app/app.go | 4 ++-- example/client/github/github.go | 4 ++-- pkg/client/client.go | 15 ++++++++------- pkg/client/jwt_profile.go | 4 ++-- pkg/{utils => client/rp/cli}/browser.go | 2 +- pkg/client/rp/cli/cli.go | 6 +++--- pkg/client/rp/delegation.go | 4 ++-- pkg/client/rp/jwks.go | 4 ++-- pkg/client/rp/relaying_party.go | 20 ++++++++++---------- pkg/client/rs/resource_server.go | 10 +++++----- pkg/{utils => crypto}/crypto.go | 2 +- pkg/{utils => crypto}/hash.go | 2 +- pkg/{utils => crypto}/key.go | 2 +- pkg/{utils => crypto}/sign.go | 2 +- pkg/{utils => http}/cookie.go | 2 +- pkg/{utils => http}/http.go | 4 ++-- pkg/{utils => http}/marshal.go | 2 +- pkg/{utils => http}/marshal_test.go | 2 +- pkg/oidc/code_challenge.go | 4 ++-- pkg/oidc/token.go | 13 +++++++------ pkg/oidc/verifier.go | 10 +++++----- pkg/op/auth_request.go | 17 +++++++++-------- pkg/op/auth_request_test.go | 8 ++++---- pkg/op/crypto.go | 6 +++--- pkg/op/discovery.go | 4 ++-- pkg/op/error.go | 8 ++++---- pkg/op/keys.go | 6 +++--- pkg/op/mock/authorizer.mock.go | 8 ++++---- pkg/op/op.go | 10 +++++----- pkg/op/probes.go | 4 ++-- pkg/op/session.go | 6 +++--- pkg/op/token.go | 9 +++++---- pkg/op/token_code.go | 6 +++--- pkg/op/token_intospection.go | 10 +++++----- pkg/op/token_jwt_profile.go | 8 ++++---- pkg/op/token_refresh.go | 9 +++++---- pkg/op/token_request.go | 6 +++--- pkg/op/userinfo.go | 10 +++++----- pkg/{utils => strings}/strings.go | 2 +- pkg/{utils => strings}/strings_test.go | 2 +- 40 files changed, 131 insertions(+), 126 deletions(-) rename pkg/{utils => client/rp/cli}/browser.go (96%) rename pkg/{utils => crypto}/crypto.go (99%) rename pkg/{utils => crypto}/hash.go (98%) rename pkg/{utils => crypto}/key.go (94%) rename pkg/{utils => crypto}/sign.go (97%) rename pkg/{utils => http}/cookie.go (99%) rename pkg/{utils => http}/http.go (97%) rename pkg/{utils => http}/marshal.go (98%) rename pkg/{utils => http}/marshal_test.go (98%) rename pkg/{utils => strings}/strings.go (89%) rename pkg/{utils => strings}/strings_test.go (98%) diff --git a/example/client/app/app.go b/example/client/app/app.go index d835959..90bb1cb 100644 --- a/example/client/app/app.go +++ b/example/client/app/app.go @@ -12,8 +12,8 @@ import ( "github.com/sirupsen/logrus" "github.com/caos/oidc/pkg/client/rp" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) var ( @@ -30,7 +30,7 @@ func main() { scopes := strings.Split(os.Getenv("SCOPES"), " ") redirectURI := fmt.Sprintf("http://localhost:%v%v", port, callbackPath) - cookieHandler := utils.NewCookieHandler(key, key, utils.WithUnsecure()) + cookieHandler := httphelper.NewCookieHandler(key, key, httphelper.WithUnsecure()) options := []rp.Option{ rp.WithCookieHandler(cookieHandler), diff --git a/example/client/github/github.go b/example/client/github/github.go index 35c7723..d9be995 100644 --- a/example/client/github/github.go +++ b/example/client/github/github.go @@ -12,7 +12,7 @@ import ( "github.com/caos/oidc/pkg/client/rp" "github.com/caos/oidc/pkg/client/rp/cli" - "github.com/caos/oidc/pkg/utils" + "github.com/caos/oidc/pkg/http" ) var ( @@ -34,7 +34,7 @@ func main() { } ctx := context.Background() - cookieHandler := utils.NewCookieHandler(key, key, utils.WithUnsecure()) + cookieHandler := http.NewCookieHandler(key, key, http.WithUnsecure()) relyingParty, err := rp.NewRelyingPartyOAuth(rpConfig, rp.WithCookieHandler(cookieHandler)) if err != nil { fmt.Printf("error creating relaying party: %v", err) diff --git a/pkg/client/client.go b/pkg/client/client.go index fa64b70..1828d1d 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -10,12 +10,13 @@ import ( "golang.org/x/oauth2" "gopkg.in/square/go-jose.v2" + "github.com/caos/oidc/pkg/crypto" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) var ( - Encoder = func() utils.Encoder { + Encoder = func() httphelper.Encoder { e := schema.NewEncoder() e.RegisterEncoder(oidc.SpaceDelimitedArray{}, func(value reflect.Value) string { return value.Interface().(oidc.SpaceDelimitedArray).Encode() @@ -32,7 +33,7 @@ func Discover(issuer string, httpClient *http.Client) (*oidc.DiscoveryConfigurat return nil, err } discoveryConfig := new(oidc.DiscoveryConfiguration) - err = utils.HttpRequest(httpClient, req, &discoveryConfig) + err = httphelper.HttpRequest(httpClient, req, &discoveryConfig) if err != nil { return nil, err } @@ -52,12 +53,12 @@ func CallTokenEndpoint(request interface{}, caller tokenEndpointCaller) (newToke } func callTokenEndpoint(request interface{}, authFn interface{}, caller tokenEndpointCaller) (newToken *oauth2.Token, err error) { - req, err := utils.FormRequest(caller.TokenEndpoint(), request, Encoder, authFn) + req, err := httphelper.FormRequest(caller.TokenEndpoint(), request, Encoder, authFn) if err != nil { return nil, err } tokenRes := new(oidc.AccessTokenResponse) - if err := utils.HttpRequest(caller.HttpClient(), req, &tokenRes); err != nil { + if err := httphelper.HttpRequest(caller.HttpClient(), req, &tokenRes); err != nil { return nil, err } return &oauth2.Token{ @@ -69,7 +70,7 @@ func callTokenEndpoint(request interface{}, authFn interface{}, caller tokenEndp } func NewSignerFromPrivateKeyByte(key []byte, keyID string) (jose.Signer, error) { - privateKey, err := utils.BytesToPrivateKey(key) + privateKey, err := crypto.BytesToPrivateKey(key) if err != nil { return nil, err } @@ -83,7 +84,7 @@ func NewSignerFromPrivateKeyByte(key []byte, keyID string) (jose.Signer, error) func SignedJWTProfileAssertion(clientID string, audience []string, expiration time.Duration, signer jose.Signer) (string, error) { iat := time.Now() exp := iat.Add(expiration) - return utils.Sign(&oidc.JWTTokenRequest{ + return crypto.Sign(&oidc.JWTTokenRequest{ Issuer: clientID, Subject: clientID, Audience: audience, diff --git a/pkg/client/jwt_profile.go b/pkg/client/jwt_profile.go index 89679ec..e120541 100644 --- a/pkg/client/jwt_profile.go +++ b/pkg/client/jwt_profile.go @@ -5,8 +5,8 @@ import ( "golang.org/x/oauth2" + "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) //JWTProfileExchange handles the oauth2 jwt profile exchange @@ -21,7 +21,7 @@ func ClientAssertionCodeOptions(assertion string) []oauth2.AuthCodeOption { } } -func ClientAssertionFormAuthorization(assertion string) utils.FormAuthorization { +func ClientAssertionFormAuthorization(assertion string) http.FormAuthorization { return func(values url.Values) { values.Set("client_assertion", assertion) values.Set("client_assertion_type", oidc.ClientAssertionTypeJWTAssertion) diff --git a/pkg/utils/browser.go b/pkg/client/rp/cli/browser.go similarity index 96% rename from pkg/utils/browser.go rename to pkg/client/rp/cli/browser.go index dca75e4..1948427 100644 --- a/pkg/utils/browser.go +++ b/pkg/client/rp/cli/browser.go @@ -1,4 +1,4 @@ -package utils +package cli import ( "fmt" diff --git a/pkg/client/rp/cli/cli.go b/pkg/client/rp/cli/cli.go index 89566eb..aba1546 100644 --- a/pkg/client/rp/cli/cli.go +++ b/pkg/client/rp/cli/cli.go @@ -5,8 +5,8 @@ import ( "net/http" "github.com/caos/oidc/pkg/client/rp" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) const ( @@ -28,9 +28,9 @@ func CodeFlow(ctx context.Context, relyingParty rp.RelyingParty, callbackPath, p http.Handle(loginPath, rp.AuthURLHandler(stateProvider, relyingParty)) http.Handle(callbackPath, rp.CodeExchangeHandler(callback, relyingParty)) - utils.StartServer(codeflowCtx, ":"+port) + httphelper.StartServer(codeflowCtx, ":"+port) - utils.OpenBrowser("http://localhost:" + port + loginPath) + OpenBrowser("http://localhost:" + port + loginPath) return <-tokenChan } diff --git a/pkg/client/rp/delegation.go b/pkg/client/rp/delegation.go index 3ae6bb6..73edd96 100644 --- a/pkg/client/rp/delegation.go +++ b/pkg/client/rp/delegation.go @@ -5,8 +5,8 @@ import ( ) //DelegationTokenRequest is an implementation of TokenExchangeRequest -//it exchanges a "urn:ietf:params:oauth:token-type:access_token" with an optional -//"urn:ietf:params:oauth:token-type:access_token" actor token for a +//it exchanges an "urn:ietf:params:oauth:token-type:access_token" with an optional +//"urn:ietf:params:oauth:token-type:access_token" actor token for an //"urn:ietf:params:oauth:token-type:access_token" delegation token func DelegationTokenRequest(subjectToken string, opts ...tokenexchange.TokenExchangeOption) *tokenexchange.TokenExchangeRequest { return tokenexchange.NewTokenExchangeRequest(subjectToken, tokenexchange.AccessTokenType, opts...) diff --git a/pkg/client/rp/jwks.go b/pkg/client/rp/jwks.go index 4062ab4..78f9580 100644 --- a/pkg/client/rp/jwks.go +++ b/pkg/client/rp/jwks.go @@ -7,9 +7,9 @@ import ( "net/http" "sync" - "github.com/caos/oidc/pkg/utils" "gopkg.in/square/go-jose.v2" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" ) @@ -207,7 +207,7 @@ func (r *remoteKeySet) fetchRemoteKeys(ctx context.Context) ([]jose.JSONWebKey, } keySet := new(jsonWebKeySet) - if err = utils.HttpRequest(r.httpClient, req, keySet); err != nil { + if err = httphelper.HttpRequest(r.httpClient, req, keySet); err != nil { return nil, fmt.Errorf("oidc: failed to get keys: %v", err) } return keySet.Keys, nil diff --git a/pkg/client/rp/relaying_party.go b/pkg/client/rp/relaying_party.go index 91fa324..302636b 100644 --- a/pkg/client/rp/relaying_party.go +++ b/pkg/client/rp/relaying_party.go @@ -8,13 +8,13 @@ import ( "strings" "time" + httphelper "github.com/caos/oidc/pkg/http" "github.com/google/uuid" "golang.org/x/oauth2" "gopkg.in/square/go-jose.v2" "github.com/caos/oidc/pkg/client" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) const ( @@ -39,7 +39,7 @@ type RelyingParty interface { IsPKCE() bool //CookieHandler returns a http cookie handler used for various state transfer cookies - CookieHandler() *utils.CookieHandler + CookieHandler() *httphelper.CookieHandler //HttpClient returns a http client used for calls to the openid provider, e.g. calling token endpoint HttpClient() *http.Client @@ -76,7 +76,7 @@ type relyingParty struct { pkce bool httpClient *http.Client - cookieHandler *utils.CookieHandler + cookieHandler *httphelper.CookieHandler errorHandler func(http.ResponseWriter, *http.Request, string, string, string) idTokenVerifier IDTokenVerifier @@ -96,7 +96,7 @@ func (rp *relyingParty) IsPKCE() bool { return rp.pkce } -func (rp *relyingParty) CookieHandler() *utils.CookieHandler { +func (rp *relyingParty) CookieHandler() *httphelper.CookieHandler { return rp.cookieHandler } @@ -136,7 +136,7 @@ func (rp *relyingParty) ErrorHandler() func(http.ResponseWriter, *http.Request, func NewRelyingPartyOAuth(config *oauth2.Config, options ...Option) (RelyingParty, error) { rp := &relyingParty{ oauthConfig: config, - httpClient: utils.DefaultHTTPClient, + httpClient: httphelper.DefaultHTTPClient, oauth2Only: true, } @@ -161,7 +161,7 @@ func NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI string, sco RedirectURL: redirectURI, Scopes: scopes, }, - httpClient: utils.DefaultHTTPClient, + httpClient: httphelper.DefaultHTTPClient, oauth2Only: false, } @@ -185,7 +185,7 @@ func NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI string, sco type Option func(*relyingParty) error //WithCookieHandler set a `CookieHandler` for securing the various redirects -func WithCookieHandler(cookieHandler *utils.CookieHandler) Option { +func WithCookieHandler(cookieHandler *httphelper.CookieHandler) Option { return func(rp *relyingParty) error { rp.cookieHandler = cookieHandler return nil @@ -195,7 +195,7 @@ func WithCookieHandler(cookieHandler *utils.CookieHandler) Option { //WithPKCE sets the RP to use PKCE (oauth2 code challenge) //it also sets a `CookieHandler` for securing the various redirects //and exchanging the code challenge -func WithPKCE(cookieHandler *utils.CookieHandler) Option { +func WithPKCE(cookieHandler *httphelper.CookieHandler) Option { return func(rp *relyingParty) error { rp.pkce = true rp.cookieHandler = cookieHandler @@ -246,7 +246,7 @@ func Discover(issuer string, httpClient *http.Client) (Endpoints, error) { return Endpoints{}, err } discoveryConfig := new(oidc.DiscoveryConfiguration) - err = utils.HttpRequest(httpClient, req, &discoveryConfig) + err = httphelper.HttpRequest(httpClient, req, &discoveryConfig) if err != nil { return Endpoints{}, err } @@ -395,7 +395,7 @@ func Userinfo(token, tokenType, subject string, rp RelyingParty) (oidc.UserInfo, } req.Header.Set("authorization", tokenType+" "+token) userinfo := oidc.NewUserInfo() - if err := utils.HttpRequest(rp.HttpClient(), req, &userinfo); err != nil { + if err := httphelper.HttpRequest(rp.HttpClient(), req, &userinfo); err != nil { return nil, err } if userinfo.GetSubject() != subject { diff --git a/pkg/client/rs/resource_server.go b/pkg/client/rs/resource_server.go index 551fe88..224442f 100644 --- a/pkg/client/rs/resource_server.go +++ b/pkg/client/rs/resource_server.go @@ -7,8 +7,8 @@ import ( "time" "github.com/caos/oidc/pkg/client" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type ResourceServer interface { @@ -39,7 +39,7 @@ func (r *resourceServer) AuthFn() (interface{}, error) { func NewResourceServerClientCredentials(issuer, clientID, clientSecret string, option ...Option) (ResourceServer, error) { authorizer := func() (interface{}, error) { - return utils.AuthorizeBasic(clientID, clientSecret), nil + return httphelper.AuthorizeBasic(clientID, clientSecret), nil } return newResourceServer(issuer, authorizer, option...) } @@ -61,7 +61,7 @@ func NewResourceServerJWTProfile(issuer, clientID, keyID string, key []byte, opt func newResourceServer(issuer string, authorizer func() (interface{}, error), options ...Option) (*resourceServer, error) { rs := &resourceServer{ issuer: issuer, - httpClient: utils.DefaultHTTPClient, + httpClient: httphelper.DefaultHTTPClient, } for _, optFunc := range options { optFunc(rs) @@ -111,12 +111,12 @@ func Introspect(ctx context.Context, rp ResourceServer, token string) (oidc.Intr if err != nil { return nil, err } - req, err := utils.FormRequest(rp.IntrospectionURL(), &oidc.IntrospectionRequest{Token: token}, client.Encoder, authFn) + req, err := httphelper.FormRequest(rp.IntrospectionURL(), &oidc.IntrospectionRequest{Token: token}, client.Encoder, authFn) if err != nil { return nil, err } resp := oidc.NewIntrospectionResponse() - if err := utils.HttpRequest(rp.HttpClient(), req, resp); err != nil { + if err := httphelper.HttpRequest(rp.HttpClient(), req, resp); err != nil { return nil, err } return resp, nil diff --git a/pkg/utils/crypto.go b/pkg/crypto/crypto.go similarity index 99% rename from pkg/utils/crypto.go rename to pkg/crypto/crypto.go index 3ca4963..a06809a 100644 --- a/pkg/utils/crypto.go +++ b/pkg/crypto/crypto.go @@ -1,4 +1,4 @@ -package utils +package crypto import ( "crypto/aes" diff --git a/pkg/utils/hash.go b/pkg/crypto/hash.go similarity index 98% rename from pkg/utils/hash.go rename to pkg/crypto/hash.go index 5dae03c..5b9d9ae 100644 --- a/pkg/utils/hash.go +++ b/pkg/crypto/hash.go @@ -1,4 +1,4 @@ -package utils +package crypto import ( "crypto/sha256" diff --git a/pkg/utils/key.go b/pkg/crypto/key.go similarity index 94% rename from pkg/utils/key.go rename to pkg/crypto/key.go index 60820a5..d75d1ab 100644 --- a/pkg/utils/key.go +++ b/pkg/crypto/key.go @@ -1,4 +1,4 @@ -package utils +package crypto import ( "crypto/rsa" diff --git a/pkg/utils/sign.go b/pkg/crypto/sign.go similarity index 97% rename from pkg/utils/sign.go rename to pkg/crypto/sign.go index 5ebac43..a0b9cae 100644 --- a/pkg/utils/sign.go +++ b/pkg/crypto/sign.go @@ -1,4 +1,4 @@ -package utils +package crypto import ( "encoding/json" diff --git a/pkg/utils/cookie.go b/pkg/http/cookie.go similarity index 99% rename from pkg/utils/cookie.go rename to pkg/http/cookie.go index 9e73e08..62ea295 100644 --- a/pkg/utils/cookie.go +++ b/pkg/http/cookie.go @@ -1,4 +1,4 @@ -package utils +package http import ( "errors" diff --git a/pkg/utils/http.go b/pkg/http/http.go similarity index 97% rename from pkg/utils/http.go rename to pkg/http/http.go index 27f96f9..2512707 100644 --- a/pkg/utils/http.go +++ b/pkg/http/http.go @@ -1,4 +1,4 @@ -package utils +package http import ( "context" @@ -14,7 +14,7 @@ import ( var ( DefaultHTTPClient = &http.Client{ - Timeout: time.Duration(30 * time.Second), + Timeout: 30 * time.Second, } ) diff --git a/pkg/utils/marshal.go b/pkg/http/marshal.go similarity index 98% rename from pkg/utils/marshal.go rename to pkg/http/marshal.go index a755e84..f6b872d 100644 --- a/pkg/utils/marshal.go +++ b/pkg/http/marshal.go @@ -1,4 +1,4 @@ -package utils +package http import ( "bytes" diff --git a/pkg/utils/marshal_test.go b/pkg/http/marshal_test.go similarity index 98% rename from pkg/utils/marshal_test.go rename to pkg/http/marshal_test.go index f9221f6..03410d3 100644 --- a/pkg/utils/marshal_test.go +++ b/pkg/http/marshal_test.go @@ -1,4 +1,4 @@ -package utils +package http import ( "bytes" diff --git a/pkg/oidc/code_challenge.go b/pkg/oidc/code_challenge.go index 9c4c8a3..4e82feb 100644 --- a/pkg/oidc/code_challenge.go +++ b/pkg/oidc/code_challenge.go @@ -3,7 +3,7 @@ package oidc import ( "crypto/sha256" - "github.com/caos/oidc/pkg/utils" + "github.com/caos/oidc/pkg/crypto" ) const ( @@ -19,7 +19,7 @@ type CodeChallenge struct { } func NewSHACodeChallenge(code string) string { - return utils.HashString(sha256.New(), code, false) + return crypto.HashString(sha256.New(), code, false) } func VerifyCodeChallenge(c *CodeChallenge, codeVerifier string) bool { diff --git a/pkg/oidc/token.go b/pkg/oidc/token.go index 2980ed4..cf2b80a 100644 --- a/pkg/oidc/token.go +++ b/pkg/oidc/token.go @@ -9,7 +9,8 @@ import ( "golang.org/x/oauth2" "gopkg.in/square/go-jose.v2" - "github.com/caos/oidc/pkg/utils" + "github.com/caos/oidc/pkg/crypto" + "github.com/caos/oidc/pkg/http" ) const ( @@ -185,7 +186,7 @@ func (a *accessTokenClaims) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return utils.ConcatenateJSON(b, info) + return http.ConcatenateJSON(b, info) } func (a *accessTokenClaims) UnmarshalJSON(data []byte) error { @@ -372,7 +373,7 @@ func (t *idTokenClaims) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } - return utils.ConcatenateJSON(b, info) + return http.ConcatenateJSON(b, info) } func (t *idTokenClaims) UnmarshalJSON(data []byte) error { @@ -569,12 +570,12 @@ func NewJWTProfileAssertion(userID, keyID string, audience []string, key []byte, } func ClaimHash(claim string, sigAlgorithm jose.SignatureAlgorithm) (string, error) { - hash, err := utils.GetHashAlgorithm(sigAlgorithm) + hash, err := crypto.GetHashAlgorithm(sigAlgorithm) if err != nil { return "", err } - return utils.HashString(hash, claim, true), nil + return crypto.HashString(hash, claim, true), nil } func AppendClientIDToAudience(clientID string, audience []string) []string { @@ -587,7 +588,7 @@ func AppendClientIDToAudience(clientID string, audience []string) []string { } func GenerateJWTProfileToken(assertion JWTProfileAssertionClaims) (string, error) { - privateKey, err := utils.BytesToPrivateKey(assertion.GetPrivateKey()) + privateKey, err := crypto.BytesToPrivateKey(assertion.GetPrivateKey()) if err != nil { return "", err } diff --git a/pkg/oidc/verifier.go b/pkg/oidc/verifier.go index 4284d17..0ab6c1d 100644 --- a/pkg/oidc/verifier.go +++ b/pkg/oidc/verifier.go @@ -12,7 +12,7 @@ import ( "gopkg.in/square/go-jose.v2" - "github.com/caos/oidc/pkg/utils" + str "github.com/caos/oidc/pkg/strings" ) type Claims interface { @@ -61,10 +61,10 @@ type Verifier interface { type ACRVerifier func(string) error //DefaultACRVerifier implements `ACRVerifier` returning an error -//if non of the provided values matches the acr claim +//if none of the provided values matches the acr claim func DefaultACRVerifier(possibleValues []string) ACRVerifier { return func(acr string) error { - if !utils.Contains(possibleValues, acr) { + if !str.Contains(possibleValues, acr) { return fmt.Errorf("expected one of: %v, got: %q", possibleValues, acr) } return nil @@ -103,7 +103,7 @@ func CheckIssuer(claims Claims, issuer string) error { } func CheckAudience(claims Claims, clientID string) error { - if !utils.Contains(claims.GetAudience(), clientID) { + if !str.Contains(claims.GetAudience(), clientID) { return fmt.Errorf("%w: Audience must contain client_id %q", ErrAudience, clientID) } @@ -138,7 +138,7 @@ func CheckSignature(ctx context.Context, token string, payload []byte, claims Cl if len(supportedSigAlgs) == 0 { supportedSigAlgs = []string{"RS256"} } - if !utils.Contains(supportedSigAlgs, sig.Header.Algorithm) { + 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) } diff --git a/pkg/op/auth_request.go b/pkg/op/auth_request.go index cd694d1..a6348bd 100644 --- a/pkg/op/auth_request.go +++ b/pkg/op/auth_request.go @@ -11,8 +11,9 @@ import ( "github.com/gorilla/mux" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" + str "github.com/caos/oidc/pkg/strings" ) type AuthRequest interface { @@ -34,8 +35,8 @@ type AuthRequest interface { type Authorizer interface { Storage() Storage - Decoder() utils.Decoder - Encoder() utils.Encoder + Decoder() httphelper.Decoder + Encoder() httphelper.Encoder Signer() Signer IDTokenHintVerifier() IDTokenHintVerifier Crypto() Crypto @@ -92,7 +93,7 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) { } //ParseAuthorizeRequest parsed the http request into a oidc.AuthRequest -func ParseAuthorizeRequest(r *http.Request, decoder utils.Decoder) (*oidc.AuthRequest, error) { +func ParseAuthorizeRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.AuthRequest, error) { err := r.ParseForm() if err != nil { return nil, oidc.ErrInvalidRequest().WithDescription("cannot parse form").WithParent(err) @@ -182,7 +183,7 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res "Please ensure it is added to the request. If you have any questions, you may contact the administrator of the application.") } if strings.HasPrefix(uri, "https://") { - if !utils.Contains(client.RedirectURIs(), uri) { + if !str.Contains(client.RedirectURIs(), uri) { return oidc.ErrInvalidRequestRedirectURI(). WithDescription("The requested redirect_uri is missing in the client configuration. " + "If you have any questions, you may contact the administrator of the application.") @@ -192,7 +193,7 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res if client.ApplicationType() == ApplicationTypeNative { return validateAuthReqRedirectURINative(client, uri, responseType) } - if !utils.Contains(client.RedirectURIs(), uri) { + if !str.Contains(client.RedirectURIs(), uri) { return oidc.ErrInvalidRequestRedirectURI().WithDescription("The requested redirect_uri is missing in the client configuration. " + "If you have any questions, you may contact the administrator of the application.") } @@ -214,7 +215,7 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res func validateAuthReqRedirectURINative(client Client, uri string, responseType oidc.ResponseType) error { parsedURL, isLoopback := HTTPLoopbackOrLocalhost(uri) isCustomSchema := !strings.HasPrefix(uri, "http://") - if utils.Contains(client.RedirectURIs(), uri) { + if str.Contains(client.RedirectURIs(), uri) { if isLoopback || isCustomSchema { return nil } @@ -339,7 +340,7 @@ func AuthResponseToken(w http.ResponseWriter, r *http.Request, authReq AuthReque AuthRequestError(w, r, authReq, err, authorizer.Encoder()) return } - params, err := utils.URLEncodeResponse(resp, authorizer.Encoder()) + params, err := httphelper.URLEncodeResponse(resp, authorizer.Encoder()) if err != nil { AuthRequestError(w, r, authReq, err, authorizer.Encoder()) return diff --git a/pkg/op/auth_request_test.go b/pkg/op/auth_request_test.go index aae7beb..eadfdd3 100644 --- a/pkg/op/auth_request_test.go +++ b/pkg/op/auth_request_test.go @@ -13,10 +13,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" "github.com/caos/oidc/pkg/op" "github.com/caos/oidc/pkg/op/mock" - "github.com/caos/oidc/pkg/utils" ) // @@ -77,7 +77,7 @@ import ( func TestParseAuthorizeRequest(t *testing.T) { type args struct { r *http.Request - decoder utils.Decoder + decoder httphelper.Decoder } type res struct { want *oidc.AuthRequest @@ -103,7 +103,7 @@ func TestParseAuthorizeRequest(t *testing.T) { "decoding error", args{ &http.Request{URL: &url.URL{RawQuery: "unknown=value"}}, - func() utils.Decoder { + func() httphelper.Decoder { decoder := schema.NewDecoder() decoder.IgnoreUnknownKeys(false) return decoder @@ -118,7 +118,7 @@ func TestParseAuthorizeRequest(t *testing.T) { "parsing ok", args{ &http.Request{URL: &url.URL{RawQuery: "scope=openid"}}, - func() utils.Decoder { + func() httphelper.Decoder { decoder := schema.NewDecoder() decoder.IgnoreUnknownKeys(false) return decoder diff --git a/pkg/op/crypto.go b/pkg/op/crypto.go index e95157d..e9dd67b 100644 --- a/pkg/op/crypto.go +++ b/pkg/op/crypto.go @@ -1,7 +1,7 @@ package op import ( - "github.com/caos/oidc/pkg/utils" + "github.com/caos/oidc/pkg/crypto" ) type Crypto interface { @@ -18,9 +18,9 @@ func NewAESCrypto(key [32]byte) Crypto { } func (c *aesCrypto) Encrypt(s string) (string, error) { - return utils.EncryptAES(s, c.key) + return crypto.EncryptAES(s, c.key) } func (c *aesCrypto) Decrypt(s string) (string, error) { - return utils.DecryptAES(s, c.key) + return crypto.DecryptAES(s, c.key) } diff --git a/pkg/op/discovery.go b/pkg/op/discovery.go index 807aa20..fc5a1c0 100644 --- a/pkg/op/discovery.go +++ b/pkg/op/discovery.go @@ -3,8 +3,8 @@ package op import ( "net/http" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) func discoveryHandler(c Configuration, s Signer) func(http.ResponseWriter, *http.Request) { @@ -14,7 +14,7 @@ func discoveryHandler(c Configuration, s Signer) func(http.ResponseWriter, *http } func Discover(w http.ResponseWriter, config *oidc.DiscoveryConfiguration) { - utils.MarshalJSON(w, config) + httphelper.MarshalJSON(w, config) } func CreateDiscoveryConfig(c Configuration, s Signer) *oidc.DiscoveryConfiguration { diff --git a/pkg/op/error.go b/pkg/op/error.go index d208f91..cc8267b 100644 --- a/pkg/op/error.go +++ b/pkg/op/error.go @@ -3,8 +3,8 @@ package op import ( "net/http" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type ErrAuthRequest interface { @@ -13,7 +13,7 @@ type ErrAuthRequest interface { GetState() string } -func AuthRequestError(w http.ResponseWriter, r *http.Request, authReq ErrAuthRequest, err error, encoder utils.Encoder) { +func AuthRequestError(w http.ResponseWriter, r *http.Request, authReq ErrAuthRequest, err error, encoder httphelper.Encoder) { if authReq == nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -24,7 +24,7 @@ func AuthRequestError(w http.ResponseWriter, r *http.Request, authReq ErrAuthReq http.Error(w, e.Description, http.StatusBadRequest) return } - params, err := utils.URLEncodeResponse(e, encoder) + params, err := httphelper.URLEncodeResponse(e, encoder) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -45,5 +45,5 @@ func RequestError(w http.ResponseWriter, r *http.Request, err error) { if e.ErrorType == oidc.InvalidClient { status = 401 } - utils.MarshalJSONWithStatus(w, e, status) + httphelper.MarshalJSONWithStatus(w, e, status) } diff --git a/pkg/op/keys.go b/pkg/op/keys.go index 5875a7b..e637066 100644 --- a/pkg/op/keys.go +++ b/pkg/op/keys.go @@ -6,7 +6,7 @@ import ( "gopkg.in/square/go-jose.v2" - "github.com/caos/oidc/pkg/utils" + httphelper "github.com/caos/oidc/pkg/http" ) type KeyProvider interface { @@ -22,8 +22,8 @@ func keysHandler(k KeyProvider) func(http.ResponseWriter, *http.Request) { func Keys(w http.ResponseWriter, r *http.Request, k KeyProvider) { keySet, err := k.GetKeySet(r.Context()) if err != nil { - utils.MarshalJSONWithStatus(w, err, http.StatusInternalServerError) + httphelper.MarshalJSONWithStatus(w, err, http.StatusInternalServerError) return } - utils.MarshalJSON(w, keySet) + httphelper.MarshalJSON(w, keySet) } diff --git a/pkg/op/mock/authorizer.mock.go b/pkg/op/mock/authorizer.mock.go index 69f6927..bb5ac54 100644 --- a/pkg/op/mock/authorizer.mock.go +++ b/pkg/op/mock/authorizer.mock.go @@ -5,11 +5,11 @@ package mock import ( - reflect "reflect" + "reflect" - op "github.com/caos/oidc/pkg/op" - utils "github.com/caos/oidc/pkg/utils" - gomock "github.com/golang/mock/gomock" + utils "github.com/caos/oidc/pkg/http" + "github.com/caos/oidc/pkg/op" + "github.com/golang/mock/gomock" ) // MockAuthorizer is a mock of Authorizer interface. diff --git a/pkg/op/op.go b/pkg/op/op.go index 419a9b9..84657cb 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -12,8 +12,8 @@ import ( "golang.org/x/text/language" "gopkg.in/square/go-jose.v2" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) const ( @@ -41,8 +41,8 @@ var ( type OpenIDProvider interface { Configuration Storage() Storage - Decoder() utils.Decoder - Encoder() utils.Encoder + Decoder() httphelper.Decoder + Encoder() httphelper.Encoder IDTokenHintVerifier() IDTokenHintVerifier AccessTokenVerifier() AccessTokenVerifier Crypto() Crypto @@ -211,11 +211,11 @@ func (o *openidProvider) Storage() Storage { return o.storage } -func (o *openidProvider) Decoder() utils.Decoder { +func (o *openidProvider) Decoder() httphelper.Decoder { return o.decoder } -func (o *openidProvider) Encoder() utils.Encoder { +func (o *openidProvider) Encoder() httphelper.Encoder { return o.encoder } diff --git a/pkg/op/probes.go b/pkg/op/probes.go index c6bb748..b6fdde2 100644 --- a/pkg/op/probes.go +++ b/pkg/op/probes.go @@ -5,7 +5,7 @@ import ( "errors" "net/http" - "github.com/caos/oidc/pkg/utils" + httphelper "github.com/caos/oidc/pkg/http" ) type ProbesFn func(context.Context) error @@ -49,7 +49,7 @@ func ReadyStorage(s Storage) ProbesFn { } func ok(w http.ResponseWriter) { - utils.MarshalJSON(w, status{"ok"}) + httphelper.MarshalJSON(w, status{"ok"}) } type status struct { diff --git a/pkg/op/session.go b/pkg/op/session.go index 205886b..1f9290e 100644 --- a/pkg/op/session.go +++ b/pkg/op/session.go @@ -4,12 +4,12 @@ import ( "context" "net/http" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type SessionEnder interface { - Decoder() utils.Decoder + Decoder() httphelper.Decoder Storage() Storage IDTokenHintVerifier() IDTokenHintVerifier DefaultLogoutRedirectURI() string @@ -44,7 +44,7 @@ func EndSession(w http.ResponseWriter, r *http.Request, ender SessionEnder) { http.Redirect(w, r, session.RedirectURI, http.StatusFound) } -func ParseEndSessionRequest(r *http.Request, decoder utils.Decoder) (*oidc.EndSessionRequest, error) { +func ParseEndSessionRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.EndSessionRequest, error) { err := r.ParseForm() if err != nil { return nil, oidc.ErrInvalidRequest().WithDescription("error parsing form").WithParent(err) diff --git a/pkg/op/token.go b/pkg/op/token.go index 80f8469..3e97360 100644 --- a/pkg/op/token.go +++ b/pkg/op/token.go @@ -4,8 +4,9 @@ import ( "context" "time" + "github.com/caos/oidc/pkg/crypto" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" + "github.com/caos/oidc/pkg/strings" ) type TokenCreator interface { @@ -64,7 +65,7 @@ func createTokens(ctx context.Context, tokenRequest TokenRequest, storage Storag func needsRefreshToken(tokenRequest TokenRequest, client Client) bool { switch req := tokenRequest.(type) { case AuthRequest: - return utils.Contains(req.GetScopes(), oidc.ScopeOfflineAccess) && req.GetResponseType() == oidc.ResponseTypeCode && ValidateGrantType(client, oidc.GrantTypeRefreshToken) + return strings.Contains(req.GetScopes(), oidc.ScopeOfflineAccess) && req.GetResponseType() == oidc.ResponseTypeCode && ValidateGrantType(client, oidc.GrantTypeRefreshToken) case RefreshTokenRequest: return true default: @@ -104,7 +105,7 @@ func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, ex } claims.SetPrivateClaims(privateClaims) } - return utils.Sign(claims, signer.Signer()) + return crypto.Sign(claims, signer.Signer()) } type IDTokenRequest interface { @@ -151,7 +152,7 @@ func CreateIDToken(ctx context.Context, issuer string, request IDTokenRequest, v claims.SetCodeHash(codeHash) } - return utils.Sign(claims, signer.Signer()) + return crypto.Sign(claims, signer.Signer()) } func removeUserinfoScopes(scopes []string) []string { diff --git a/pkg/op/token_code.go b/pkg/op/token_code.go index 62bad2b..7b5873c 100644 --- a/pkg/op/token_code.go +++ b/pkg/op/token_code.go @@ -4,8 +4,8 @@ import ( "context" "net/http" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) //CodeExchange handles the OAuth 2.0 authorization_code grant, including @@ -29,11 +29,11 @@ func CodeExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) { RequestError(w, r, err) return } - utils.MarshalJSON(w, resp) + httphelper.MarshalJSON(w, resp) } //ParseAccessTokenRequest parsed the http request into a oidc.AccessTokenRequest -func ParseAccessTokenRequest(r *http.Request, decoder utils.Decoder) (*oidc.AccessTokenRequest, error) { +func ParseAccessTokenRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.AccessTokenRequest, error) { request := new(oidc.AccessTokenRequest) err := ParseAuthenticatedTokenRequest(r, decoder, request) if err != nil { diff --git a/pkg/op/token_intospection.go b/pkg/op/token_intospection.go index e2ae0ad..8fd9187 100644 --- a/pkg/op/token_intospection.go +++ b/pkg/op/token_intospection.go @@ -5,12 +5,12 @@ import ( "net/http" "net/url" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type Introspector interface { - Decoder() utils.Decoder + Decoder() httphelper.Decoder Crypto() Crypto Storage() Storage AccessTokenVerifier() AccessTokenVerifier @@ -36,16 +36,16 @@ func Introspect(w http.ResponseWriter, r *http.Request, introspector Introspecto } tokenID, subject, ok := getTokenIDAndSubject(r.Context(), introspector, token) if !ok { - utils.MarshalJSON(w, response) + httphelper.MarshalJSON(w, response) return } err = introspector.Storage().SetIntrospectionFromToken(r.Context(), response, tokenID, subject, clientID) if err != nil { - utils.MarshalJSON(w, response) + httphelper.MarshalJSON(w, response) return } response.SetActive(true) - utils.MarshalJSON(w, response) + httphelper.MarshalJSON(w, response) } func ParseTokenIntrospectionRequest(r *http.Request, introspector Introspector) (token, clientID string, err error) { diff --git a/pkg/op/token_jwt_profile.go b/pkg/op/token_jwt_profile.go index 4e2b732..01a1411 100644 --- a/pkg/op/token_jwt_profile.go +++ b/pkg/op/token_jwt_profile.go @@ -5,8 +5,8 @@ import ( "net/http" "time" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type JWTAuthorizationGrantExchanger interface { @@ -37,10 +37,10 @@ func JWTProfile(w http.ResponseWriter, r *http.Request, exchanger JWTAuthorizati RequestError(w, r, err) return } - utils.MarshalJSON(w, resp) + httphelper.MarshalJSON(w, resp) } -func ParseJWTProfileGrantRequest(r *http.Request, decoder utils.Decoder) (*oidc.JWTProfileGrantRequest, error) { +func ParseJWTProfileGrantRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.JWTProfileGrantRequest, error) { err := r.ParseForm() if err != nil { return nil, oidc.ErrInvalidRequest().WithDescription("error parsing form").WithParent(err) @@ -74,6 +74,6 @@ func CreateJWTTokenResponse(ctx context.Context, tokenRequest TokenRequest, crea //ParseJWTProfileRequest has been renamed to ParseJWTProfileGrantRequest // //deprecated: use ParseJWTProfileGrantRequest -func ParseJWTProfileRequest(r *http.Request, decoder utils.Decoder) (*oidc.JWTProfileGrantRequest, error) { +func ParseJWTProfileRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.JWTProfileGrantRequest, error) { return ParseJWTProfileGrantRequest(r, decoder) } diff --git a/pkg/op/token_refresh.go b/pkg/op/token_refresh.go index fe7661d..001c913 100644 --- a/pkg/op/token_refresh.go +++ b/pkg/op/token_refresh.go @@ -6,8 +6,9 @@ import ( "net/http" "time" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" + "github.com/caos/oidc/pkg/strings" ) type RefreshTokenRequest interface { @@ -37,11 +38,11 @@ func RefreshTokenExchange(w http.ResponseWriter, r *http.Request, exchanger Exch RequestError(w, r, err) return } - utils.MarshalJSON(w, resp) + httphelper.MarshalJSON(w, resp) } //ParseRefreshTokenRequest parsed the http request into a oidc.RefreshTokenRequest -func ParseRefreshTokenRequest(r *http.Request, decoder utils.Decoder) (*oidc.RefreshTokenRequest, error) { +func ParseRefreshTokenRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.RefreshTokenRequest, error) { request := new(oidc.RefreshTokenRequest) err := ParseAuthenticatedTokenRequest(r, decoder, request) if err != nil { @@ -77,7 +78,7 @@ func ValidateRefreshTokenScopes(requestedScopes []string, authRequest RefreshTok return nil } for _, scope := range requestedScopes { - if !utils.Contains(authRequest.GetScopes(), scope) { + if !strings.Contains(authRequest.GetScopes(), scope) { return oidc.ErrInvalidScope() } } diff --git a/pkg/op/token_request.go b/pkg/op/token_request.go index e01cd5a..6732bb1 100644 --- a/pkg/op/token_request.go +++ b/pkg/op/token_request.go @@ -5,14 +5,14 @@ import ( "net/http" "net/url" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type Exchanger interface { Issuer() string Storage() Storage - Decoder() utils.Decoder + Decoder() httphelper.Decoder Signer() Signer Crypto() Crypto AuthMethodPostSupported() bool @@ -61,7 +61,7 @@ type AuthenticatedTokenRequest interface { //ParseAuthenticatedTokenRequest parses the client_id and client_secret from the HTTP request from either //HTTP Basic Auth header or form body and sets them into the provided authenticatedTokenRequest interface -func ParseAuthenticatedTokenRequest(r *http.Request, decoder utils.Decoder, request AuthenticatedTokenRequest) error { +func ParseAuthenticatedTokenRequest(r *http.Request, decoder httphelper.Decoder, request AuthenticatedTokenRequest) error { err := r.ParseForm() if err != nil { return oidc.ErrInvalidRequest().WithDescription("error parsing form").WithParent(err) diff --git a/pkg/op/userinfo.go b/pkg/op/userinfo.go index c3f2d55..f07a8bc 100644 --- a/pkg/op/userinfo.go +++ b/pkg/op/userinfo.go @@ -6,12 +6,12 @@ import ( "net/http" "strings" + httphelper "github.com/caos/oidc/pkg/http" "github.com/caos/oidc/pkg/oidc" - "github.com/caos/oidc/pkg/utils" ) type UserinfoProvider interface { - Decoder() utils.Decoder + Decoder() httphelper.Decoder Crypto() Crypto Storage() Storage AccessTokenVerifier() AccessTokenVerifier @@ -37,13 +37,13 @@ func Userinfo(w http.ResponseWriter, r *http.Request, userinfoProvider UserinfoP info := oidc.NewUserInfo() err = userinfoProvider.Storage().SetUserinfoFromToken(r.Context(), info, tokenID, subject, r.Header.Get("origin")) if err != nil { - utils.MarshalJSONWithStatus(w, err, http.StatusForbidden) + httphelper.MarshalJSONWithStatus(w, err, http.StatusForbidden) return } - utils.MarshalJSON(w, info) + httphelper.MarshalJSON(w, info) } -func ParseUserinfoRequest(r *http.Request, decoder utils.Decoder) (string, error) { +func ParseUserinfoRequest(r *http.Request, decoder httphelper.Decoder) (string, error) { accessToken, err := getAccessToken(r) if err == nil { return accessToken, nil diff --git a/pkg/utils/strings.go b/pkg/strings/strings.go similarity index 89% rename from pkg/utils/strings.go rename to pkg/strings/strings.go index 5ffcd37..af48cf3 100644 --- a/pkg/utils/strings.go +++ b/pkg/strings/strings.go @@ -1,4 +1,4 @@ -package utils +package strings func Contains(list []string, needle string) bool { for _, item := range list { diff --git a/pkg/utils/strings_test.go b/pkg/strings/strings_test.go similarity index 98% rename from pkg/utils/strings_test.go rename to pkg/strings/strings_test.go index 86af2af..78698d4 100644 --- a/pkg/utils/strings_test.go +++ b/pkg/strings/strings_test.go @@ -1,4 +1,4 @@ -package utils +package strings import "testing"