@@ -1067,3 +1067,296 @@ func TestCheckTokenWithDPoP_EdgeCases(t *testing.T) {
10671067 assert .Nil (t , dpopCtx )
10681068 })
10691069}
1070+
1071+ // TestCheckTokenWithDPoP_LoggingPaths tests logging branches for better coverage
1072+ func TestCheckTokenWithDPoP_LoggingPaths (t * testing.T ) {
1073+ t .Run ("successful validation with debug logging" , func (t * testing.T ) {
1074+ logger := & mockLogger {}
1075+ validator := & mockTokenValidator {
1076+ validateFunc : func (ctx context.Context , token string ) (any , error ) {
1077+ return & mockTokenClaims {
1078+ hasConfirmation : true ,
1079+ jkt : "test-jkt" ,
1080+ }, nil
1081+ },
1082+ dpopValidateFunc : func (ctx context.Context , proof string ) (DPoPProofClaims , error ) {
1083+ return & mockDPoPProofClaims {
1084+ publicKeyThumbprint : "test-jkt" ,
1085+ htm : "POST" ,
1086+ htu : "https://example.com/api" ,
1087+ iat : time .Now ().Unix (),
1088+ }, nil
1089+ },
1090+ }
1091+
1092+ c , err := New (
1093+ WithValidator (validator ),
1094+ WithLogger (logger ),
1095+ WithDPoPMode (DPoPAllowed ),
1096+ )
1097+ require .NoError (t , err )
1098+
1099+ claims , dpopCtx , err := c .CheckTokenWithDPoP (
1100+ context .Background (),
1101+ "token" ,
1102+ "proof" ,
1103+ "POST" ,
1104+ "https://example.com/api" ,
1105+ )
1106+
1107+ assert .NoError (t , err )
1108+ assert .NotNil (t , claims )
1109+ assert .NotNil (t , dpopCtx )
1110+
1111+ // Verify debug logs for successful validation
1112+ assert .NotEmpty (t , logger .debugCalls )
1113+ foundTokenLog := false
1114+ foundProofLog := false
1115+ for _ , call := range logger .debugCalls {
1116+ if call .msg == "Access token validated successfully" {
1117+ foundTokenLog = true
1118+ }
1119+ if call .msg == "DPoP proof validated successfully" {
1120+ foundProofLog = true
1121+ }
1122+ }
1123+ assert .True (t , foundTokenLog , "Expected debug log for token validation" )
1124+ assert .True (t , foundProofLog , "Expected debug log for DPoP proof validation" )
1125+ })
1126+
1127+ t .Run ("DPoP disabled with warning logging" , func (t * testing.T ) {
1128+ logger := & mockLogger {}
1129+ validator := & mockTokenValidator {
1130+ validateFunc : func (ctx context.Context , token string ) (any , error ) {
1131+ return & mockTokenClaims {
1132+ hasConfirmation : false ,
1133+ }, nil
1134+ },
1135+ }
1136+
1137+ c , err := New (
1138+ WithValidator (validator ),
1139+ WithLogger (logger ),
1140+ WithDPoPMode (DPoPDisabled ),
1141+ )
1142+ require .NoError (t , err )
1143+
1144+ claims , dpopCtx , err := c .CheckTokenWithDPoP (
1145+ context .Background (),
1146+ "token" ,
1147+ "proof-present-but-disabled" , // DPoP proof present
1148+ "POST" ,
1149+ "https://example.com/api" ,
1150+ )
1151+
1152+ assert .NoError (t , err )
1153+ assert .NotNil (t , claims )
1154+ assert .Nil (t , dpopCtx )
1155+
1156+ // Verify warning log
1157+ assert .NotEmpty (t , logger .warnCalls )
1158+ found := false
1159+ for _ , call := range logger .warnCalls {
1160+ if call .msg == "DPoP header present but DPoP is disabled, treating as Bearer token" {
1161+ found = true
1162+ break
1163+ }
1164+ }
1165+ assert .True (t , found , "Expected warning log for DPoP disabled" )
1166+ })
1167+
1168+ t .Run ("JKT mismatch with error logging" , func (t * testing.T ) {
1169+ logger := & mockLogger {}
1170+ validator := & mockTokenValidator {
1171+ validateFunc : func (ctx context.Context , token string ) (any , error ) {
1172+ return & mockTokenClaims {
1173+ hasConfirmation : true ,
1174+ jkt : "expected-jkt" ,
1175+ }, nil
1176+ },
1177+ dpopValidateFunc : func (ctx context.Context , proof string ) (DPoPProofClaims , error ) {
1178+ return & mockDPoPProofClaims {
1179+ publicKeyThumbprint : "different-jkt" ,
1180+ htm : "POST" ,
1181+ htu : "https://example.com/api" ,
1182+ iat : time .Now ().Unix (),
1183+ }, nil
1184+ },
1185+ }
1186+
1187+ c , err := New (
1188+ WithValidator (validator ),
1189+ WithLogger (logger ),
1190+ WithDPoPMode (DPoPAllowed ),
1191+ )
1192+ require .NoError (t , err )
1193+
1194+ claims , dpopCtx , err := c .CheckTokenWithDPoP (
1195+ context .Background (),
1196+ "token" ,
1197+ "proof" ,
1198+ "POST" ,
1199+ "https://example.com/api" ,
1200+ )
1201+
1202+ assert .Error (t , err )
1203+ assert .Nil (t , claims )
1204+ assert .Nil (t , dpopCtx )
1205+
1206+ // Verify error log for JKT mismatch
1207+ assert .NotEmpty (t , logger .errorCalls )
1208+ found := false
1209+ for _ , call := range logger .errorCalls {
1210+ if call .msg == "DPoP JKT mismatch" {
1211+ found = true
1212+ break
1213+ }
1214+ }
1215+ assert .True (t , found , "Expected error log for JKT mismatch" )
1216+ })
1217+
1218+ t .Run ("HTM mismatch with error logging" , func (t * testing.T ) {
1219+ logger := & mockLogger {}
1220+ validator := & mockTokenValidator {
1221+ validateFunc : func (ctx context.Context , token string ) (any , error ) {
1222+ return & mockTokenClaims {
1223+ hasConfirmation : true ,
1224+ jkt : "test-jkt" ,
1225+ }, nil
1226+ },
1227+ dpopValidateFunc : func (ctx context.Context , proof string ) (DPoPProofClaims , error ) {
1228+ return & mockDPoPProofClaims {
1229+ publicKeyThumbprint : "test-jkt" ,
1230+ htm : "GET" ,
1231+ htu : "https://example.com/api" ,
1232+ iat : time .Now ().Unix (),
1233+ }, nil
1234+ },
1235+ }
1236+
1237+ c , err := New (
1238+ WithValidator (validator ),
1239+ WithLogger (logger ),
1240+ WithDPoPMode (DPoPAllowed ),
1241+ )
1242+ require .NoError (t , err )
1243+
1244+ claims , dpopCtx , err := c .CheckTokenWithDPoP (
1245+ context .Background (),
1246+ "token" ,
1247+ "proof" ,
1248+ "POST" , // Different from proof HTM
1249+ "https://example.com/api" ,
1250+ )
1251+
1252+ assert .Error (t , err )
1253+ assert .Nil (t , claims )
1254+ assert .Nil (t , dpopCtx )
1255+
1256+ // Verify error log for HTM mismatch
1257+ assert .NotEmpty (t , logger .errorCalls )
1258+ found := false
1259+ for _ , call := range logger .errorCalls {
1260+ if call .msg == "DPoP HTM mismatch" {
1261+ found = true
1262+ break
1263+ }
1264+ }
1265+ assert .True (t , found , "Expected error log for HTM mismatch" )
1266+ })
1267+
1268+ t .Run ("HTU mismatch with error logging" , func (t * testing.T ) {
1269+ logger := & mockLogger {}
1270+ validator := & mockTokenValidator {
1271+ validateFunc : func (ctx context.Context , token string ) (any , error ) {
1272+ return & mockTokenClaims {
1273+ hasConfirmation : true ,
1274+ jkt : "test-jkt" ,
1275+ }, nil
1276+ },
1277+ dpopValidateFunc : func (ctx context.Context , proof string ) (DPoPProofClaims , error ) {
1278+ return & mockDPoPProofClaims {
1279+ publicKeyThumbprint : "test-jkt" ,
1280+ htm : "POST" ,
1281+ htu : "https://example.com/wrong-url" ,
1282+ iat : time .Now ().Unix (),
1283+ }, nil
1284+ },
1285+ }
1286+
1287+ c , err := New (
1288+ WithValidator (validator ),
1289+ WithLogger (logger ),
1290+ WithDPoPMode (DPoPAllowed ),
1291+ )
1292+ require .NoError (t , err )
1293+
1294+ claims , dpopCtx , err := c .CheckTokenWithDPoP (
1295+ context .Background (),
1296+ "token" ,
1297+ "proof" ,
1298+ "POST" ,
1299+ "https://example.com/api" , // Different from proof HTU
1300+ )
1301+
1302+ assert .Error (t , err )
1303+ assert .Nil (t , claims )
1304+ assert .Nil (t , dpopCtx )
1305+
1306+ // Verify error log for HTU mismatch
1307+ assert .NotEmpty (t , logger .errorCalls )
1308+ found := false
1309+ for _ , call := range logger .errorCalls {
1310+ if call .msg == "DPoP HTU mismatch" {
1311+ found = true
1312+ break
1313+ }
1314+ }
1315+ assert .True (t , found , "Expected error log for HTU mismatch" )
1316+ })
1317+
1318+ t .Run ("DPoP proof validation failure with error logging" , func (t * testing.T ) {
1319+ logger := & mockLogger {}
1320+ validator := & mockTokenValidator {
1321+ validateFunc : func (ctx context.Context , token string ) (any , error ) {
1322+ return & mockTokenClaims {
1323+ hasConfirmation : true ,
1324+ jkt : "test-jkt" ,
1325+ }, nil
1326+ },
1327+ dpopValidateFunc : func (ctx context.Context , proof string ) (DPoPProofClaims , error ) {
1328+ return nil , errors .New ("proof validation failed" )
1329+ },
1330+ }
1331+
1332+ c , err := New (
1333+ WithValidator (validator ),
1334+ WithLogger (logger ),
1335+ WithDPoPMode (DPoPAllowed ),
1336+ )
1337+ require .NoError (t , err )
1338+
1339+ claims , dpopCtx , err := c .CheckTokenWithDPoP (
1340+ context .Background (),
1341+ "token" ,
1342+ "invalid-proof" ,
1343+ "POST" ,
1344+ "https://example.com/api" ,
1345+ )
1346+
1347+ assert .Error (t , err )
1348+ assert .Nil (t , claims )
1349+ assert .Nil (t , dpopCtx )
1350+
1351+ // Verify error log for proof validation
1352+ assert .NotEmpty (t , logger .errorCalls )
1353+ found := false
1354+ for _ , call := range logger .errorCalls {
1355+ if call .msg == "DPoP proof validation failed" {
1356+ found = true
1357+ break
1358+ }
1359+ }
1360+ assert .True (t , found , "Expected error log for proof validation failure" )
1361+ })
1362+ }
0 commit comments