mirror of
https://github.com/photoprism/photoprism.git
synced 2026-01-23 02:24:24 +00:00
test(oidc): add comprehensive tests for dummy OIDC service
- Add tests for AuthRequest getters (ID, ClientID, Nonce, etc.) - Add tests for AuthStorage methods (Health, GetKeySet, CreateAccessToken, etc.) - Add tests for ConfClient methods (GetID, RedirectURIs, LoginURL, etc.) - Improve test coverage for OIDC mock storage and client Fixes #5381
This commit is contained in:
parent
41a719255f
commit
eec2c58157
2 changed files with 348 additions and 0 deletions
168
docker/dummy/oidc/app/mock/client_test.go
Normal file
168
docker/dummy/oidc/app/mock/client_test.go
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
package mock
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/oidc/pkg/oidc"
|
||||
"github.com/zitadel/oidc/pkg/op"
|
||||
)
|
||||
|
||||
func TestConfClientGetID(t *testing.T) {
|
||||
c := &ConfClient{ID: "test-client"}
|
||||
if got := c.GetID(); got != "test-client" {
|
||||
t.Fatalf("expected ID 'test-client', got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientRedirectURIs(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
uris := c.RedirectURIs()
|
||||
if len(uris) == 0 {
|
||||
t.Fatal("expected non-empty redirect URIs")
|
||||
}
|
||||
// Check that localhost:2342 PhotoPrism callback is included
|
||||
found := false
|
||||
for _, uri := range uris {
|
||||
if uri == "http://localhost:2342/api/v1/oidc/redirect" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("expected PhotoPrism OIDC redirect URI in list")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientPostLogoutRedirectURIs(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
uris := c.PostLogoutRedirectURIs()
|
||||
if len(uris) != 0 {
|
||||
t.Fatalf("expected empty post-logout redirect URIs, got %v", uris)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientLoginURL(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
url := c.LoginURL("abc123")
|
||||
expected := "login?id=abc123"
|
||||
if url != expected {
|
||||
t.Fatalf("expected login URL %q, got %q", expected, url)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientApplicationType(t *testing.T) {
|
||||
tests := []struct {
|
||||
appType op.ApplicationType
|
||||
expected op.ApplicationType
|
||||
}{
|
||||
{op.ApplicationTypeWeb, op.ApplicationTypeWeb},
|
||||
{op.ApplicationTypeNative, op.ApplicationTypeNative},
|
||||
{op.ApplicationTypeUserAgent, op.ApplicationTypeUserAgent},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
c := &ConfClient{applicationType: tt.appType}
|
||||
if got := c.ApplicationType(); got != tt.expected {
|
||||
t.Fatalf("expected ApplicationType %v, got %v", tt.expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientAuthMethod(t *testing.T) {
|
||||
c := &ConfClient{authMethod: oidc.AuthMethodBasic}
|
||||
if got := c.AuthMethod(); got != oidc.AuthMethodBasic {
|
||||
t.Fatalf("expected AuthMethod %v, got %v", oidc.AuthMethodBasic, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientIDTokenLifetime(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
expected := 60 * time.Minute
|
||||
if got := c.IDTokenLifetime(); got != expected {
|
||||
t.Fatalf("expected IDTokenLifetime %v, got %v", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientAccessTokenType(t *testing.T) {
|
||||
c := &ConfClient{accessTokenType: op.AccessTokenTypeJWT}
|
||||
if got := c.AccessTokenType(); got != op.AccessTokenTypeJWT {
|
||||
t.Fatalf("expected AccessTokenType %v, got %v", op.AccessTokenTypeJWT, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientResponseTypes(t *testing.T) {
|
||||
expected := []oidc.ResponseType{oidc.ResponseTypeCode}
|
||||
c := &ConfClient{responseTypes: expected}
|
||||
got := c.ResponseTypes()
|
||||
if len(got) != len(expected) {
|
||||
t.Fatalf("expected %d response types, got %d", len(expected), len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientGrantTypes(t *testing.T) {
|
||||
expected := []oidc.GrantType{oidc.GrantTypeCode}
|
||||
c := &ConfClient{grantTypes: expected}
|
||||
got := c.GrantTypes()
|
||||
if len(got) != len(expected) {
|
||||
t.Fatalf("expected %d grant types, got %d", len(expected), len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientDevMode(t *testing.T) {
|
||||
c := &ConfClient{devMode: true}
|
||||
if !c.DevMode() {
|
||||
t.Fatal("expected DevMode to be true")
|
||||
}
|
||||
c.devMode = false
|
||||
if c.DevMode() {
|
||||
t.Fatal("expected DevMode to be false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientAllowedScopes(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
if got := c.AllowedScopes(); got != nil {
|
||||
t.Fatalf("expected nil AllowedScopes, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientRestrictAdditionalIdTokenScopes(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
fn := c.RestrictAdditionalIdTokenScopes()
|
||||
scopes := []string{"openid", "profile"}
|
||||
got := fn(scopes)
|
||||
if len(got) != len(scopes) {
|
||||
t.Fatalf("expected same scopes returned, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientRestrictAdditionalAccessTokenScopes(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
fn := c.RestrictAdditionalAccessTokenScopes()
|
||||
scopes := []string{"openid", "profile"}
|
||||
got := fn(scopes)
|
||||
if len(got) != len(scopes) {
|
||||
t.Fatalf("expected same scopes returned, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientIsScopeAllowed(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
if c.IsScopeAllowed("openid") {
|
||||
t.Fatal("expected IsScopeAllowed to return false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientIDTokenUserinfoClaimsAssertion(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
if c.IDTokenUserinfoClaimsAssertion() {
|
||||
t.Fatal("expected IDTokenUserinfoClaimsAssertion to return false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfClientClockSkew(t *testing.T) {
|
||||
c := &ConfClient{}
|
||||
if got := c.ClockSkew(); got != 0 {
|
||||
t.Fatalf("expected ClockSkew 0, got %v", got)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,93 @@ func TestAuthRequestResponseModeDefault(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAuthRequestResponseModeCustom(t *testing.T) {
|
||||
req := &AuthRequest{ResponseMode: oidc.ResponseModeFragment}
|
||||
if got := req.GetResponseMode(); got != oidc.ResponseModeFragment {
|
||||
t.Fatalf("expected response mode %q, got %q", oidc.ResponseModeFragment, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthRequestGetters(t *testing.T) {
|
||||
req := &AuthRequest{
|
||||
ID: "test-id",
|
||||
ClientID: "test-client",
|
||||
Nonce: "test-nonce",
|
||||
RedirectURI: "https://example.com/callback",
|
||||
}
|
||||
|
||||
if got := req.GetID(); got != "test-id" {
|
||||
t.Fatalf("expected ID %q, got %q", "test-id", got)
|
||||
}
|
||||
if got := req.GetClientID(); got != "test-client" {
|
||||
t.Fatalf("expected ClientID %q, got %q", "test-client", got)
|
||||
}
|
||||
if got := req.GetNonce(); got != "test-nonce" {
|
||||
t.Fatalf("expected Nonce %q, got %q", "test-nonce", got)
|
||||
}
|
||||
if got := req.GetRedirectURI(); got != "https://example.com/callback" {
|
||||
t.Fatalf("expected RedirectURI %q, got %q", "https://example.com/callback", got)
|
||||
}
|
||||
if got := req.GetSubject(); got != "sub00000001" {
|
||||
t.Fatalf("expected Subject %q, got %q", "sub00000001", got)
|
||||
}
|
||||
if got := req.GetACR(); got != "" {
|
||||
t.Fatalf("expected empty ACR, got %q", got)
|
||||
}
|
||||
if len(req.GetAMR()) != 0 {
|
||||
t.Fatalf("expected empty AMR, got %v", req.GetAMR())
|
||||
}
|
||||
if !req.Done() {
|
||||
t.Fatal("expected Done() to return true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthRequestAudience(t *testing.T) {
|
||||
req := &AuthRequest{ClientID: "my-client"}
|
||||
aud := req.GetAudience()
|
||||
if len(aud) != 1 || aud[0] != "my-client" {
|
||||
t.Fatalf("expected audience [my-client], got %v", aud)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthRequestScopes(t *testing.T) {
|
||||
req := &AuthRequest{}
|
||||
scopes := req.GetScopes()
|
||||
expected := []string{"openid", "profile", "email"}
|
||||
if len(scopes) != len(expected) {
|
||||
t.Fatalf("expected %d scopes, got %d", len(expected), len(scopes))
|
||||
}
|
||||
for i, s := range expected {
|
||||
if scopes[i] != s {
|
||||
t.Fatalf("expected scope %q at index %d, got %q", s, i, scopes[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAuthStorage(t *testing.T) {
|
||||
storage := NewAuthStorage()
|
||||
if storage == nil {
|
||||
t.Fatal("expected non-nil storage")
|
||||
}
|
||||
as, ok := storage.(*AuthStorage)
|
||||
if !ok {
|
||||
t.Fatal("expected *AuthStorage type")
|
||||
}
|
||||
if as.key == nil {
|
||||
t.Fatal("expected non-nil RSA key")
|
||||
}
|
||||
if as.kid == "" {
|
||||
t.Fatal("expected non-empty kid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageHealth(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
if err := storage.Health(context.Background()); err != nil {
|
||||
t.Fatalf("expected nil from Health(), got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRevokeTokenNoError(t *testing.T) {
|
||||
s := &AuthStorage{}
|
||||
if err := s.RevokeToken(
|
||||
|
|
@ -25,3 +112,96 @@ func TestRevokeTokenNoError(t *testing.T) {
|
|||
t.Fatalf("expected nil error from RevokeToken, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageGetKeySet(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
keySet, err := storage.GetKeySet(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error from GetKeySet: %v", err)
|
||||
}
|
||||
if keySet == nil {
|
||||
t.Fatal("expected non-nil key set")
|
||||
}
|
||||
if len(keySet.Keys) != 2 {
|
||||
t.Fatalf("expected 2 keys, got %d", len(keySet.Keys))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageGetKey(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
key, err := storage.GetKey(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error from GetKey: %v", err)
|
||||
}
|
||||
if key == nil {
|
||||
t.Fatal("expected non-nil key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageCreateAccessToken(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
tokenID, expiration, err := storage.CreateAccessToken(context.Background(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if tokenID != "loginId" {
|
||||
t.Fatalf("expected tokenID 'loginId', got %q", tokenID)
|
||||
}
|
||||
if expiration.IsZero() {
|
||||
t.Fatal("expected non-zero expiration")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageCreateAccessAndRefreshTokens(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
accessID, refresh, expiration, err := storage.CreateAccessAndRefreshTokens(context.Background(), nil, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if accessID != "loginId" {
|
||||
t.Fatalf("expected accessID 'loginId', got %q", accessID)
|
||||
}
|
||||
if refresh != "refreshToken" {
|
||||
t.Fatalf("expected refresh 'refreshToken', got %q", refresh)
|
||||
}
|
||||
if expiration.IsZero() {
|
||||
t.Fatal("expected non-zero expiration")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageTerminateSession(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
if err := storage.TerminateSession(context.Background(), "user", "client"); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageAuthorizeClientIDSecret(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
if err := storage.AuthorizeClientIDSecret(context.Background(), "client", "secret"); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageValidateJWTProfileScopes(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
scopes := []string{"openid", "profile"}
|
||||
result, err := storage.ValidateJWTProfileScopes(context.Background(), "user", scopes)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(result) != len(scopes) {
|
||||
t.Fatalf("expected %d scopes, got %d", len(scopes), len(result))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthStorageGetPrivateClaimsFromScopes(t *testing.T) {
|
||||
storage := NewAuthStorage().(*AuthStorage)
|
||||
claims, err := storage.GetPrivateClaimsFromScopes(context.Background(), "", "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if claims["private_claim"] != "test" {
|
||||
t.Fatalf("expected private_claim 'test', got %v", claims["private_claim"])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue