@@ -6,18 +6,25 @@ module Test.SAML2.WebSSO.APISpec
6
6
)
7
7
where
8
8
9
+ import Codec.Binary.UTF8.String qualified as UTF8
9
10
import Control.Concurrent.MVar
10
11
import Control.Exception (SomeException , try )
11
12
import Control.Lens
12
13
import Control.Monad
13
14
import Control.Monad.IO.Class
15
+ import Data.ByteString qualified as SBS
14
16
import Data.ByteString.Base64.Lazy qualified as EL (decodeLenient , encode )
17
+ import Data.ByteString.Lazy qualified as LBS
18
+ import Data.ByteString.Lazy.Char8 qualified as LBSC8
19
+ import Data.ByteString.Lazy.UTF8 qualified as LBSUTF8
15
20
import Data.Either
16
21
import Data.EitherR
17
22
import Data.List.NonEmpty (NonEmpty ((:|) ))
18
23
import Data.Map qualified as Map
19
- import Data.Maybe ( maybeToList )
24
+ import Data.Maybe
20
25
import Data.String.Conversions
26
+ import Data.Text.Lazy.Encoding as LT
27
+ import Data.Tree.NTree.TypeDefs as HXT
21
28
import Data.UUID
22
29
import Data.Yaml qualified as Yaml
23
30
import Network.Wai.Test
@@ -26,14 +33,17 @@ import SAML2.WebSSO
26
33
import SAML2.WebSSO.API.Example (RequestStore )
27
34
import SAML2.WebSSO.Test.MockResponse
28
35
import SAML2.WebSSO.Test.Util
36
+ import SAML2.XML qualified as HSAML2
29
37
import Servant
30
38
import Test.Hspec hiding (pending )
31
39
import Test.Hspec.Wai
32
40
import Test.Hspec.Wai.Matcher
33
41
import Text.XML as XML
42
+ import Text.XML.HXT.DOM.ShowXml as HXT
43
+ import Text.XML.HXT.DOM.TypeDefs as HXT
34
44
import URI.ByteString.QQ
35
45
36
- spec :: Spec
46
+ spec :: ( HasCallStack ) => Spec
37
47
spec = describe " API" $ do
38
48
describe " base64 encoding" $ do
39
49
describe " compatible with /usr/bin/env base64" $ do
@@ -327,10 +337,11 @@ spec = describe "API" $ do
327
337
-- * onelogin
328
338
-- * jives [https://community.jivesoftware.com/docs/DOC-240217#jive_content_id_IdP_Metadata]
329
339
330
- focus . describe " simpleVerifyAuthnResponse, second attempt" $ do
340
+ describe " simpleVerifyAuthnResponse, second attempt" $ do
331
341
let check :: FilePath -> FilePath -> Expectation
332
342
check metaFile respFile = do
333
- resp :: LBS <- cs <$> readSampleIO respFile
343
+ resp :: LBS <- readSampleIOLBS respFile
344
+ -- () <- error $ show resp -- "R\196\131zvan Ioan BIBAR\200\154" (UTF8!)
334
345
assertions <- liftIO $ do
335
346
idpCfg :: IdPConfig_ <- do
336
347
raw :: LBS <- cs <$> readSampleIO metaFile
@@ -347,3 +358,45 @@ spec = describe "API" $ do
347
358
348
359
it " works" $ do
349
360
check " microsoft-azure-utf8-issue-metadata.base64" " microsoft-azure-utf8-issue-authentication-request.base64"
361
+
362
+ -- hxt uses Char8.pack, which won't work on unicode strings.
363
+
364
+ focus . it " hxt bug?" $ do
365
+ let nope1 :: LBS. ByteString = HXT. xshowBlob [NTree (XText payloadString) [] ]
366
+ nope2 :: LBS. ByteString = LBSC8. pack payloadString
367
+ nope3 :: LBS. ByteString = LBSUTF8. fromString payloadString
368
+ yeah1 :: LBS. ByteString = LBS. pack bs
369
+
370
+ -- 0xC4=196, 0x83=131, 0xC8 = 200, 0x9A = 154
371
+ -- ă -> 0xC4 0x83 (utf-8), 0x0103 (utf-16)
372
+ -- Ț -> 0xC8 0x9A (utf-8), 0x021A (utf-16)
373
+ bs = [0xC4 , 0x83 , 0xC8 , 0x9A ]
374
+ payloadLBS :: LBS. ByteString = LBS. pack bs
375
+ payloadString :: String = " ăȚ"
376
+ utf8String = UTF8. encodeString payloadString
377
+
378
+ print (payloadLBS, payloadString, nope1, nope2, nope3)
379
+ print (LBS. unpack payloadLBS, LBS. unpack nope1, LBS. unpack nope2, (LBS. unpack . LBSC8. pack) utf8String, LBS. unpack nope3)
380
+ -- print ((LB.toString . LBS.toString) nope1, (LB.toString . LBS.toStrict) nope2)
381
+
382
+ LBS. writeFile " /tmp/x" payloadLBS
383
+ -- <>) . LT.encodeUtf8) <$> LT.decodeUtf8' nope1)
384
+ LBS. unpack nope2 `shouldBe` bs
385
+ nope1 `shouldSatisfy` (SBS. isValidUtf8 . LBSC8. toStrict)
386
+ nope2 `shouldSatisfy` (SBS. isValidUtf8 . LBSC8. toStrict)
387
+ nope1 `shouldBe` " \x0103\x021a "
388
+ nope2 `shouldBe` " \x0103\x021a "
389
+
390
+ it " parseFromXmlTree" $ do
391
+ resp :: LBS <- cs <$> readSampleIO " microsoft-azure-utf8-issue-authentication-request.base64"
392
+ let tree :: Maybe (NTree XNode ) = HSAML2. xmlToDoc resp
393
+ liftIO $ print resp
394
+ liftIO $ print tree
395
+ let result :: Either String AuthnResponse = parseFromXmlTree (fromJust tree)
396
+ liftIO $ print result
397
+ False `shouldBe` True
398
+
399
+ it " HSAML2.docToXMLWithRoot" $ do
400
+ let x = " <samlp:Response ID=\" ăȚ\" ></samlp:Response>\n "
401
+ y = HSAML2. docToXMLWithRoot (HXT. NTree (HXT. XText x) [] )
402
+ y `shouldBe` x
0 commit comments