backup
This commit is contained in:
parent
10d671956a
commit
80eeee2de2
19 changed files with 422 additions and 157 deletions
|
@ -6,6 +6,13 @@ import (
|
|||
"github.com/caos/oidc/pkg/oidc"
|
||||
)
|
||||
|
||||
type Signer struct {
|
||||
}
|
||||
|
||||
func (s *Signer) Sign(*oidc.IDTokenClaims) (string, error) {
|
||||
return "sdsa", nil
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
}
|
||||
|
||||
|
@ -64,5 +71,5 @@ func (c *ConfClient) LoginURL(id string) string {
|
|||
}
|
||||
|
||||
func (c *ConfClient) ApplicationType() oidc.ApplicationType {
|
||||
return oidc.ApplicationTypeWeb
|
||||
return oidc.ApplicationTypeNative
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ func main() {
|
|||
Port: "9998",
|
||||
}
|
||||
storage := &mock.Storage{}
|
||||
handler, err := server.NewDefaultOP(config, storage, server.WithCustomTokenEndpoint("test"))
|
||||
signer := &mock.Signer{}
|
||||
handler, err := server.NewDefaultOP(config, storage, signer, server.WithCustomTokenEndpoint("test"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -10,25 +10,35 @@ import (
|
|||
"github.com/gorilla/schema"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op/u"
|
||||
str_utils "github.com/caos/utils/strings"
|
||||
)
|
||||
|
||||
type Authorizer interface {
|
||||
Storage() Storage
|
||||
Storage() u.Storage
|
||||
Decoder() *schema.Decoder
|
||||
Encoder() *schema.Encoder
|
||||
Signer() Signer
|
||||
Signe() u.Signer
|
||||
ErrorHandler() func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error)
|
||||
}
|
||||
|
||||
// type Signer interface {
|
||||
// Sign(claims *oidc.IDTokenClaims) (string, error)
|
||||
// }
|
||||
|
||||
type ValidationAuthorizer interface {
|
||||
Authorizer
|
||||
ValidateAuthRequest(*oidc.AuthRequest, Storage) error
|
||||
ValidateAuthRequest(*oidc.AuthRequest, u.Storage) error
|
||||
}
|
||||
|
||||
// type errorHandler func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error)
|
||||
type callbackHandler func(authReq *oidc.AuthRequest, client oidc.Client, w http.ResponseWriter, r *http.Request)
|
||||
|
||||
func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
AuthRequestError(w, r, nil, ErrInvalidRequest("cannot parse form: %v", err))
|
||||
AuthRequestError(w, r, nil, ErrInvalidRequest("cannot parse form"))
|
||||
// AuthRequestError(w, r, nil, )
|
||||
return
|
||||
}
|
||||
authReq := new(oidc.AuthRequest)
|
||||
|
@ -62,7 +72,7 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
|
|||
RedirectToLogin(authReq, client, w, r)
|
||||
}
|
||||
|
||||
func ValidateAuthRequest(authReq *oidc.AuthRequest, storage Storage) error {
|
||||
func ValidateAuthRequest(authReq *oidc.AuthRequest, storage u.Storage) error {
|
||||
if err := ValidateAuthReqScopes(authReq.Scopes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,7 +100,7 @@ func ValidateAuthReqScopes(scopes []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ValidateAuthReqRedirectURI(uri, client_id string, responseType oidc.ResponseType, storage Storage) error {
|
||||
func ValidateAuthReqRedirectURI(uri, client_id string, responseType oidc.ResponseType, storage u.Storage) error {
|
||||
if uri == "" {
|
||||
return ErrInvalidRequest("redirect_uri must not be empty")
|
||||
}
|
||||
|
@ -153,7 +163,7 @@ func AuthResponse(authReq *oidc.AuthRequest, authorizer Authorizer, w http.Respo
|
|||
|
||||
}
|
||||
}
|
||||
idToken, err := CreateIDToken(authReq, accessToken, authorizer.Signer())
|
||||
idToken, err := CreateIDToken(authReq, accessToken, authorizer.Signe())
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
|
|
|
@ -3,19 +3,18 @@ package op
|
|||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/schema"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
"github.com/caos/oidc/pkg/op/mock"
|
||||
"github.com/caos/oidc/pkg/op/u"
|
||||
)
|
||||
|
||||
func TestValidateAuthRequest(t *testing.T) {
|
||||
type args struct {
|
||||
authRequest *oidc.AuthRequest
|
||||
storage op.Storage
|
||||
storage u.Storage
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -66,7 +65,7 @@ func TestValidateAuthReqRedirectURI(t *testing.T) {
|
|||
uri string
|
||||
clientID string
|
||||
responseType oidc.ResponseType
|
||||
storage op.Storage
|
||||
storage u.Storage
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -172,23 +171,54 @@ func TestValidateAuthReqScopes(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAuthorize(t *testing.T) {
|
||||
// testCallback := func(t *testing.T, clienID string) callbackHandler {
|
||||
// return func(authReq *oidc.AuthRequest, client oidc.Client, w http.ResponseWriter, r *http.Request) {
|
||||
// // require.Equal(t, clientID, client.)
|
||||
// }
|
||||
// }
|
||||
// testErr := func(t *testing.T, expected error) errorHandler {
|
||||
// return func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error) {
|
||||
// require.Equal(t, expected, err)
|
||||
// }
|
||||
// }
|
||||
type args struct {
|
||||
w http.ResponseWriter
|
||||
r *http.Request
|
||||
storage Storage
|
||||
decoder *schema.Decoder
|
||||
w http.ResponseWriter
|
||||
r *http.Request
|
||||
authorizer Authorizer
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
}{
|
||||
{"parsing fails", args{httptest.NewRecorder(), &http.Request{Method: "POST", Body: nil}, nil, nil}},
|
||||
{"decoding fails", args{httptest.NewRecorder(), &http.Request{}, nil, schema.NewDecoder()}},
|
||||
{"decoding fails", args{httptest.NewRecorder(), &http.Request{}, nil, schema.NewDecoder()}},
|
||||
{
|
||||
"parsing fails",
|
||||
args{
|
||||
httptest.NewRecorder(),
|
||||
&http.Request{Method: "POST", Body: nil},
|
||||
mock.NewAuthorizerExpectValid(t, true),
|
||||
// testCallback(t, ""),
|
||||
// testErr(t, ErrInvalidRequest("cannot parse form")),
|
||||
},
|
||||
},
|
||||
{
|
||||
"decoding fails",
|
||||
args{
|
||||
httptest.NewRecorder(),
|
||||
func() *http.Request {
|
||||
r := httptest.NewRequest("POST", "/authorize", strings.NewReader("client_id=foo"))
|
||||
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
return r
|
||||
}(),
|
||||
mock.NewAuthorizerExpectValid(t, true),
|
||||
// testCallback(t, ""),
|
||||
// testErr(t, ErrInvalidRequest("cannot parse auth request")),
|
||||
},
|
||||
},
|
||||
// {"decoding fails", args{httptest.NewRecorder(), &http.Request{}, mock.NewAuthorizerExpectValid(t), nil, testErr(t, nil)}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
Authorize(tt.args.w, tt.args.r, tt.args.storage, tt.args.decoder)
|
||||
Authorize(tt.args.w, tt.args.r, tt.args.authorizer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
package op
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/schema"
|
||||
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op/u"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultAuthorizationEndpoint = "authorize"
|
||||
defaulTokenEndpoint = "oauth/token"
|
||||
defaultIntrospectEndpoint = "introspect"
|
||||
defaultUserinfoEndpoint = "userinfo"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultEndpoints = &endpoints{
|
||||
Authorization: defaultAuthorizationEndpoint,
|
||||
Token: defaulTokenEndpoint,
|
||||
IntrospectionEndpoint: defaultIntrospectEndpoint,
|
||||
Userinfo: defaultUserinfoEndpoint,
|
||||
}
|
||||
)
|
||||
|
||||
type DefaultOP struct {
|
||||
config *Config
|
||||
endpoints *endpoints
|
||||
discoveryConfig *oidc.DiscoveryConfiguration
|
||||
storage Storage
|
||||
storage u.Storage
|
||||
signer u.Signer
|
||||
http *http.Server
|
||||
decoder *schema.Decoder
|
||||
encoder *schema.Encoder
|
||||
|
@ -77,42 +90,7 @@ func WithCustomUserinfoEndpoint(endpoint Endpoint) DefaultOPOpts {
|
|||
}
|
||||
}
|
||||
|
||||
const (
|
||||
defaultAuthorizationEndpoint = "authorize"
|
||||
defaulTokenEndpoint = "oauth/token"
|
||||
defaultIntrospectEndpoint = "introspect"
|
||||
defaultUserinfoEndpoint = "userinfo"
|
||||
)
|
||||
|
||||
func CreateDiscoveryConfig(c Configuration) *oidc.DiscoveryConfiguration {
|
||||
return &oidc.DiscoveryConfiguration{
|
||||
Issuer: c.Issuer(),
|
||||
AuthorizationEndpoint: c.AuthorizationEndpoint().Absolute(c.Issuer()),
|
||||
TokenEndpoint: c.TokenEndpoint().Absolute(c.Issuer()),
|
||||
// IntrospectionEndpoint: c.Intro().Absolute(c.Issuer()),
|
||||
UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()),
|
||||
// EndSessionEndpoint: c.TokenEndpoint().Absolute(c.Issuer())(c.EndSessionEndpoint),
|
||||
// CheckSessionIframe: c.TokenEndpoint().Absolute(c.Issuer())(c.CheckSessionIframe),
|
||||
// JwksURI: c.TokenEndpoint().Absolute(c.Issuer())(c.JwksURI),
|
||||
// ScopesSupported: oidc.SupportedScopes,
|
||||
// ResponseTypesSupported: responseTypes,
|
||||
// GrantTypesSupported: oidc.SupportedGrantTypes,
|
||||
// ClaimsSupported: oidc.SupportedClaims,
|
||||
// IdTokenSigningAlgValuesSupported: []string{keys.SigningAlgorithm},
|
||||
// SubjectTypesSupported: []string{"public"},
|
||||
// TokenEndpointAuthMethodsSupported:
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var DefaultEndpoints = &endpoints{
|
||||
Authorization: defaultAuthorizationEndpoint,
|
||||
Token: defaulTokenEndpoint,
|
||||
IntrospectionEndpoint: defaultIntrospectEndpoint,
|
||||
Userinfo: defaultUserinfoEndpoint,
|
||||
}
|
||||
|
||||
func NewDefaultOP(config *Config, storage Storage, opOpts ...DefaultOPOpts) (OpenIDProvider, error) {
|
||||
func NewDefaultOP(config *Config, storage u.Storage, signer u.Signer, opOpts ...DefaultOPOpts) (OpenIDProvider, error) {
|
||||
if err := ValidateIssuer(config.Issuer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -120,6 +98,7 @@ func NewDefaultOP(config *Config, storage Storage, opOpts ...DefaultOPOpts) (Ope
|
|||
p := &DefaultOP{
|
||||
config: config,
|
||||
storage: storage,
|
||||
signer: signer,
|
||||
endpoints: DefaultEndpoints,
|
||||
}
|
||||
|
||||
|
@ -148,20 +127,6 @@ func (p *DefaultOP) Issuer() string {
|
|||
return p.config.Issuer
|
||||
}
|
||||
|
||||
type Endpoint string
|
||||
|
||||
func (e Endpoint) Relative() string {
|
||||
return relativeEndpoint(string(e))
|
||||
}
|
||||
|
||||
func (e Endpoint) Absolute(host string) string {
|
||||
return absoluteEndpoint(host, string(e))
|
||||
}
|
||||
|
||||
func (e Endpoint) Validate() error {
|
||||
return nil //TODO:
|
||||
}
|
||||
|
||||
func (p *DefaultOP) AuthorizationEndpoint() Endpoint {
|
||||
return p.endpoints.Authorization
|
||||
}
|
||||
|
@ -183,7 +148,7 @@ func (p *DefaultOP) HttpHandler() *http.Server {
|
|||
}
|
||||
|
||||
func (p *DefaultOP) HandleDiscovery(w http.ResponseWriter, r *http.Request) {
|
||||
utils.MarshalJSON(w, p.discoveryConfig)
|
||||
Discover(w, p.discoveryConfig)
|
||||
}
|
||||
|
||||
func (p *DefaultOP) Decoder() *schema.Decoder {
|
||||
|
@ -194,13 +159,17 @@ func (p *DefaultOP) Encoder() *schema.Encoder {
|
|||
return p.encoder
|
||||
}
|
||||
|
||||
func (p *DefaultOP) Storage() Storage {
|
||||
func (p *DefaultOP) Storage() u.Storage {
|
||||
return p.storage
|
||||
}
|
||||
|
||||
func (p *DefaultOP) Signer() Signer {
|
||||
// return p.signer
|
||||
return nil
|
||||
func (p *DefaultOP) Signe() u.Signer {
|
||||
return p.signer
|
||||
// return
|
||||
}
|
||||
|
||||
func (p *DefaultOP) ErrorHandler() func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error) {
|
||||
return AuthRequestError
|
||||
}
|
||||
|
||||
func (p *DefaultOP) HandleAuthorize(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -270,56 +239,3 @@ func (p *DefaultOP) handleTokenExchange(w http.ResponseWriter, r *http.Request)
|
|||
func (p *DefaultOP) HandleUserinfo(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
// func (c *Config) DefaultAndValidate() error {
|
||||
// if err := ValidateIssuer(c.Issuer); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if c.AuthorizationEndpoint == "" {
|
||||
// c.AuthorizationEndpoint = defaultAuthorizationEndpoint
|
||||
// }
|
||||
// if c.TokenEndpoint == "" {
|
||||
// c.TokenEndpoint = defaulTokenEndpoint
|
||||
// }
|
||||
// if c.IntrospectionEndpoint == "" {
|
||||
// c.IntrospectionEndpoint = defaultIntrospectEndpoint
|
||||
// }
|
||||
// if c.UserinfoEndpoint == "" {
|
||||
// c.UserinfoEndpoint = defaultUserinfoEndpoint
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func ValidateIssuer(issuer string) error {
|
||||
if issuer == "" {
|
||||
return errors.New("missing issuer")
|
||||
}
|
||||
u, err := url.Parse(issuer)
|
||||
if err != nil {
|
||||
return errors.New("invalid url for issuer")
|
||||
}
|
||||
if u.Host == "" {
|
||||
return errors.New("host for issuer missing")
|
||||
}
|
||||
if u.Scheme != "https" {
|
||||
if !(u.Scheme == "http" && (u.Host == "localhost" || u.Host == "127.0.0.1" || u.Host == "::1" || strings.HasPrefix(u.Host, "localhost:"))) { //TODO: ?
|
||||
return errors.New("scheme for issuer must be `https`")
|
||||
}
|
||||
}
|
||||
if u.Fragment != "" || len(u.Query()) > 0 {
|
||||
return errors.New("no fragments or query allowed for issuer")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) absoluteEndpoint(endpoint string) string {
|
||||
return strings.TrimSuffix(c.Issuer, "/") + relativeEndpoint(endpoint)
|
||||
}
|
||||
|
||||
func absoluteEndpoint(host, endpoint string) string {
|
||||
return strings.TrimSuffix(host, "/") + relativeEndpoint(endpoint)
|
||||
}
|
||||
|
||||
func relativeEndpoint(endpoint string) string {
|
||||
return "/" + strings.TrimPrefix(endpoint, "/")
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op/u"
|
||||
)
|
||||
|
||||
func TestDefaultOP_HandleDiscovery(t *testing.T) {
|
||||
|
@ -15,7 +16,7 @@ func TestDefaultOP_HandleDiscovery(t *testing.T) {
|
|||
config *Config
|
||||
endpoints *endpoints
|
||||
discoveryConfig *oidc.DiscoveryConfiguration
|
||||
storage Storage
|
||||
storage u.Storage
|
||||
http *http.Server
|
||||
}
|
||||
type args struct {
|
||||
|
|
33
pkg/op/discovery.go
Normal file
33
pkg/op/discovery.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package op
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
)
|
||||
|
||||
func Discover(w http.ResponseWriter, config *oidc.DiscoveryConfiguration) {
|
||||
utils.MarshalJSON(w, config)
|
||||
}
|
||||
|
||||
func CreateDiscoveryConfig(c Configuration) *oidc.DiscoveryConfiguration {
|
||||
return &oidc.DiscoveryConfiguration{
|
||||
Issuer: c.Issuer(),
|
||||
AuthorizationEndpoint: c.AuthorizationEndpoint().Absolute(c.Issuer()),
|
||||
TokenEndpoint: c.TokenEndpoint().Absolute(c.Issuer()),
|
||||
// IntrospectionEndpoint: c.Intro().Absolute(c.Issuer()),
|
||||
UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()),
|
||||
// EndSessionEndpoint: c.TokenEndpoint().Absolute(c.Issuer())(c.EndSessionEndpoint),
|
||||
// CheckSessionIframe: c.TokenEndpoint().Absolute(c.Issuer())(c.CheckSessionIframe),
|
||||
// JwksURI: c.TokenEndpoint().Absolute(c.Issuer())(c.JwksURI),
|
||||
// ScopesSupported: oidc.SupportedScopes,
|
||||
// ResponseTypesSupported: responseTypes,
|
||||
// GrantTypesSupported: oidc.SupportedGrantTypes,
|
||||
// ClaimsSupported: oidc.SupportedClaims,
|
||||
// IdTokenSigningAlgValuesSupported: []string{keys.SigningAlgorithm},
|
||||
// SubjectTypesSupported: []string{"public"},
|
||||
// TokenEndpointAuthMethodsSupported:
|
||||
|
||||
}
|
||||
}
|
25
pkg/op/endpoint.go
Normal file
25
pkg/op/endpoint.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package op
|
||||
|
||||
import "strings"
|
||||
|
||||
type Endpoint string
|
||||
|
||||
func (e Endpoint) Relative() string {
|
||||
return relativeEndpoint(string(e))
|
||||
}
|
||||
|
||||
func (e Endpoint) Absolute(host string) string {
|
||||
return absoluteEndpoint(host, string(e))
|
||||
}
|
||||
|
||||
func (e Endpoint) Validate() error {
|
||||
return nil //TODO:
|
||||
}
|
||||
|
||||
func absoluteEndpoint(host, endpoint string) string {
|
||||
return strings.TrimSuffix(host, "/") + relativeEndpoint(endpoint)
|
||||
}
|
||||
|
||||
func relativeEndpoint(endpoint string) string {
|
||||
return "/" + strings.TrimPrefix(endpoint, "/")
|
||||
}
|
|
@ -10,6 +10,8 @@ replace github.com/caos/oidc/pkg/utils => /Users/livio/workspaces/go/src/github.
|
|||
|
||||
replace github.com/caos/oidc/pkg/op => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/op
|
||||
|
||||
replace github.com/caos/oidc/pkg/op/u => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/op/u
|
||||
|
||||
require (
|
||||
github.com/caos/oidc v0.0.0-20191119072320-6412f213450c
|
||||
github.com/caos/oidc/pkg/oidc v0.0.0-00010101000000-000000000000
|
||||
|
|
|
@ -55,6 +55,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
|||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
|
|
107
pkg/op/mock/authorizer.mock.go
Normal file
107
pkg/op/mock/authorizer.mock.go
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/caos/oidc/pkg/op (interfaces: Authorizer)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
oidc "github.com/caos/oidc/pkg/oidc"
|
||||
u "github.com/caos/oidc/pkg/op/u"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
schema "github.com/gorilla/schema"
|
||||
http "net/http"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockAuthorizer is a mock of Authorizer interface
|
||||
type MockAuthorizer struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAuthorizerMockRecorder
|
||||
}
|
||||
|
||||
// MockAuthorizerMockRecorder is the mock recorder for MockAuthorizer
|
||||
type MockAuthorizerMockRecorder struct {
|
||||
mock *MockAuthorizer
|
||||
}
|
||||
|
||||
// NewMockAuthorizer creates a new mock instance
|
||||
func NewMockAuthorizer(ctrl *gomock.Controller) *MockAuthorizer {
|
||||
mock := &MockAuthorizer{ctrl: ctrl}
|
||||
mock.recorder = &MockAuthorizerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockAuthorizer) EXPECT() *MockAuthorizerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Decoder mocks base method
|
||||
func (m *MockAuthorizer) Decoder() *schema.Decoder {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Decoder")
|
||||
ret0, _ := ret[0].(*schema.Decoder)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Decoder indicates an expected call of Decoder
|
||||
func (mr *MockAuthorizerMockRecorder) Decoder() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Decoder", reflect.TypeOf((*MockAuthorizer)(nil).Decoder))
|
||||
}
|
||||
|
||||
// Encoder mocks base method
|
||||
func (m *MockAuthorizer) Encoder() *schema.Encoder {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Encoder")
|
||||
ret0, _ := ret[0].(*schema.Encoder)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Encoder indicates an expected call of Encoder
|
||||
func (mr *MockAuthorizerMockRecorder) Encoder() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Encoder", reflect.TypeOf((*MockAuthorizer)(nil).Encoder))
|
||||
}
|
||||
|
||||
// ErrorHandler mocks base method
|
||||
func (m *MockAuthorizer) ErrorHandler() func(http.ResponseWriter, *http.Request, *oidc.AuthRequest, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ErrorHandler")
|
||||
ret0, _ := ret[0].(func(http.ResponseWriter, *http.Request, *oidc.AuthRequest, error))
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ErrorHandler indicates an expected call of ErrorHandler
|
||||
func (mr *MockAuthorizerMockRecorder) ErrorHandler() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ErrorHandler", reflect.TypeOf((*MockAuthorizer)(nil).ErrorHandler))
|
||||
}
|
||||
|
||||
// Signe mocks base method
|
||||
func (m *MockAuthorizer) Signe() u.Signer {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Signe")
|
||||
ret0, _ := ret[0].(u.Signer)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Signe indicates an expected call of Signe
|
||||
func (mr *MockAuthorizerMockRecorder) Signe() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Signe", reflect.TypeOf((*MockAuthorizer)(nil).Signe))
|
||||
}
|
||||
|
||||
// Storage mocks base method
|
||||
func (m *MockAuthorizer) Storage() u.Storage {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Storage")
|
||||
ret0, _ := ret[0].(u.Storage)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Storage indicates an expected call of Storage
|
||||
func (mr *MockAuthorizerMockRecorder) Storage() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockAuthorizer)(nil).Storage))
|
||||
}
|
86
pkg/op/mock/authorizer.mock.impl.go
Normal file
86
pkg/op/mock/authorizer.mock.impl.go
Normal file
|
@ -0,0 +1,86 @@
|
|||
package mock
|
||||
|
||||
import (
|
||||
http "net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/gorilla/schema"
|
||||
|
||||
oidc "github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
u "github.com/caos/oidc/pkg/op/u"
|
||||
)
|
||||
|
||||
func NewAuthorizer(t *testing.T) op.Authorizer {
|
||||
return NewMockAuthorizer(gomock.NewController(t))
|
||||
}
|
||||
|
||||
func NewAuthorizerExpectValid(t *testing.T, wantErr bool) op.Authorizer {
|
||||
m := NewAuthorizer(t)
|
||||
ExpectDecoder(m)
|
||||
ExpectEncoder(m)
|
||||
ExpectSigner(m, t)
|
||||
ExpectStorage(m, t)
|
||||
ExpectErrorHandler(m, t, wantErr)
|
||||
return m
|
||||
}
|
||||
|
||||
// func NewAuthorizerExpectDecoderFails(t *testing.T) op.Authorizer {
|
||||
// m := NewAuthorizer(t)
|
||||
// ExpectDecoderFails(m)
|
||||
// ExpectEncoder(m)
|
||||
// ExpectSigner(m, t)
|
||||
// ExpectStorage(m, t)
|
||||
// ExpectErrorHandler(m, t)
|
||||
// return m
|
||||
// }
|
||||
|
||||
func ExpectDecoder(a op.Authorizer) {
|
||||
mockA := a.(*MockAuthorizer)
|
||||
mockA.EXPECT().Decoder().AnyTimes().Return(schema.NewDecoder())
|
||||
}
|
||||
|
||||
func ExpectEncoder(a op.Authorizer) {
|
||||
mockA := a.(*MockAuthorizer)
|
||||
mockA.EXPECT().Encoder().AnyTimes().Return(schema.NewEncoder())
|
||||
}
|
||||
|
||||
func ExpectSigner(a op.Authorizer, t *testing.T) {
|
||||
mockA := a.(*MockAuthorizer)
|
||||
mockA.EXPECT().Signe().DoAndReturn(
|
||||
func() u.Signer {
|
||||
return &Sig{}
|
||||
})
|
||||
}
|
||||
|
||||
func ExpectErrorHandler(a op.Authorizer, t *testing.T, wantErr bool) {
|
||||
mockA := a.(*MockAuthorizer)
|
||||
mockA.EXPECT().ErrorHandler().AnyTimes().
|
||||
Return(func(w http.ResponseWriter, r *http.Request, authReq *oidc.AuthRequest, err error) {
|
||||
if wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
type Sig struct{}
|
||||
|
||||
func (s *Sig) Sign(*oidc.IDTokenClaims) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func ExpectStorage(a op.Authorizer, t *testing.T) {
|
||||
mockA := a.(*MockAuthorizer)
|
||||
mockA.EXPECT().Storage().AnyTimes().Return(NewMockStorageAny(t))
|
||||
}
|
||||
|
||||
// func NewMockSignerAny(t *testing.T) op.Signer {
|
||||
// m := NewMockSigner(gomock.NewController(t))
|
||||
// m.EXPECT().Sign(gomock.Any()).AnyTimes().Return("", nil)
|
||||
// return m
|
||||
// }
|
|
@ -1,3 +1,4 @@
|
|||
package mock
|
||||
|
||||
//go:generate mockgen -package mock -destination ./storage.mock.go github.com/caos/oidc/pkg/op Storage
|
||||
//go:generate mockgen -package mock -destination ./storage.mock.go github.com/caos/oidc/pkg/op/u Storage
|
||||
//go:generate mockgen -package mock -destination ./authorizer.mock.go github.com/caos/oidc/pkg/op Authorizer
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/caos/oidc/pkg/op (interfaces: Storage)
|
||||
// Source: github.com/caos/oidc/pkg/op/u (interfaces: Storage)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
@ -48,6 +48,21 @@ func (mr *MockStorageMockRecorder) AuthRequestByCode(arg0, arg1, arg2 interface{
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthRequestByCode", reflect.TypeOf((*MockStorage)(nil).AuthRequestByCode), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// AuthRequestByID mocks base method
|
||||
func (m *MockStorage) AuthRequestByID(arg0 string) (*oidc.AuthRequest, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AuthRequestByID", arg0)
|
||||
ret0, _ := ret[0].(*oidc.AuthRequest)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AuthRequestByID indicates an expected call of AuthRequestByID
|
||||
func (mr *MockStorageMockRecorder) AuthRequestByID(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthRequestByID", reflect.TypeOf((*MockStorage)(nil).AuthRequestByID), arg0)
|
||||
}
|
||||
|
||||
// AuthorizeClientIDCodeVerifier mocks base method
|
||||
func (m *MockStorage) AuthorizeClientIDCodeVerifier(arg0, arg1 string) (oidc.Client, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
|
@ -4,30 +4,29 @@ import (
|
|||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
u "github.com/caos/oidc/pkg/op/u"
|
||||
)
|
||||
|
||||
func NewStorage(t *testing.T) op.Storage {
|
||||
func NewStorage(t *testing.T) u.Storage {
|
||||
return NewMockStorage(gomock.NewController(t))
|
||||
}
|
||||
|
||||
func NewMockStorageExpectValidClientID(t *testing.T) op.Storage {
|
||||
func NewMockStorageExpectValidClientID(t *testing.T) u.Storage {
|
||||
m := NewStorage(t)
|
||||
ExpectValidClientID(m)
|
||||
return m
|
||||
}
|
||||
|
||||
func NewMockStorageExpectInvalidClientID(t *testing.T) op.Storage {
|
||||
func NewMockStorageExpectInvalidClientID(t *testing.T) u.Storage {
|
||||
m := NewStorage(t)
|
||||
ExpectInvalidClientID(m)
|
||||
return m
|
||||
}
|
||||
|
||||
func NewMockStorageAny(t *testing.T) op.Storage {
|
||||
func NewMockStorageAny(t *testing.T) u.Storage {
|
||||
m := NewStorage(t)
|
||||
mockS := m.(*MockStorage)
|
||||
mockS.EXPECT().GetClientByClientID(gomock.Any()).AnyTimes().Return(&ConfClient{}, nil)
|
||||
|
@ -35,12 +34,12 @@ func NewMockStorageAny(t *testing.T) op.Storage {
|
|||
return m
|
||||
}
|
||||
|
||||
func ExpectInvalidClientID(s op.Storage) {
|
||||
func ExpectInvalidClientID(s u.Storage) {
|
||||
mockS := s.(*MockStorage)
|
||||
mockS.EXPECT().GetClientByClientID(gomock.Any()).Return(nil, errors.New("client not found"))
|
||||
}
|
||||
|
||||
func ExpectValidClientID(s op.Storage) {
|
||||
func ExpectValidClientID(s u.Storage) {
|
||||
mockS := s.(*MockStorage)
|
||||
mockS.EXPECT().GetClientByClientID(gomock.Any()).DoAndReturn(
|
||||
func(id string) (oidc.Client, error) {
|
||||
|
|
25
pkg/op/op.go
25
pkg/op/op.go
|
@ -2,7 +2,10 @@ package op
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
|
@ -22,6 +25,28 @@ type OpenIDProvider interface {
|
|||
HttpHandler() *http.Server
|
||||
}
|
||||
|
||||
func ValidateIssuer(issuer string) error {
|
||||
if issuer == "" {
|
||||
return errors.New("missing issuer")
|
||||
}
|
||||
u, err := url.Parse(issuer)
|
||||
if err != nil {
|
||||
return errors.New("invalid url for issuer")
|
||||
}
|
||||
if u.Host == "" {
|
||||
return errors.New("host for issuer missing")
|
||||
}
|
||||
if u.Scheme != "https" {
|
||||
if !(u.Scheme == "http" && (u.Host == "localhost" || u.Host == "127.0.0.1" || u.Host == "::1" || strings.HasPrefix(u.Host, "localhost:"))) { //TODO: ?
|
||||
return errors.New("scheme for issuer must be `https`")
|
||||
}
|
||||
}
|
||||
if u.Fragment != "" || len(u.Query()) > 0 {
|
||||
return errors.New("no fragments or query allowed for issuer")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateRouter(o OpenIDProvider) *mux.Router {
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc(oidc.DiscoveryEndpoint, o.HandleDiscovery)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/caos/oidc/pkg/op/u"
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
|
||||
"github.com/gorilla/schema"
|
||||
|
@ -23,7 +24,7 @@ import (
|
|||
// return ParseTokenExchangeRequest(w, r)
|
||||
// }
|
||||
|
||||
func CodeExchange(w http.ResponseWriter, r *http.Request, storage Storage, decoder *schema.Decoder) {
|
||||
func CodeExchange(w http.ResponseWriter, r *http.Request, storage u.Storage, decoder *schema.Decoder) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
ExchangeRequestError(w, r, ErrInvalidRequest("error parsing form"))
|
||||
|
@ -78,11 +79,7 @@ func CreateAccessToken() (string, error) {
|
|||
return "accessToken", nil
|
||||
}
|
||||
|
||||
type Signer interface {
|
||||
Sign(claims *oidc.IDTokenClaims) (string, error)
|
||||
}
|
||||
|
||||
func CreateIDToken(authReq *oidc.AuthRequest, atHash string, signer Signer) (string, error) {
|
||||
func CreateIDToken(authReq *oidc.AuthRequest, atHash string, signer u.Signer) (string, error) {
|
||||
var issuer, sub, acr string
|
||||
var aud, amr []string
|
||||
var exp, iat, authTime time.Time
|
||||
|
@ -103,7 +100,7 @@ func CreateIDToken(authReq *oidc.AuthRequest, atHash string, signer Signer) (str
|
|||
return signer.Sign(claims)
|
||||
}
|
||||
|
||||
func AuthorizeClient(r *http.Request, tokenReq *oidc.AccessTokenRequest, storage Storage) (oidc.Client, error) {
|
||||
func AuthorizeClient(r *http.Request, tokenReq *oidc.AccessTokenRequest, storage u.Storage) (oidc.Client, error) {
|
||||
if tokenReq.ClientID == "" {
|
||||
clientID, clientSecret, ok := r.BasicAuth()
|
||||
if ok {
|
||||
|
@ -124,7 +121,7 @@ func ParseTokenExchangeRequest(w http.ResponseWriter, r *http.Request) (oidc.Tok
|
|||
return nil, errors.New("Unimplemented") //TODO: impl
|
||||
}
|
||||
|
||||
func ValidateTokenExchangeRequest(tokenReq oidc.TokenRequest, storage Storage) error {
|
||||
func ValidateTokenExchangeRequest(tokenReq oidc.TokenRequest, storage u.Storage) error {
|
||||
|
||||
return errors.New("Unimplemented") //TODO: impl
|
||||
}
|
||||
|
|
9
pkg/op/u/signer.go
Normal file
9
pkg/op/u/signer.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package u
|
||||
|
||||
import (
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
)
|
||||
|
||||
type Signer interface {
|
||||
Sign(claims *oidc.IDTokenClaims) (string, error)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package op
|
||||
package u
|
||||
|
||||
import "github.com/caos/oidc/pkg/oidc"
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue