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:
Vedant Madane 2026-01-12 01:54:20 +05:30
parent 41a719255f
commit eec2c58157
2 changed files with 348 additions and 0 deletions

View 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)
}
}

View file

@ -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"])
}
}