chatdesk-ui/auth_v2.169.0/internal/api/provider/oidc_test.go

186 lines
7.5 KiB
Go

package provider
import (
"context"
"crypto"
"crypto/rsa"
"encoding/base64"
"math/big"
"testing"
"time"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/stretchr/testify/require"
)
type realIDToken struct {
AccessToken string
IDToken string
Time time.Time
Email string
Verifier func(context.Context, *oidc.Config) *oidc.IDTokenVerifier
}
func googleIDTokenVerifier(ctx context.Context, config *oidc.Config) *oidc.IDTokenVerifier {
keyBytes, err := base64.RawURLEncoding.DecodeString("pP-rCe4jkKX6mq8yP1GcBZcxJzmxKWicHHor1S3Q49u6Oe-bQsk5NsK5mdR7Y7liGV9n0ikXSM42dYKQdxbhKA-7--fFon5isJoHr4fIwL2CCwVm5QWlK37q6PiH2_F1M0hRorHfkCb4nI56ZvfygvuOH4LIS82OzIgmsYbeEfwDRpeMSxWKwlpa3pX3GZ6jG7FgzJGBvmBkagpgsa2JZdyU4gEGMOkHdSzi5Ii-6RGfFLhhI1OMxC9P2JaU5yjMN2pikfFIq_dbpm75yNUGpWJNVywtrlNvvJfA74UMN_lVCAaSR0A03BUMg6ljB65gFllpKF224uWBA8tpjngwKQ")
if err != nil {
panic(err)
}
n := big.NewInt(0)
n.SetBytes(keyBytes)
publicKey := &rsa.PublicKey{
N: n,
E: 65537,
}
return oidc.NewVerifier(
"https://accounts.google.com",
&oidc.StaticKeySet{
PublicKeys: []crypto.PublicKey{publicKey},
},
config,
)
}
func azureIDTokenVerifier(ctx context.Context, config *oidc.Config) *oidc.IDTokenVerifier {
keyBytes, err := base64.RawURLEncoding.DecodeString("1djHqyNclRpJWtHCnkP5QWvDxozCTG_ZDnkEmudpcxjnYrVL4RVIwdNCBLAStg8Dob5OUyAlHcRFMCqGTW4HA6kHgIxyfiFsYCBDMHWd2-61N1cAS6S9SdXlWXkBQgU0Qj6q_yFYTRS7J-zI_jMLRQAlpowfDFM1vSTBIci7kqynV6pPOz4jMaDQevmSscEs-jz7e8YXAiiVpN588oBQ0jzQaTTx90WjgRP23mn8mPyabj8gcR3gLwKLsBUhlp1oZj7FopGp8z8LHuueJB_q_LOUa_gAozZ0lfoJxFimXgpgEK7GNVdMRsMH3mIl0A5oYN8f29RFwbG0rNO5ZQ1YWQ")
if err != nil {
panic(err)
}
n := big.NewInt(0)
n.SetBytes(keyBytes)
publicKey := &rsa.PublicKey{
N: n,
E: 65537,
}
return oidc.NewVerifier(
IssuerAzureMicrosoft,
&oidc.StaticKeySet{
PublicKeys: []crypto.PublicKey{publicKey},
},
config,
)
}
var realIDTokens map[string]realIDToken = map[string]realIDToken{
IssuerGoogle: {
AccessToken: "ya29.a0AWY7CklOn4TehiT4kA6osNP6e-pHErOY8X53T2oUe7Oqqwc3-uIJpoEgoZCUogewBuNWr-JFT2FK9s0E0oRSFtAfu0-uIDckBj5ca1pxnk0-zPkPZouqoIyl0AlIpQjIUEuyuQTYUay99kRajbHcFCR1VMbNcQaCgYKAQESARESFQG1tDrp1joUHupV5Rn8-nWDpKkmMw0165",
IDToken: "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg1YmE5MzEzZmQ3YTdkNGFmYTg0ODg0YWJjYzg0MDMwMDQzNjMxODAiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI5MTQ2NjY0MjA3NS03OWNwaWs4aWNxYzU4NjY5bjdtaXY5NjZsYmFwOTNhMi5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF1ZCI6IjkxNDY2NjQyMDc1LTc5Y3BpazhpY3FjNTg2NjluN21pdjk2NmxiYXA5M2EyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTAzNzgzMTkwMTI2NDM5NzUxMjY5IiwiaGQiOiJzdXBhYmFzZS5pbyIsImVtYWlsIjoic3RvamFuQHN1cGFiYXNlLmlvIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF0X2hhc2giOiJlcGVWV244VmxWa28zd195Unk3UDZRIiwibmFtZSI6IlN0b2phbiBEaW1pdHJvdnNraSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQWNIVHRka0dhWjVlcGtqT1dxSEF1UUV4N2cwRlBCeXJiQ2ZNUjVNTk5kYz1zOTYtYyIsImdpdmVuX25hbWUiOiJTdG9qYW4iLCJmYW1pbHlfbmFtZSI6IkRpbWl0cm92c2tpIiwibG9jYWxlIjoiZW4tR0IiLCJpYXQiOjE2ODY2NTk5MzIsImV4cCI6MTY4NjY2MzUzMn0.nKAN9BFSxvavXYfWX4fZHREYY_3O4uOFRFq1KU1NNrBOMq_CPpM8c8PV7ZhKQvGCjBthSjtxGWbcqT0ByA7RdpNW6kj5UpFxEPdhenZ-eO1FwiEVIC8uZpiX6J3Nr7fAqi1P0DVeB3Zr_GrtkS9MDhZNb3hE5NDkvjCulwP4gRBC-5Pn_aRJRESxYkr_naKiSSmVilkmNVjZO4orq6KuYlvWHKHZIRiUI1akt0gVr5GxsEpd_duzUU30yVSPiq8l6fgxvJn2hT0MHa77wo3hvlP0NyAoSE7Nh4tRSowB0Qq7_byDMUmNWfXh-Qqa2M6ywuJ-_3LTLNUJH-cwdm2tNQ",
Time: time.Unix(1686659933, 0), // 1 sec after iat
Verifier: googleIDTokenVerifier,
},
IssuerAzureMicrosoft: {
AccessToken: "access-token",
Time: time.Unix(1697277774, 0), // 1 sec after iat
IDToken: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlhvdVhMWVExVGlwNW9kWWFqaUN0RlZnVmFFcyJ9.eyJ2ZXIiOiIyLjAiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vOTE4ODA0MGQtNmM2Ny00YzViLWIxMTItMzZhMzA0YjY2ZGFkL3YyLjAiLCJzdWIiOiJBQUFBQUFBQUFBQUFBQUFBQUFBQUFCWkRuRDkxOTBfc2wxcTZwenZlRHZNIiwiYXVkIjoiYTBkOGY5NzItNTRhYy00YWJmLTkxNGMtNTIyMDE0YzQwMjJhIiwiZXhwIjoxNjk3MzY0NDczLCJpYXQiOjE2OTcyNzc3NzMsIm5iZiI6MTY5NzI3Nzc3MywiZW1haWwiOiJzZGltaXRyb3Zza2lAZ21haWwuY29tIiwidGlkIjoiOTE4ODA0MGQtNmM2Ny00YzViLWIxMTItMzZhMzA0YjY2ZGFkIiwieG1zX2Vkb3YiOiIxIiwiYWlvIjoiRHBQV3lZSnRJcUl5OHpyVjROIUlIdGtFa09BMDhPS29lZ1RkYmZQUEVPYmxtYk9ESFQ0cGJVcVI1cExraENyWWZ6bUgzb3A1RzN5RGp2M0tNZ0Rad29lQ1FjKmVueldyb21iQ3BuKkR6OEpQOGMxU3pEVG1TbGp4U3U3UnVLTXNZSjRvS1lDazFBSVcqUUNUTmlMWkpUKlN3WWZQcjZBTW9IejFEZ3pBZEFkbk9uWiFHNUNFeEtQalBxcHRuVmpUZlEkJCJ9.CskICxOaeqd4SkiPdWEHJKZVdhAdgzM5SN7K7FYi0dguQH1-v6XTetDIoEsBn0GZoozXjbG2GgkFcVhhBvNA0ZrDIr4KcjfnJ5-7rwX3AtxdQ3umrHRlGu3jlmbDOtWzPWNMLLRXfR1Mm3pHEUvlzqmk3Ffh4TuAmXID-fb-Xmfuuv1k0UsZ5mlr_3ybTPVZk-Lj0bqkR1L5Zzt4HjgfpchRryJ3Y24b4dDsSjg7mgE_5JivgjhtVef5OnqYhKUF1DTy2pFysFO_eRliK6qjouYeZnQOJnWHP1MgpySAOQ3sVcwvE4P9g7V3QouxByZPv-g99N1K4GwZrtdm46gtTQ",
Verifier: azureIDTokenVerifier,
},
}
func TestParseIDToken(t *testing.T) {
defer func() {
OverrideVerifiers = make(map[string]func(context.Context, *oidc.Config) *oidc.IDTokenVerifier)
OverrideClock = nil
}()
// note that this test can fail if/when the issuers rotate their
// signing keys (which happens rarely if ever)
// then you should obtain new ID tokens and update this test
for issuer, token := range realIDTokens {
oidcProvider, err := oidc.NewProvider(context.Background(), issuer)
require.NoError(t, err)
OverrideVerifiers[oidcProvider.Endpoint().AuthURL] = token.Verifier
_, user, err := ParseIDToken(context.Background(), oidcProvider, &oidc.Config{
SkipClientIDCheck: true,
Now: func() time.Time {
return token.Time
},
}, token.IDToken, ParseIDTokenOptions{
AccessToken: token.AccessToken,
})
require.NoError(t, err)
require.NotEmpty(t, user.Emails[0].Email)
require.Equal(t, user.Emails[0].Verified, true)
}
}
func TestAzureIDTokenClaimsIsEmailVerified(t *testing.T) {
positiveExamples := []AzureIDTokenClaims{
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: nil,
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: true,
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: "1",
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: "true",
},
}
negativeExamples := []AzureIDTokenClaims{
{
Email: "",
XMicrosoftEmailDomainOwnerVerified: true,
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: false,
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: "0",
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: "false",
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: float32(0),
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: float64(0),
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: int(0),
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: int32(0),
},
{
Email: "test@example.com",
XMicrosoftEmailDomainOwnerVerified: int64(0),
},
}
for i, example := range positiveExamples {
if !example.IsEmailVerified() {
t.Errorf("positive example %v reports negative result", i)
}
}
for i, example := range negativeExamples {
if example.IsEmailVerified() {
t.Errorf("negative example %v reports positive result", i)
}
}
}