mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-04-28 16:38:12 +00:00
5d95123dcb
* feat(oidc): support for all in-spec attributes and scopes * add tests * assert phone/email verified when either is set * update tests * add claims back to userinfo * remove redundant column drop in migration * fix duplicate migration id * fix clobbered imports post-rebase
199 lines
6.5 KiB
Go
199 lines
6.5 KiB
Go
package service_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/tinyauthapp/tinyauth/internal/config"
|
|
"github.com/tinyauthapp/tinyauth/internal/repository"
|
|
"github.com/tinyauthapp/tinyauth/internal/service"
|
|
)
|
|
|
|
func newTestUser() repository.OidcUserinfo {
|
|
addr := config.AddressClaim{
|
|
Formatted: "123 Main St",
|
|
StreetAddress: "123 Main St",
|
|
Locality: "Springfield",
|
|
Region: "IL",
|
|
PostalCode: "62701",
|
|
Country: "US",
|
|
}
|
|
addrJSON, _ := json.Marshal(addr)
|
|
|
|
return repository.OidcUserinfo{
|
|
Sub: "test-sub",
|
|
Name: "Test User",
|
|
PreferredUsername: "testuser",
|
|
Email: "test@example.com",
|
|
Groups: "admins,users",
|
|
UpdatedAt: 1234567890,
|
|
GivenName: "Test",
|
|
FamilyName: "User",
|
|
MiddleName: "M",
|
|
Nickname: "testy",
|
|
Profile: "https://example.com/testuser",
|
|
Picture: "https://example.com/testuser.jpg",
|
|
Website: "https://testuser.example.com",
|
|
Gender: "male",
|
|
Birthdate: "1990-01-01",
|
|
Zoneinfo: "America/Chicago",
|
|
Locale: "en-US",
|
|
PhoneNumber: "+15555550100",
|
|
Address: string(addrJSON),
|
|
}
|
|
}
|
|
|
|
func TestCompileUserinfo(t *testing.T) {
|
|
dir := t.TempDir()
|
|
svc := service.NewOIDCService(service.OIDCServiceConfig{
|
|
PrivateKeyPath: dir + "/key.pem",
|
|
PublicKeyPath: dir + "/key.pub",
|
|
Issuer: "https://tinyauth.example.com",
|
|
SessionExpiry: 3600,
|
|
}, nil)
|
|
require.NoError(t, svc.Init())
|
|
|
|
type testCase struct {
|
|
description string
|
|
mutate func(u *repository.OidcUserinfo)
|
|
scope string
|
|
run func(t *testing.T, info service.UserinfoResponse)
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
description: "openid scope only returns sub and updated_at",
|
|
scope: "openid",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, "test-sub", info.Sub)
|
|
assert.Equal(t, int64(1234567890), info.UpdatedAt)
|
|
assert.Empty(t, info.Name)
|
|
assert.Empty(t, info.Email)
|
|
assert.Nil(t, info.Groups)
|
|
assert.Nil(t, info.PhoneNumberVerified)
|
|
assert.Nil(t, info.Address)
|
|
},
|
|
},
|
|
{
|
|
description: "profile scope returns all profile fields",
|
|
scope: "openid,profile",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, "Test User", info.Name)
|
|
assert.Equal(t, "testuser", info.PreferredUsername)
|
|
assert.Equal(t, "Test", info.GivenName)
|
|
assert.Equal(t, "User", info.FamilyName)
|
|
assert.Equal(t, "M", info.MiddleName)
|
|
assert.Equal(t, "testy", info.Nickname)
|
|
assert.Equal(t, "https://example.com/testuser", info.Profile)
|
|
assert.Equal(t, "https://example.com/testuser.jpg", info.Picture)
|
|
assert.Equal(t, "https://testuser.example.com", info.Website)
|
|
assert.Equal(t, "male", info.Gender)
|
|
assert.Equal(t, "1990-01-01", info.Birthdate)
|
|
assert.Equal(t, "America/Chicago", info.Zoneinfo)
|
|
assert.Equal(t, "en-US", info.Locale)
|
|
assert.Empty(t, info.Email)
|
|
},
|
|
},
|
|
{
|
|
description: "email scope sets email and email_verified true when email present",
|
|
scope: "openid,email",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, "test@example.com", info.Email)
|
|
assert.True(t, info.EmailVerified)
|
|
assert.Empty(t, info.Name)
|
|
},
|
|
},
|
|
{
|
|
description: "email scope sets email_verified false when email absent",
|
|
scope: "openid,email",
|
|
mutate: func(u *repository.OidcUserinfo) { u.Email = "" },
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Empty(t, info.Email)
|
|
assert.False(t, info.EmailVerified)
|
|
},
|
|
},
|
|
{
|
|
description: "phone scope sets phone_number_verified true when phone present",
|
|
scope: "openid,phone",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, "+15555550100", info.PhoneNumber)
|
|
require.NotNil(t, info.PhoneNumberVerified)
|
|
assert.True(t, *info.PhoneNumberVerified)
|
|
},
|
|
},
|
|
{
|
|
description: "phone scope sets phone_number_verified false when phone absent",
|
|
scope: "openid,phone",
|
|
mutate: func(u *repository.OidcUserinfo) { u.PhoneNumber = "" },
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
require.NotNil(t, info.PhoneNumberVerified)
|
|
assert.False(t, *info.PhoneNumberVerified)
|
|
},
|
|
},
|
|
{
|
|
description: "address scope returns parsed address",
|
|
scope: "openid,address",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
require.NotNil(t, info.Address)
|
|
assert.Equal(t, "123 Main St", info.Address.Formatted)
|
|
assert.Equal(t, "123 Main St", info.Address.StreetAddress)
|
|
assert.Equal(t, "Springfield", info.Address.Locality)
|
|
assert.Equal(t, "IL", info.Address.Region)
|
|
assert.Equal(t, "62701", info.Address.PostalCode)
|
|
assert.Equal(t, "US", info.Address.Country)
|
|
},
|
|
},
|
|
{
|
|
description: "address scope with invalid JSON omits address",
|
|
scope: "openid,address",
|
|
mutate: func(u *repository.OidcUserinfo) { u.Address = "not-valid-json" },
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Nil(t, info.Address)
|
|
},
|
|
},
|
|
{
|
|
description: "groups scope returns split groups",
|
|
scope: "openid,groups",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, []string{"admins", "users"}, info.Groups)
|
|
},
|
|
},
|
|
{
|
|
description: "groups scope returns empty slice when no groups",
|
|
scope: "openid,groups",
|
|
mutate: func(u *repository.OidcUserinfo) { u.Groups = "" },
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, []string{}, info.Groups)
|
|
},
|
|
},
|
|
{
|
|
description: "all scopes return all fields",
|
|
scope: "openid,profile,email,phone,address,groups",
|
|
run: func(t *testing.T, info service.UserinfoResponse) {
|
|
assert.Equal(t, "Test User", info.Name)
|
|
assert.Equal(t, "test@example.com", info.Email)
|
|
assert.Equal(t, "+15555550100", info.PhoneNumber)
|
|
require.NotNil(t, info.PhoneNumberVerified)
|
|
assert.True(t, *info.PhoneNumberVerified)
|
|
require.NotNil(t, info.Address)
|
|
assert.Equal(t, "Springfield", info.Address.Locality)
|
|
assert.Equal(t, []string{"admins", "users"}, info.Groups)
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.description, func(t *testing.T) {
|
|
user := newTestUser()
|
|
if test.mutate != nil {
|
|
test.mutate(&user)
|
|
}
|
|
info := svc.CompileUserinfo(user, test.scope)
|
|
test.run(t, info)
|
|
})
|
|
}
|
|
}
|