userinfo and more
This commit is contained in:
parent
7210be8e4b
commit
85814fb69a
12 changed files with 702 additions and 134 deletions
|
@ -75,7 +75,7 @@ func (a *AuthRequest) GetNonce() string {
|
|||
}
|
||||
|
||||
func (a *AuthRequest) GetRedirectURI() string {
|
||||
return "https://op.certification.openid.net:62054/authz_cb"
|
||||
return a.RedirectURI
|
||||
// return "http://localhost:5556/auth/callback"
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ var (
|
|||
)
|
||||
|
||||
func (s *AuthStorage) CreateAuthRequest(authReq *oidc.AuthRequest) (op.AuthRequest, error) {
|
||||
a = &AuthRequest{ID: "id", ClientID: authReq.ClientID, ResponseType: authReq.ResponseType, Nonce: authReq.Nonce}
|
||||
a = &AuthRequest{ID: "id", ClientID: authReq.ClientID, ResponseType: authReq.ResponseType, Nonce: authReq.Nonce, RedirectURI: authReq.RedirectURI}
|
||||
return a, nil
|
||||
}
|
||||
func (s *OPStorage) GetClientByClientID(id string) (op.Client, error) {
|
||||
|
@ -134,21 +134,7 @@ func (s *AuthStorage) DeleteAuthRequestAndCode(string, string) error {
|
|||
return nil
|
||||
}
|
||||
func (s *AuthStorage) AuthRequestByID(id string) (op.AuthRequest, error) {
|
||||
if id == "none" {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
var responseType oidc.ResponseType
|
||||
if id == "code" {
|
||||
responseType = oidc.ResponseTypeCode
|
||||
} else if id == "id" {
|
||||
responseType = oidc.ResponseTypeIDTokenOnly
|
||||
} else {
|
||||
responseType = oidc.ResponseTypeIDToken
|
||||
}
|
||||
return &AuthRequest{
|
||||
ResponseType: responseType,
|
||||
RedirectURI: "/callback",
|
||||
}, nil
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (s *AuthStorage) GetSigningKey() (*jose.SigningKey, error) {
|
||||
|
@ -166,6 +152,49 @@ func (s *AuthStorage) GetKeySet() (jose.JSONWebKeySet, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *OPStorage) GetUserinfoFromScopes([]string) (interface{}, error) {
|
||||
return &oidc.Test{
|
||||
Userinfo: oidc.Userinfo{
|
||||
Subject: a.GetSubject(),
|
||||
Address: &oidc.UserinfoAddress{
|
||||
StreetAddress: "Hjkhkj 789\ndsf",
|
||||
},
|
||||
UserinfoEmail: oidc.UserinfoEmail{
|
||||
Email: "test",
|
||||
EmailVerified: true,
|
||||
},
|
||||
UserinfoPhone: oidc.UserinfoPhone{
|
||||
PhoneNumber: "sadsa",
|
||||
PhoneNumberVerified: true,
|
||||
},
|
||||
UserinfoProfile: oidc.UserinfoProfile{
|
||||
UpdatedAt: time.Now(),
|
||||
},
|
||||
// Claims: map[string]interface{}{
|
||||
// "test": "test",
|
||||
// "hkjh": "",
|
||||
// },
|
||||
},
|
||||
Add: "jkhnkj",
|
||||
}, nil
|
||||
}
|
||||
|
||||
type info struct {
|
||||
Subject string
|
||||
}
|
||||
|
||||
func (i *info) GetSubject() string {
|
||||
return i.Subject
|
||||
}
|
||||
|
||||
func (i *info) Claims() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"hodor": "hoidoir",
|
||||
"email": "asdfd",
|
||||
"emailVerfied": true,
|
||||
}
|
||||
}
|
||||
|
||||
type ConfClient struct {
|
||||
applicationType op.ApplicationType
|
||||
}
|
||||
|
@ -177,8 +206,8 @@ func (c *ConfClient) RedirectURIs() []string {
|
|||
"http://localhost:5556/auth/callback",
|
||||
"custom://callback",
|
||||
"https://localhost:8443/test/a/instructions-example/callback",
|
||||
"https://op.certification.openid.net:62054/authz_cb",
|
||||
"https://op.certification.openid.net:62054/authz_post",
|
||||
"https://op.certification.openid.net:62064/authz_cb",
|
||||
"https://op.certification.openid.net:62064/authz_post",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
233
pkg/oidc/userinfo.go
Normal file
233
pkg/oidc/userinfo.go
Normal file
|
@ -0,0 +1,233 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Test struct {
|
||||
Userinfo
|
||||
Add string `json:"add,omitempty"`
|
||||
}
|
||||
|
||||
type Userinfo struct {
|
||||
Subject string
|
||||
Address *UserinfoAddress
|
||||
UserinfoProfile
|
||||
UserinfoEmail
|
||||
UserinfoPhone
|
||||
|
||||
claims map[string]interface{}
|
||||
}
|
||||
|
||||
// type UserinfoJSON struct {
|
||||
// Subject string `json:"subject,omitempty"`
|
||||
// Address *UserinfoAddress `json:"address,omitempty"`
|
||||
// Email string `json:"email,omitempty"`
|
||||
// EmailVerified bool `json:"email_verified,omitempty"`
|
||||
// UserinfoProfileJSON
|
||||
// PhoneNumber string `json:"phone_number,omitempty"`
|
||||
// PhoneNumberVerified bool `json:"phone_number_verified,omitempty"`
|
||||
|
||||
// Claims map[string]interface{} `json:",omitempty"`
|
||||
// }
|
||||
|
||||
// type Claims map[string]interface{}
|
||||
|
||||
type UserinfoPhone struct {
|
||||
PhoneNumber string
|
||||
PhoneNumberVerified bool
|
||||
}
|
||||
type UserinfoProfile struct {
|
||||
Name string
|
||||
GivenName string
|
||||
FamilyName string
|
||||
MiddleName string
|
||||
Nickname string
|
||||
Profile string
|
||||
Picture string
|
||||
Website string
|
||||
Gender Gender
|
||||
Birthdate string
|
||||
Zoneinfo string
|
||||
// Locale language.Tag
|
||||
UpdatedAt time.Time
|
||||
PreferredUsername string
|
||||
}
|
||||
|
||||
// func (i *UserinfoProfile) MarshalJSON() ([]byte, error) {
|
||||
// j := new(UserinfoProfileJSON)
|
||||
// j.UpdatedAt = i.UpdatedAt
|
||||
// return json.Marshal(j)
|
||||
// }
|
||||
|
||||
type UserinfoProfileJSON struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
GivenName string `json:"given_name,omitempty"`
|
||||
FamilyName string `json:"family_name,omitempty"`
|
||||
MiddleName string `json:"middle_name,omitempty"`
|
||||
Nickname string `json:"nickname,omitempty"`
|
||||
Profile string `json:"profile,omitempty"`
|
||||
Picture string `json:"picture,omitempty"`
|
||||
Website string `json:"website,omitempty"`
|
||||
Gender Gender `json:"gender,omitempty"`
|
||||
Birthdate string `json:"birthdate,omitempty"`
|
||||
Zoneinfo string `json:"zoneinfo,omitempty"`
|
||||
// Locale language.Tag `json:"locale,omitempty"`
|
||||
UpdatedAt int64 `json:"updated_at,omitempty"`
|
||||
PreferredUsername string `json:"preferred_username,omitempty"`
|
||||
}
|
||||
|
||||
type Gender string
|
||||
|
||||
type UserinfoAddress struct {
|
||||
Formatted string
|
||||
StreetAddress string
|
||||
Locality string
|
||||
Region string
|
||||
PostalCode string
|
||||
Country string
|
||||
}
|
||||
|
||||
type UserinfoEmail struct {
|
||||
Email string
|
||||
EmailVerified bool
|
||||
}
|
||||
|
||||
func marshalUserinfoProfile(i UserinfoProfile, claims map[string]interface{}) {
|
||||
claims["updated_at"] = i.UpdatedAt.UTC().Unix()
|
||||
}
|
||||
|
||||
func marshalUserinfoEmail(i UserinfoEmail, claims map[string]interface{}) {
|
||||
if i.Email != "" {
|
||||
claims["email"] = i.Email
|
||||
}
|
||||
if i.EmailVerified {
|
||||
claims["email_verified"] = i.EmailVerified
|
||||
}
|
||||
}
|
||||
|
||||
func marshalUserinfoAddress(i *UserinfoAddress, claims map[string]interface{}) {
|
||||
if i == nil {
|
||||
return
|
||||
}
|
||||
address := make(map[string]interface{})
|
||||
if i.Formatted != "" {
|
||||
address["formatted"] = i.Formatted
|
||||
}
|
||||
if i.StreetAddress != "" {
|
||||
address["street_address"] = i.StreetAddress
|
||||
}
|
||||
claims["address"] = address
|
||||
// claims["email_verified"] = i.EmailVerified
|
||||
}
|
||||
|
||||
func marshalUserinfoPhone(i UserinfoPhone, claims map[string]interface{}) {
|
||||
claims["phone_number"] = i.PhoneNumber
|
||||
claims["phone_number_verified"] = i.PhoneNumberVerified
|
||||
}
|
||||
|
||||
// func copyClaims(j *Claims, i map[string]interface{}) {
|
||||
// // *j, _ = json.Marshal(i)
|
||||
// }
|
||||
|
||||
// func (p Userinfo) MarshalJSON() ([]byte, error) {
|
||||
// j := new(UserinfoJSON)
|
||||
// j.Subject = p.Subject
|
||||
// b, _ := json.Marshal(j)
|
||||
|
||||
// var m map[string]json.RawMessage
|
||||
// json.Unmarshal(b, &m)
|
||||
|
||||
// // Add tags to the map, possibly overriding struct fields
|
||||
// // for k, v := range p.Claims {
|
||||
// // // if overriding struct fields is not acceptable:
|
||||
// // // if _, ok := m[k]; ok { continue }
|
||||
// // b, _ = json.Marshal(v)
|
||||
// // ms[k] = json.RawMessage(b)
|
||||
// // }
|
||||
|
||||
// return json.Marshal(m)
|
||||
// }
|
||||
|
||||
func (i *Userinfo) MarshalJSON() ([]byte, error) {
|
||||
claims := i.claims
|
||||
if claims == nil {
|
||||
claims = make(map[string]interface{})
|
||||
}
|
||||
// j := new(UserinfoJSON)
|
||||
// j.Subject = i.Subject
|
||||
// j.Address = i.Address
|
||||
// j.Email = i.Email
|
||||
// j.EmailVerified = i.EmailVerified
|
||||
// j.PhoneNumber = i.PhoneNumber
|
||||
// j.PhoneNumberVerified = i.PhoneNumberVerified
|
||||
|
||||
// j.Claims = make(map[string]interface{})
|
||||
// claims := map[string]interface{}{
|
||||
// "sdsa": "jajfi",
|
||||
// "a23r": "",
|
||||
// }
|
||||
|
||||
// j.Claims["Sdsa"] = "sads"
|
||||
// j.Claims["3454"] = ""
|
||||
|
||||
// st := new(structpb.Struct)
|
||||
// b, _ := json.Marshal(j)
|
||||
// err := jsonpb.Unmarshal(bytes.NewReader(b), st)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// fmt.Println("st", st)
|
||||
// m := new(jsonpb.Marshaler)
|
||||
// m.EmitDefaults = false
|
||||
// s, _ := m.MarshalToString(st)
|
||||
// return []byte(s), nil
|
||||
|
||||
// claims["phone_number"] = i.PhoneNumber
|
||||
claims["sub"] = i.Subject
|
||||
marshalUserinfoAddress(i.Address, claims)
|
||||
marshalUserinfoEmail(i.UserinfoEmail, claims)
|
||||
marshalUserinfoPhone(i.UserinfoPhone, claims)
|
||||
marshalUserinfoProfile(i.UserinfoProfile, claims)
|
||||
|
||||
// for k, v := range claims {
|
||||
// j.Claims[k] = v
|
||||
// }
|
||||
// j.Claims = Claims(m)
|
||||
// copyClaims(&j.Claims, i.Claims)
|
||||
// j.Claims, _ = json.Marshal(i.Claims)
|
||||
|
||||
// j.Subject = i.Subject
|
||||
|
||||
// if j.Claims == nil {
|
||||
// j.Claims = make(map[string]interface{})
|
||||
// }
|
||||
// j.Claims["sub"] = i.Subject
|
||||
// if i.Address != nil {
|
||||
// j.Claims["address"] = i.Address
|
||||
// }
|
||||
// if i.Email != "" {
|
||||
// j.Claims["email"] = i.Email
|
||||
// }
|
||||
// if i.EmailVerified {
|
||||
// j.Claims["email_verified"] = i.EmailVerified
|
||||
// }
|
||||
// if i.PhoneNumber != "" {
|
||||
// j.Claims["phone_number"] = i.PhoneNumber
|
||||
// }
|
||||
// if i.PhoneNumberVerified {
|
||||
// j.Claims["phone_number_verified"] = i.PhoneNumberVerified
|
||||
// }
|
||||
// if !i.UpdatedAt.IsZero() {
|
||||
// j.Claims["updated_at"] = i.UpdatedAt.UTC().Unix()
|
||||
// }
|
||||
return json.Marshal(claims)
|
||||
}
|
||||
|
||||
func (i *Userinfo) UnmmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, i); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, i.claims)
|
||||
}
|
|
@ -14,7 +14,6 @@ type Configuration interface {
|
|||
KeysEndpoint() Endpoint
|
||||
|
||||
// SupportedScopes() []string
|
||||
AuthMethodBasicSupported() bool
|
||||
AuthMethodPostSupported() bool
|
||||
|
||||
Port() string
|
||||
|
|
|
@ -16,8 +16,8 @@ const (
|
|||
defaultUserinfoEndpoint = "userinfo"
|
||||
defaultKeysEndpoint = "keys"
|
||||
|
||||
authMethodBasic = "client_secret_basic"
|
||||
authMethodPost = "client_secret_post"
|
||||
AuthMethodBasic = "client_secret_basic"
|
||||
AuthMethodPost = "client_secret_post"
|
||||
|
||||
DefaultIDTokenValidity = time.Duration(5 * time.Minute)
|
||||
)
|
||||
|
@ -251,5 +251,5 @@ func (p *DefaultOP) handleTokenExchange(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
|
||||
func (p *DefaultOP) HandleUserinfo(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("ok"))
|
||||
Userinfo(w, r, p)
|
||||
}
|
||||
|
|
|
@ -20,27 +20,38 @@ func CreateDiscoveryConfig(c Configuration, s Signer) *oidc.DiscoveryConfigurati
|
|||
UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()),
|
||||
// EndSessionEndpoint: c.TokenEndpoint().Absolute(c.Issuer())(c.EndSessionEndpoint),
|
||||
// CheckSessionIframe: c.TokenEndpoint().Absolute(c.Issuer())(c.CheckSessionIframe),
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
ScopesSupported: scopes(c),
|
||||
ResponseTypesSupported: responseTypes(c),
|
||||
GrantTypesSupported: grantTypes(c),
|
||||
// ClaimsSupported: oidc.SupportedClaims,
|
||||
IDTokenSigningAlgValuesSupported: sigAlgorithms(s),
|
||||
SubjectTypesSupported: subjectTypes(c),
|
||||
TokenEndpointAuthMethodsSupported: authMethods(c.AuthMethodBasicSupported(), c.AuthMethodPostSupported()),
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
ScopesSupported: Scopes(c),
|
||||
ResponseTypesSupported: ResponseTypes(c),
|
||||
GrantTypesSupported: GrantTypes(c),
|
||||
ClaimsSupported: SupportedClaims(c),
|
||||
IDTokenSigningAlgValuesSupported: SigAlgorithms(s),
|
||||
SubjectTypesSupported: SubjectTypes(c),
|
||||
TokenEndpointAuthMethodsSupported: AuthMethods(c),
|
||||
}
|
||||
}
|
||||
|
||||
func scopes(c Configuration) []string {
|
||||
return []string{
|
||||
"openid",
|
||||
"profile",
|
||||
"email",
|
||||
"phone",
|
||||
} //TODO: config
|
||||
const (
|
||||
ScopeOpenID = "openid"
|
||||
ScopeProfile = "profile"
|
||||
ScopeEmail = "email"
|
||||
ScopePhone = "phone"
|
||||
ScopeAddress = "address"
|
||||
)
|
||||
|
||||
var DefaultSupportedScopes = []string{
|
||||
ScopeOpenID,
|
||||
ScopeProfile,
|
||||
ScopeEmail,
|
||||
ScopePhone,
|
||||
ScopeAddress,
|
||||
}
|
||||
|
||||
func responseTypes(c Configuration) []string {
|
||||
func Scopes(c Configuration) []string {
|
||||
return DefaultSupportedScopes //TODO: config
|
||||
}
|
||||
|
||||
func ResponseTypes(c Configuration) []string {
|
||||
return []string{
|
||||
"code",
|
||||
"id_token",
|
||||
|
@ -51,7 +62,7 @@ func responseTypes(c Configuration) []string {
|
|||
}
|
||||
}
|
||||
|
||||
func grantTypes(c Configuration) []string {
|
||||
func GrantTypes(c Configuration) []string {
|
||||
return []string{
|
||||
"client_credentials",
|
||||
"authorization_code",
|
||||
|
@ -60,23 +71,49 @@ func grantTypes(c Configuration) []string {
|
|||
}
|
||||
}
|
||||
|
||||
func sigAlgorithms(s Signer) []string {
|
||||
func SupportedClaims(c Configuration) []string {
|
||||
return []string{ //TODO: config
|
||||
"sub",
|
||||
"aud",
|
||||
"exp",
|
||||
"iat",
|
||||
"iss",
|
||||
"auth_time",
|
||||
"nonce",
|
||||
"acr",
|
||||
"amr",
|
||||
"c_hash",
|
||||
"at_hash",
|
||||
"act",
|
||||
"scopes",
|
||||
"client_id",
|
||||
"azp",
|
||||
"preferred_username",
|
||||
"name",
|
||||
"family_name",
|
||||
"given_name",
|
||||
"locale",
|
||||
"email",
|
||||
"email_verified",
|
||||
"phone_number",
|
||||
"phone_number_verified",
|
||||
}
|
||||
}
|
||||
|
||||
func SigAlgorithms(s Signer) []string {
|
||||
return []string{string(s.SignatureAlgorithm())}
|
||||
}
|
||||
|
||||
func subjectTypes(c Configuration) []string {
|
||||
func SubjectTypes(c Configuration) []string {
|
||||
return []string{"public"} //TODO: config
|
||||
}
|
||||
|
||||
func authMethods(basic, post bool) []string {
|
||||
authMethods := make([]string, 0, 2)
|
||||
if basic {
|
||||
// if c.AuthMethodBasicSupported() {
|
||||
authMethods = append(authMethods, authMethodBasic)
|
||||
func AuthMethods(c Configuration) []string {
|
||||
authMethods := []string{
|
||||
AuthMethodBasic,
|
||||
}
|
||||
if post {
|
||||
// if c.AuthMethodPostSupported() {
|
||||
authMethods = append(authMethods, authMethodPost)
|
||||
if c.AuthMethodPostSupported() {
|
||||
authMethods = append(authMethods, AuthMethodPost)
|
||||
}
|
||||
return authMethods
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package op
|
||||
package op_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -6,9 +6,12 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
"github.com/caos/oidc/pkg/op/mock"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
func TestDiscover(t *testing.T) {
|
||||
|
@ -30,7 +33,7 @@ func TestDiscover(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
Discover(tt.args.w, tt.args.config)
|
||||
op.Discover(tt.args.w, tt.args.config)
|
||||
rec := tt.args.w.(*httptest.ResponseRecorder)
|
||||
require.Equal(t, http.StatusOK, rec.Code)
|
||||
require.Equal(t, `{"issuer":"https://issuer.com"}`, rec.Body.String())
|
||||
|
@ -40,8 +43,8 @@ func TestDiscover(t *testing.T) {
|
|||
|
||||
func TestCreateDiscoveryConfig(t *testing.T) {
|
||||
type args struct {
|
||||
c Configuration
|
||||
s Signer
|
||||
c op.Configuration
|
||||
s op.Signer
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -52,7 +55,7 @@ func TestCreateDiscoveryConfig(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := CreateDiscoveryConfig(tt.args.c, tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := op.CreateDiscoveryConfig(tt.args.c, tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("CreateDiscoveryConfig() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
@ -61,27 +64,31 @@ func TestCreateDiscoveryConfig(t *testing.T) {
|
|||
|
||||
func Test_scopes(t *testing.T) {
|
||||
type args struct {
|
||||
c Configuration
|
||||
c op.Configuration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
{
|
||||
"default Scopes",
|
||||
args{},
|
||||
op.DefaultSupportedScopes,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := scopes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := op.Scopes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("scopes() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_responseTypes(t *testing.T) {
|
||||
func Test_ResponseTypes(t *testing.T) {
|
||||
type args struct {
|
||||
c Configuration
|
||||
c op.Configuration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -92,16 +99,16 @@ func Test_responseTypes(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := responseTypes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := op.ResponseTypes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("responseTypes() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_grantTypes(t *testing.T) {
|
||||
func Test_GrantTypes(t *testing.T) {
|
||||
type args struct {
|
||||
c Configuration
|
||||
c op.Configuration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -112,64 +119,64 @@ func Test_grantTypes(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := grantTypes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := op.GrantTypes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("grantTypes() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// func Test_sigAlgorithms(t *testing.T) {
|
||||
// type args struct {
|
||||
// s Signer
|
||||
// }
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// args args
|
||||
// want []string
|
||||
// }{
|
||||
// {
|
||||
// "",
|
||||
// args{},
|
||||
// []string{"RS256"},
|
||||
// },
|
||||
// }
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// if got := sigAlgorithms(tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
||||
// t.Errorf("sigAlgorithms() = %v, want %v", got, tt.want)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func Test_subjectTypes(t *testing.T) {
|
||||
// type args struct {
|
||||
// c Configuration
|
||||
// }
|
||||
// tests := []struct {
|
||||
// name string
|
||||
// args args
|
||||
// want []string
|
||||
// }{
|
||||
// {
|
||||
// "none",
|
||||
// args{func()}
|
||||
// }
|
||||
// }
|
||||
// for _, tt := range tests {
|
||||
// t.Run(tt.name, func(t *testing.T) {
|
||||
// if got := subjectTypes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
// t.Errorf("subjectTypes() = %v, want %v", got, tt.want)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
func Test_authMethods(t *testing.T) {
|
||||
func TestSupportedClaims(t *testing.T) {
|
||||
type args struct {
|
||||
basic bool
|
||||
post bool
|
||||
c op.Configuration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := op.SupportedClaims(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("SupportedClaims() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_SigAlgorithms(t *testing.T) {
|
||||
m := mock.NewMockSigner(gomock.NewController((t)))
|
||||
type args struct {
|
||||
s op.Signer
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
"",
|
||||
args{func() op.Signer {
|
||||
m.EXPECT().SignatureAlgorithm().Return(jose.RS256)
|
||||
return m
|
||||
}()},
|
||||
[]string{"RS256"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := op.SigAlgorithms(tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("sigAlgorithms() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_SubjectTypes(t *testing.T) {
|
||||
type args struct {
|
||||
c op.Configuration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -178,28 +185,49 @@ func Test_authMethods(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
"none",
|
||||
args{false, false},
|
||||
[]string{},
|
||||
},
|
||||
{
|
||||
"basic",
|
||||
args{true, false},
|
||||
[]string{authMethodBasic},
|
||||
},
|
||||
{
|
||||
"post",
|
||||
args{false, true},
|
||||
[]string{authMethodPost},
|
||||
},
|
||||
{
|
||||
"basic and post",
|
||||
args{true, true},
|
||||
[]string{authMethodBasic, authMethodPost},
|
||||
args{},
|
||||
[]string{"public"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := authMethods(tt.args.basic, tt.args.post); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := op.SubjectTypes(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("subjectTypes() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_AuthMethods(t *testing.T) {
|
||||
m := mock.NewMockConfiguration(gomock.NewController((t)))
|
||||
type args struct {
|
||||
c op.Configuration
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
"imlicit basic",
|
||||
args{func() op.Configuration {
|
||||
m.EXPECT().AuthMethodPostSupported().Return(false)
|
||||
return m
|
||||
}()},
|
||||
[]string{op.AuthMethodBasic},
|
||||
},
|
||||
{
|
||||
"basic and post",
|
||||
args{func() op.Configuration {
|
||||
m.EXPECT().AuthMethodPostSupported().Return(true)
|
||||
return m
|
||||
}()},
|
||||
[]string{op.AuthMethodBasic, op.AuthMethodPost},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := op.AuthMethods(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("authMethods() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
|
132
pkg/op/mock/configuration.mock.go
Normal file
132
pkg/op/mock/configuration.mock.go
Normal file
|
@ -0,0 +1,132 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/caos/oidc/pkg/op (interfaces: Configuration)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
op "github.com/caos/oidc/pkg/op"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockConfiguration is a mock of Configuration interface
|
||||
type MockConfiguration struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockConfigurationMockRecorder
|
||||
}
|
||||
|
||||
// MockConfigurationMockRecorder is the mock recorder for MockConfiguration
|
||||
type MockConfigurationMockRecorder struct {
|
||||
mock *MockConfiguration
|
||||
}
|
||||
|
||||
// NewMockConfiguration creates a new mock instance
|
||||
func NewMockConfiguration(ctrl *gomock.Controller) *MockConfiguration {
|
||||
mock := &MockConfiguration{ctrl: ctrl}
|
||||
mock.recorder = &MockConfigurationMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockConfiguration) EXPECT() *MockConfigurationMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AuthMethodPostSupported mocks base method
|
||||
func (m *MockConfiguration) AuthMethodPostSupported() bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AuthMethodPostSupported")
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AuthMethodPostSupported indicates an expected call of AuthMethodPostSupported
|
||||
func (mr *MockConfigurationMockRecorder) AuthMethodPostSupported() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthMethodPostSupported", reflect.TypeOf((*MockConfiguration)(nil).AuthMethodPostSupported))
|
||||
}
|
||||
|
||||
// AuthorizationEndpoint mocks base method
|
||||
func (m *MockConfiguration) AuthorizationEndpoint() op.Endpoint {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AuthorizationEndpoint")
|
||||
ret0, _ := ret[0].(op.Endpoint)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AuthorizationEndpoint indicates an expected call of AuthorizationEndpoint
|
||||
func (mr *MockConfigurationMockRecorder) AuthorizationEndpoint() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthorizationEndpoint", reflect.TypeOf((*MockConfiguration)(nil).AuthorizationEndpoint))
|
||||
}
|
||||
|
||||
// Issuer mocks base method
|
||||
func (m *MockConfiguration) Issuer() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Issuer")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Issuer indicates an expected call of Issuer
|
||||
func (mr *MockConfigurationMockRecorder) Issuer() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Issuer", reflect.TypeOf((*MockConfiguration)(nil).Issuer))
|
||||
}
|
||||
|
||||
// KeysEndpoint mocks base method
|
||||
func (m *MockConfiguration) KeysEndpoint() op.Endpoint {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "KeysEndpoint")
|
||||
ret0, _ := ret[0].(op.Endpoint)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// KeysEndpoint indicates an expected call of KeysEndpoint
|
||||
func (mr *MockConfigurationMockRecorder) KeysEndpoint() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeysEndpoint", reflect.TypeOf((*MockConfiguration)(nil).KeysEndpoint))
|
||||
}
|
||||
|
||||
// Port mocks base method
|
||||
func (m *MockConfiguration) Port() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Port")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Port indicates an expected call of Port
|
||||
func (mr *MockConfigurationMockRecorder) Port() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Port", reflect.TypeOf((*MockConfiguration)(nil).Port))
|
||||
}
|
||||
|
||||
// TokenEndpoint mocks base method
|
||||
func (m *MockConfiguration) TokenEndpoint() op.Endpoint {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "TokenEndpoint")
|
||||
ret0, _ := ret[0].(op.Endpoint)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// TokenEndpoint indicates an expected call of TokenEndpoint
|
||||
func (mr *MockConfigurationMockRecorder) TokenEndpoint() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TokenEndpoint", reflect.TypeOf((*MockConfiguration)(nil).TokenEndpoint))
|
||||
}
|
||||
|
||||
// UserinfoEndpoint mocks base method
|
||||
func (m *MockConfiguration) UserinfoEndpoint() op.Endpoint {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UserinfoEndpoint")
|
||||
ret0, _ := ret[0].(op.Endpoint)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UserinfoEndpoint indicates an expected call of UserinfoEndpoint
|
||||
func (mr *MockConfigurationMockRecorder) UserinfoEndpoint() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserinfoEndpoint", reflect.TypeOf((*MockConfiguration)(nil).UserinfoEndpoint))
|
||||
}
|
|
@ -3,3 +3,5 @@ package mock
|
|||
//go:generate mockgen -package mock -destination ./storage.mock.go github.com/caos/oidc/pkg/op Storage
|
||||
//go:generate mockgen -package mock -destination ./authorizer.mock.go github.com/caos/oidc/pkg/op Authorizer
|
||||
//go:generate mockgen -package mock -destination ./client.mock.go github.com/caos/oidc/pkg/op Client
|
||||
//go:generate mockgen -package mock -destination ./configuration.mock.go github.com/caos/oidc/pkg/op Configuration
|
||||
//go:generate mockgen -package mock -destination ./signer.mock.go github.com/caos/oidc/pkg/op Signer
|
||||
|
|
64
pkg/op/mock/signer.mock.go
Normal file
64
pkg/op/mock/signer.mock.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/caos/oidc/pkg/op (interfaces: Signer)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
oidc "github.com/caos/oidc/pkg/oidc"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
go_jose_v2 "gopkg.in/square/go-jose.v2"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockSigner is a mock of Signer interface
|
||||
type MockSigner struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockSignerMockRecorder
|
||||
}
|
||||
|
||||
// MockSignerMockRecorder is the mock recorder for MockSigner
|
||||
type MockSignerMockRecorder struct {
|
||||
mock *MockSigner
|
||||
}
|
||||
|
||||
// NewMockSigner creates a new mock instance
|
||||
func NewMockSigner(ctrl *gomock.Controller) *MockSigner {
|
||||
mock := &MockSigner{ctrl: ctrl}
|
||||
mock.recorder = &MockSignerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (m *MockSigner) EXPECT() *MockSignerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// SignIDToken mocks base method
|
||||
func (m *MockSigner) SignIDToken(arg0 *oidc.IDTokenClaims) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SignIDToken", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SignIDToken indicates an expected call of SignIDToken
|
||||
func (mr *MockSignerMockRecorder) SignIDToken(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SignIDToken", reflect.TypeOf((*MockSigner)(nil).SignIDToken), arg0)
|
||||
}
|
||||
|
||||
// SignatureAlgorithm mocks base method
|
||||
func (m *MockSigner) SignatureAlgorithm() go_jose_v2.SignatureAlgorithm {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SignatureAlgorithm")
|
||||
ret0, _ := ret[0].(go_jose_v2.SignatureAlgorithm)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SignatureAlgorithm indicates an expected call of SignatureAlgorithm
|
||||
func (mr *MockSignerMockRecorder) SignatureAlgorithm() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SignatureAlgorithm", reflect.TypeOf((*MockSigner)(nil).SignatureAlgorithm))
|
||||
}
|
|
@ -168,3 +168,18 @@ func (mr *MockStorageMockRecorder) GetSigningKey() *gomock.Call {
|
|||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSigningKey", reflect.TypeOf((*MockStorage)(nil).GetSigningKey))
|
||||
}
|
||||
|
||||
// GetUserinfoFromScopes mocks base method
|
||||
func (m *MockStorage) GetUserinfoFromScopes(arg0 []string) (*oidc.Userinfo, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserinfoFromScopes", arg0)
|
||||
ret0, _ := ret[0].(*oidc.Userinfo)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserinfoFromScopes indicates an expected call of GetUserinfoFromScopes
|
||||
func (mr *MockStorageMockRecorder) GetUserinfoFromScopes(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserinfoFromScopes", reflect.TypeOf((*MockStorage)(nil).GetUserinfoFromScopes), arg0)
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ type OPStorage interface {
|
|||
GetClientByClientID(string) (Client, error)
|
||||
AuthorizeClientIDSecret(string, string) (Client, error)
|
||||
AuthorizeClientIDCodeVerifier(string, string) (Client, error)
|
||||
GetUserinfoFromScopes([]string) (*oidc.Userinfo, error)
|
||||
}
|
||||
|
||||
type Storage interface {
|
||||
|
|
28
pkg/op/userinfo.go
Normal file
28
pkg/op/userinfo.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package op
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
)
|
||||
|
||||
type UserinfoProvider interface {
|
||||
Storage() Storage
|
||||
}
|
||||
|
||||
func Userinfo(w http.ResponseWriter, r *http.Request, userinfoProvider UserinfoProvider) {
|
||||
scopes, err := ScopesFromAccessToken(w, r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
info, err := userinfoProvider.Storage().GetUserinfoFromScopes(scopes)
|
||||
if err != nil {
|
||||
utils.MarshalJSON(w, err)
|
||||
return
|
||||
}
|
||||
utils.MarshalJSON(w, info)
|
||||
}
|
||||
|
||||
func ScopesFromAccessToken(w http.ResponseWriter, r *http.Request) ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue