feat(login): use new IDP templates (#5315)

The login uses the new template based IDPs with backwards compatibility for old IDPs
This commit is contained in:
Livio Spring
2023-02-28 21:20:58 +01:00
committed by GitHub
parent abacb6c5aa
commit 48f9815b7c
62 changed files with 1254 additions and 2165 deletions

View File

@@ -18,14 +18,14 @@ type Provider struct {
}
// New creates a GitLab.com provider using the [oidc.Provider] (OIDC generic provider)
func New(clientID, clientSecret, redirectURI string, options ...oidc.ProviderOpts) (*Provider, error) {
return NewCustomIssuer(name, issuer, clientID, clientSecret, redirectURI, options...)
func New(clientID, clientSecret, redirectURI string, scopes []string, options ...oidc.ProviderOpts) (*Provider, error) {
return NewCustomIssuer(name, issuer, clientID, clientSecret, redirectURI, scopes, options...)
}
// NewCustomIssuer creates a GitLab provider using the [oidc.Provider] (OIDC generic provider)
// with a custom issuer for self-managed instances
func NewCustomIssuer(name, issuer, clientID, clientSecret, redirectURI string, options ...oidc.ProviderOpts) (*Provider, error) {
rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, oidc.DefaultMapper, options...)
func NewCustomIssuer(name, issuer, clientID, clientSecret, redirectURI string, scopes []string, options ...oidc.ProviderOpts) (*Provider, error) {
rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, scopes, oidc.DefaultMapper, options...)
if err != nil {
return nil, err
}

View File

@@ -16,6 +16,7 @@ func TestProvider_BeginAuth(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
opts []oidc.ProviderOpts
}
tests := []struct {
@@ -29,6 +30,7 @@ func TestProvider_BeginAuth(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
},
want: &oidc.Session{
AuthURL: "https://gitlab.com/oauth/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState",
@@ -40,7 +42,7 @@ func TestProvider_BeginAuth(t *testing.T) {
a := assert.New(t)
r := require.New(t)
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.opts...)
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.opts...)
r.NoError(err)
session, err := provider.BeginAuth(context.Background(), "testState")

View File

@@ -22,6 +22,7 @@ func TestProvider_FetchUser(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
httpMock func()
authURL string
code string
@@ -55,6 +56,7 @@ func TestProvider_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
httpMock: func() {
gock.New("https://gitlab.com/oauth").
Get("/userinfo").
@@ -74,6 +76,7 @@ func TestProvider_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
httpMock: func() {
gock.New("https://gitlab.com/oauth").
Get("/userinfo").
@@ -110,6 +113,7 @@ func TestProvider_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
httpMock: func() {
gock.New("https://gitlab.com/oauth").
Get("/userinfo").
@@ -161,7 +165,7 @@ func TestProvider_FetchUser(t *testing.T) {
// call the real discovery endpoint
gock.New(issuer).Get(openid.DiscoveryEndpoint).EnableNetworking()
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.options...)
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.options...)
require.NoError(t, err)
session := &oidc.Session{

View File

@@ -20,8 +20,8 @@ type Provider struct {
}
// New creates a Google provider using the [oidc.Provider] (OIDC generic provider)
func New(clientID, clientSecret, redirectURI string, opts ...oidc.ProviderOpts) (*Provider, error) {
rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, userMapper, opts...)
func New(clientID, clientSecret, redirectURI string, scopes []string, opts ...oidc.ProviderOpts) (*Provider, error) {
rp, err := oidc.New(name, issuer, clientID, clientSecret, redirectURI, scopes, userMapper, opts...)
if err != nil {
return nil, err
}

View File

@@ -16,6 +16,7 @@ func TestProvider_BeginAuth(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
}
tests := []struct {
name string
@@ -28,6 +29,7 @@ func TestProvider_BeginAuth(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
},
want: &oidc.Session{
AuthURL: "https://accounts.google.com/o/oauth2/v2/auth?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState",
@@ -39,7 +41,7 @@ func TestProvider_BeginAuth(t *testing.T) {
a := assert.New(t)
r := require.New(t)
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI)
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes)
r.NoError(err)
session, err := provider.BeginAuth(context.Background(), "testState")

View File

@@ -22,6 +22,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
httpMock func()
authURL string
code string
@@ -55,6 +56,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
httpMock: func() {
gock.New("https://openidconnect.googleapis.com").
Get("/v1/userinfo").
@@ -74,6 +76,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
httpMock: func() {
gock.New("https://openidconnect.googleapis.com").
Get("/v1/userinfo").
@@ -110,6 +113,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
httpMock: func() {
gock.New("https://openidconnect.googleapis.com").
Get("/v1/userinfo").
@@ -162,7 +166,7 @@ func TestSession_FetchUser(t *testing.T) {
// call the real discovery endpoint
gock.New(issuer).Get(openid.DiscoveryEndpoint).EnableNetworking()
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI)
provider, err := New(tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes)
require.NoError(t, err)
session := &oidc.Session{

View File

@@ -18,7 +18,6 @@ const (
var _ idp.Provider = (*Provider)(nil)
var (
ErrNoTokens = errors.New("no tokens provided")
ErrMissingUserAgentID = errors.New("userAgentID missing")
)

View File

@@ -2,7 +2,13 @@ package jwt
import (
"context"
"errors"
"fmt"
"net/http"
"time"
"github.com/zitadel/logging"
"github.com/zitadel/oidc/v2/pkg/client/rp"
"github.com/zitadel/oidc/v2/pkg/oidc"
"golang.org/x/text/language"
@@ -11,8 +17,14 @@ import (
var _ idp.Session = (*Session)(nil)
var (
ErrNoTokens = errors.New("no tokens provided")
ErrInvalidToken = errors.New("invalid tokens provided")
)
// Session is the [idp.Session] implementation for the JWT provider
type Session struct {
*Provider
AuthURL string
Tokens *oidc.Tokens
}
@@ -28,9 +40,48 @@ func (s *Session) FetchUser(ctx context.Context) (user idp.User, err error) {
if s.Tokens == nil {
return nil, ErrNoTokens
}
s.Tokens.IDTokenClaims, err = s.validateToken(ctx, s.Tokens.IDToken)
if err != nil {
return nil, err
}
return &User{s.Tokens.IDTokenClaims}, nil
}
func (s *Session) validateToken(ctx context.Context, token string) (oidc.IDTokenClaims, error) {
logging.Debug("begin token validation")
// TODO: be able to specify them in the template: https://github.com/zitadel/zitadel/issues/5322
offset := 3 * time.Second
maxAge := time.Hour
claims := oidc.EmptyIDTokenClaims()
payload, err := oidc.ParseToken(token, claims)
if err != nil {
return nil, fmt.Errorf("%w: malformed jwt payload: %v", ErrInvalidToken, err)
}
if err = oidc.CheckIssuer(claims, s.Provider.issuer); err != nil {
return nil, fmt.Errorf("%w: invalid issuer: %v", ErrInvalidToken, err)
}
logging.Debug("begin signature validation")
keySet := rp.NewRemoteKeySet(http.DefaultClient, s.Provider.keysEndpoint)
if err = oidc.CheckSignature(ctx, token, payload, claims, nil, keySet); err != nil {
return nil, fmt.Errorf("%w: invalid signature: %v", ErrInvalidToken, err)
}
if !claims.GetExpiration().IsZero() {
if err = oidc.CheckExpiration(claims, offset); err != nil {
return nil, fmt.Errorf("%w: expired: %v", ErrInvalidToken, err)
}
}
if !claims.GetIssuedAt().IsZero() {
if err = oidc.CheckIssuedAt(claims, maxAge, offset); err != nil {
return nil, fmt.Errorf("%w: %v", ErrInvalidToken, err)
}
}
return claims, nil
}
type User struct {
oidc.IDTokenClaims
}

View File

@@ -2,25 +2,37 @@ package jwt
import (
"context"
"encoding/json"
"errors"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/h2non/gock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/oidc/v2/pkg/oidc"
"golang.org/x/oauth2"
"golang.org/x/text/language"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/zitadel/internal/idp"
"github.com/zitadel/zitadel/internal/crypto"
)
func TestSession_FetchUser(t *testing.T) {
type fields struct {
authURL string
tokens *oidc.Tokens
name string
issuer string
jwtEndpoint string
keysEndpoint string
headerName string
encryptionAlg func(t *testing.T) crypto.EncryptionAlgorithm
httpMock func(issuer string)
authURL string
tokens *oidc.Tokens
}
type want struct {
err func(error) bool
user idp.User
id string
firstName string
lastName string
@@ -41,8 +53,22 @@ func TestSession_FetchUser(t *testing.T) {
want want
}{
{
name: "no tokens",
fields: fields{},
name: "no tokens",
fields: fields{
issuer: "https://jwt.com",
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
httpMock: func(issuer string) {
gock.New(issuer).
Get("/keys").
Reply(200).
JSON(keys(t))
},
},
want: want{
err: func(err error) bool {
return errors.Is(err, ErrNoTokens)
@@ -50,11 +76,53 @@ func TestSession_FetchUser(t *testing.T) {
},
},
{
name: "successful fetch",
name: "invalid token",
fields: fields{
issuer: "https://jwt.com",
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
httpMock: func(issuer string) {
gock.New(issuer).
Get("/keys").
Reply(200).
JSON(keys(t))
},
authURL: "https://auth.com/jwt?authRequestID=testState",
tokens: &oidc.Tokens{
Token: &oauth2.Token{},
Token: &oauth2.Token{},
IDToken: "invalidToken",
},
},
want: want{
err: func(err error) bool {
return errors.Is(err, ErrInvalidToken)
},
},
},
{
name: "successful fetch",
fields: fields{
issuer: "https://jwt.com",
jwtEndpoint: "https://auth.com/jwt",
keysEndpoint: "https://jwt.com/keys",
headerName: "jwt-header",
encryptionAlg: func(t *testing.T) crypto.EncryptionAlgorithm {
return crypto.CreateMockEncryptionAlg(gomock.NewController(t))
},
httpMock: func(issuer string) {
gock.New(issuer).
Get("/keys").
Reply(200).
JSON(keys(t))
},
authURL: "https://auth.com/jwt?authRequestID=testState",
tokens: &oidc.Tokens{
Token: &oauth2.Token{},
IDToken: idToken(t, "https://jwt.com"),
IDTokenClaims: func() oidc.IDTokenClaims {
claims := oidc.EmptyIDTokenClaims()
userinfo := oidc.NewUserInfo()
@@ -75,25 +143,6 @@ func TestSession_FetchUser(t *testing.T) {
},
},
want: want{
user: &User{
IDTokenClaims: func() oidc.IDTokenClaims {
claims := oidc.EmptyIDTokenClaims()
userinfo := oidc.NewUserInfo()
userinfo.SetSubject("sub")
userinfo.SetPicture("picture")
userinfo.SetName("firstname lastname")
userinfo.SetEmail("email", true)
userinfo.SetGivenName("firstname")
userinfo.SetFamilyName("lastname")
userinfo.SetNickname("nickname")
userinfo.SetPreferredUsername("username")
userinfo.SetProfile("profile")
userinfo.SetPhone("phone", true)
userinfo.SetLocale(language.English)
claims.SetUserinfo(userinfo)
return claims
}(),
},
id: "sub",
firstName: "firstname",
lastName: "lastname",
@@ -112,11 +161,24 @@ func TestSession_FetchUser(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer gock.Off()
tt.fields.httpMock(tt.fields.issuer)
a := assert.New(t)
provider, err := New(
tt.fields.name,
tt.fields.issuer,
tt.fields.jwtEndpoint,
tt.fields.keysEndpoint,
tt.fields.headerName,
tt.fields.encryptionAlg(t),
)
require.NoError(t, err)
session := &Session{
AuthURL: tt.fields.authURL,
Tokens: tt.fields.tokens,
Provider: provider,
AuthURL: tt.fields.authURL,
Tokens: tt.fields.tokens,
}
user, err := session.FetchUser(context.Background())
@@ -125,7 +187,6 @@ func TestSession_FetchUser(t *testing.T) {
}
if tt.want.err == nil {
a.NoError(err)
a.Equal(tt.want.user, user)
a.Equal(tt.want.id, user.GetID())
a.Equal(tt.want.firstName, user.GetFirstName())
a.Equal(tt.want.lastName, user.GetLastName())
@@ -143,3 +204,96 @@ func TestSession_FetchUser(t *testing.T) {
})
}
}
func idToken(t *testing.T, issuer string) string {
claims := oidc.NewIDTokenClaims(
issuer,
"sub",
[]string{"clientID"},
time.Now().Add(1*time.Hour),
time.Now().Add(-1*time.Minute),
"",
"",
nil,
"clientID",
0,
)
info := oidc.NewUserInfo()
info.SetSubject("sub")
info.SetGivenName("firstname")
info.SetFamilyName("lastname")
info.SetName("firstname lastname")
info.SetNickname("nickname")
info.SetPreferredUsername("username")
info.SetEmail("email", true)
info.SetPhone("phone", true)
info.SetLocale(language.English)
info.SetPicture("picture")
info.SetProfile("profile")
claims.SetUserinfo(info)
privateKey, err := crypto.BytesToPrivateKey([]byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAs38btwb3c7r0tMaQpGvBmY+mPwMU/LpfuPoC0k2t4RsKp0fv
40SMl50CRrHgk395wch8PMPYbl3+8TtYAJuyrFALIj3Ff1UcKIk0hOH5DDsfh7/q
2wFuncTmS6bifYo8CfSq2vDGnM7nZnEvxY/MfSydZdcmIqlkUpfQmtzExw9+tSe5
Dxq6gn5JtlGgLgZGt69r5iMMrTEGhhVAXzNuMZbmlCoBru+rC8ITlTX/0V1ZcsSb
L8tYWhthyu9x6yjo1bH85wiVI4gs0MhU8f2a+kjL/KGZbR14Ua2eo6tonBZLC5DH
WM2TkYXgRCDPufjcgmzN0Lm91E4P8KvBcvly6QIDAQABAoIBAQCPj1nbSPcg2KZe
73FAD+8HopyUSSK//1AP4eXfzcEECVy77g0u9+R6XlkzsZCsZ4g6NN8ounqfyw3c
YlpAIkcFCf/dowoSjT+4LASVQyatYZwWNqjgAIU4KgMG/rKnNahPTiBYe7peMB1j
EaPjnt8uPkCk8y7NCi3y4Pk24tt/WM5KbJK2NQhUi1csGnleDfE+0blV0l/e6C68
W5cbnbWAroMqae/Yon3XVZiXX0m+l2f6ZzIgKaD18J+eEM8FjJC+jQKiRe1i9v3K
nQrLwh/gn8J10FcbKn3xqslKVidzASIrNIzHT9j/Z5T9NXuAKa7IV2x+Dtdus+wq
iBsUunwBAoGBANpYew+8i9vDwK4/SefduDTuzJ0H9lWTjtbiWQ+KYZoeJ7q3/qns
jsmi+mjxkXxXg1RrGbNbjtbl3RXXIrUeeBB0lglRJUjc3VK7VvNoyXIWsiqhCspH
IJ9Yuknv4mXB01m/glbSCS/xu4RTgf5aOG4jUiRb9+dCIpvDxI9gbXEVAoGBANJz
hIJkplIJ+biTi3G1Oz17qkUkInNXzAEzKD9Atoz5AIAiR1ivOMLOlbucfjevw/Nw
TnpkMs9xqCefKupTlsriXtZI88m7ZKzAmolYsPolOy/Jhi31h9JFVTEfKGqVS+dk
A4ndhgdW9RUeNJPY2YVCARXQrWpueweQDA1cNaeFAoGAPJsYtXqBW6PPRM5+ZiSt
78tk8iV2o7RMjqrPS7f+dXfvUS2nO2VVEPTzCtQarOfhpToBLT65vD6bimdn09w8
OV0TFEz4y2u65y7m6LNqTwertpdy1ki97l0DgGhccCBH2P6GYDD2qd8wTH+dcot6
ZF/begopGoDJ+HBzi9SZLC0CgYBZzPslHMevyBvr++GLwrallKhiWnns1/DwLiEl
ZHrBCtuA0Z+6IwLIdZiE9tEQ+ApYTXrfVPQteqUzSwLn/IUiy5eGPpjwYushoAoR
Q2w5QTvRN1/vKo8rVXR1woLfgBdkhFPSN1mitiNcQIhU8jpXV4PZCDOHb99FqdzK
sqcedQKBgQCOmgbqxGsnT2WQhoOdzln+NOo6Tx+FveLLqat2KzpY59W4noeI2Awn
HfIQgWUAW9dsjVVOXMP1jhq8U9hmH/PFWA11V/iCdk1NTxZEw87VAOeWuajpdDHG
+iex349j8h2BcQ4Zd0FWu07gGFnS/yuDJPn6jBhRusdieEcxLRjTKg==
-----END RSA PRIVATE KEY-----
`))
if err != nil {
t.Fatal(err)
}
signer, err := jose.NewSigner(jose.SigningKey{Key: privateKey, Algorithm: "RS256"}, &jose.SignerOptions{})
if err != nil {
t.Fatal(err)
}
data, err := json.Marshal(claims)
if err != nil {
t.Fatal(err)
}
jws, err := signer.Sign(data)
if err != nil {
t.Fatal(err)
}
idToken, err := jws.CompactSerialize()
if err != nil {
t.Fatal(err)
}
return idToken
}
func keys(t *testing.T) *jose.JSONWebKeySet {
privateKey, err := crypto.BytesToPublicKey([]byte(`-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs38btwb3c7r0tMaQpGvB
mY+mPwMU/LpfuPoC0k2t4RsKp0fv40SMl50CRrHgk395wch8PMPYbl3+8TtYAJuy
rFALIj3Ff1UcKIk0hOH5DDsfh7/q2wFuncTmS6bifYo8CfSq2vDGnM7nZnEvxY/M
fSydZdcmIqlkUpfQmtzExw9+tSe5Dxq6gn5JtlGgLgZGt69r5iMMrTEGhhVAXzNu
MZbmlCoBru+rC8ITlTX/0V1ZcsSbL8tYWhthyu9x6yjo1bH85wiVI4gs0MhU8f2a
+kjL/KGZbR14Ua2eo6tonBZLC5DHWM2TkYXgRCDPufjcgmzN0Lm91E4P8KvBcvly
6QIDAQAB
-----END PUBLIC KEY-----
`))
if err != nil {
t.Fatal(err)
}
return &jose.JSONWebKeySet{Keys: []jose.JSONWebKey{{Key: privateKey, Algorithm: "RS256", Use: oidc.KeyUseSignature}}}
}

View File

@@ -68,7 +68,7 @@ var DefaultMapper UserInfoMapper = func(info oidc.UserInfo) idp.User {
}
// New creates a generic OIDC provider
func New(name, issuer, clientID, clientSecret, redirectURI string, userInfoMapper UserInfoMapper, options ...ProviderOpts) (provider *Provider, err error) {
func New(name, issuer, clientID, clientSecret, redirectURI string, scopes []string, userInfoMapper UserInfoMapper, options ...ProviderOpts) (provider *Provider, err error) {
provider = &Provider{
name: name,
userInfoMapper: userInfoMapper,
@@ -76,13 +76,27 @@ func New(name, issuer, clientID, clientSecret, redirectURI string, userInfoMappe
for _, option := range options {
option(provider)
}
provider.RelyingParty, err = rp.NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI, []string{oidc.ScopeOpenID}, provider.options...)
provider.RelyingParty, err = rp.NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI, setDefaultScope(scopes), provider.options...)
if err != nil {
return nil, err
}
return provider, nil
}
// setDefaultScope ensures that at least openid ist set
// if none is provided it will request `openid profile email phone`
func setDefaultScope(scopes []string) []string {
if len(scopes) == 0 {
return []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopePhone}
}
for _, scope := range scopes {
if scope == oidc.ScopeOpenID {
return scopes
}
}
return append(scopes, oidc.ScopeOpenID)
}
// Name implements the [idp.Provider] interface
func (p *Provider) Name() string {
return p.name

View File

@@ -20,6 +20,7 @@ func TestProvider_BeginAuth(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
userMapper func(info oidc.UserInfo) idp.User
httpMock func(issuer string)
}
@@ -36,6 +37,7 @@ func TestProvider_BeginAuth(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
httpMock: func(issuer string) {
gock.New(issuer).
@@ -59,7 +61,7 @@ func TestProvider_BeginAuth(t *testing.T) {
a := assert.New(t)
r := require.New(t)
provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.userMapper)
provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.userMapper)
r.NoError(err)
session, err := provider.BeginAuth(context.Background(), "testState")
@@ -77,6 +79,7 @@ func TestProvider_Options(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
userMapper func(info oidc.UserInfo) idp.User
opts []ProviderOpts
httpMock func(issuer string)
@@ -102,6 +105,7 @@ func TestProvider_Options(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
opts: nil,
httpMock: func(issuer string) {
@@ -133,6 +137,7 @@ func TestProvider_Options(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
opts: []ProviderOpts{
WithLinkingAllowed(),
@@ -169,7 +174,7 @@ func TestProvider_Options(t *testing.T) {
tt.fields.httpMock(tt.fields.issuer)
a := assert.New(t)
provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.userMapper, tt.fields.opts...)
provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.userMapper, tt.fields.opts...)
require.NoError(t, err)
a.Equal(tt.want.name, provider.Name())

View File

@@ -27,6 +27,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID string
clientSecret string
redirectURI string
scopes []string
userMapper func(oidc.UserInfo) idp.User
httpMock func(issuer string)
authURL string
@@ -62,6 +63,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
httpMock: func(issuer string) {
gock.New(issuer).
@@ -93,6 +95,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
httpMock: func(issuer string) {
gock.New(issuer).
@@ -141,6 +144,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
httpMock: func(issuer string) {
gock.New(issuer).
@@ -201,6 +205,7 @@ func TestSession_FetchUser(t *testing.T) {
clientID: "clientID",
clientSecret: "clientSecret",
redirectURI: "redirectURI",
scopes: []string{"openid"},
userMapper: DefaultMapper,
httpMock: func(issuer string) {
gock.New(issuer).
@@ -254,7 +259,7 @@ func TestSession_FetchUser(t *testing.T) {
tt.fields.httpMock(tt.fields.issuer)
a := assert.New(t)
provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.userMapper)
provider, err := New(tt.fields.name, tt.fields.issuer, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.userMapper)
require.NoError(t, err)
session := &Session{