1+ <?php
2+
3+ namespace Tests \Unit ;
4+
5+ use BookStack \Auth \Access \OpenIdConnect \OpenIdConnectIdToken ;
6+ use phpseclib3 \Crypt \RSA ;
7+ use Tests \TestCase ;
8+
9+ class OpenIdConnectIdTokenTest extends TestCase
10+ {
11+
12+ public function test_valid_token_passes_validation ()
13+ {
14+ $ token = new OpenIdConnectIdToken ($ this ->getValidToken (), 'https://auth.example.com ' , [
15+ $ this ->jwkKeyArray ()
16+ ]);
17+
18+ $ this ->assertTrue ($ token ->validate ('xxyyzz.aaa.bbccdd.123 ' ));
19+ }
20+
21+ protected function getValidToken ($ payloadOverrides = []): string
22+ {
23+ $ defaultPayload = [
24+ "sub " => "abc1234def " ,
25+ "name " => "Barry Scott " ,
26+ "email " => "bscott@example.com " ,
27+ "ver " => 1 ,
28+ "iss " => "https://auth.example.com " ,
29+ "aud " => "xxyyzz.aaa.bbccdd.123 " ,
30+ "iat " => time (),
31+ "exp " => time () + 720 ,
32+ "jti " => "ID.AaaBBBbbCCCcccDDddddddEEEeeeeee " ,
33+ "amr " => ["pwd " ],
34+ "idp " => "fghfghgfh546456dfgdfg " ,
35+ "preferred_username " => "xXBazzaXx " ,
36+ "auth_time " => time (),
37+ "at_hash " => "sT4jbsdSGy9w12pq3iNYDA " ,
38+ ];
39+
40+ $ payload = array_merge ($ defaultPayload , $ payloadOverrides );
41+ $ header = [
42+ 'kid ' => 'xyz456 ' ,
43+ 'alg ' => 'RS256 ' ,
44+ ];
45+
46+ $ top = implode ('. ' , [
47+ $ this ->base64UrlEncode (json_encode ($ header )),
48+ $ this ->base64UrlEncode (json_encode ($ payload )),
49+ ]);
50+
51+ $ privateKey = RSA ::loadPrivateKey ($ this ->privatePemKey ())->withPadding (RSA ::SIGNATURE_PKCS1 );
52+ $ signature = $ privateKey ->sign ($ top );
53+
54+ return $ top . '. ' . $ this ->base64UrlEncode ($ signature );
55+ }
56+
57+ protected function base64UrlEncode (string $ decoded ): string
58+ {
59+ return strtr (base64_encode ($ decoded ), '+/ ' , '-_ ' );
60+ }
61+
62+ protected function pemKey (): string
63+ {
64+ return "-----BEGIN PUBLIC KEY-----
65+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqo1OmfNKec5S2zQC4SP9
66+ DrHuUR0VgCi6oqcGERz7zqO36hqk3A3R3aCgJkEjfnbnMuszRRKs45NbXoOp9pvm
67+ zXL16c93Obn7G8x8A3ao6yN5qKO5S5+CETqOZfKN/g75Xlz7VsC3igOhgsXnPx6i
68+ iM6sbYbk0U/XpFaT84LXKI8VTIPUo7gTeZN1pTET//i9FlzAOzX+xfWBKdOqlEzl
69+ +zihMHCZUUvQu99P+o0MDR0lMUT+vPJ6SJeRfnoHexwt6bZFiNnsZIEL03bX4QNk
70+ WvsLta1+jNUee+8IPVhzCO8bvM86NzLaKUJ4k6NZ5IVrmdCFpFsjCWByOrDG8wdw
71+ 3wIDAQAB
72+ -----END PUBLIC KEY----- " ;
73+ }
74+
75+ protected function privatePemKey (): string
76+ {
77+ return "-----BEGIN PRIVATE KEY-----
78+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqjU6Z80p5zlLb
79+ NALhI/0Ose5RHRWAKLqipwYRHPvOo7fqGqTcDdHdoKAmQSN+ducy6zNFEqzjk1te
80+ g6n2m+bNcvXpz3c5ufsbzHwDdqjrI3moo7lLn4IROo5l8o3+DvleXPtWwLeKA6GC
81+ xec/HqKIzqxthuTRT9ekVpPzgtcojxVMg9SjuBN5k3WlMRP/+L0WXMA7Nf7F9YEp
82+ 06qUTOX7OKEwcJlRS9C730/6jQwNHSUxRP688npIl5F+egd7HC3ptkWI2exkgQvT
83+ dtfhA2Ra+wu1rX6M1R577wg9WHMI7xu8zzo3MtopQniTo1nkhWuZ0IWkWyMJYHI6
84+ sMbzB3DfAgMBAAECggEADm7K2ghWoxwsstQh8j+DaLzx9/dIHIJV2PHdd5FGVeRQ
85+ 6gS7MswQmHrBUrtsb4VMZ2iz/AJqkw+jScpGldH3pCc4XELsSfxNHbseO4TNIqjr
86+ 4LOKOLYU4bRc3I+8KGXIAI5JzrucTJemEVUCDrte8cjbmqExt+zTyNpyxsapworF
87+ v+vnSdv40d62f+cS1xvwB+ymLK/B/wZ/DemDCi8jsi7ou/M7l5xNCzjH4iMSLtOW
88+ fgEhejIBG9miMJWPiVpTXE3tMdNuN3OsWc4XXm2t4VRovlZdu30Fax1xWB+Locsv
89+ HlHKLOFc8g+jZh0TL2KCNjPffMcC7kHhW3afshpIsQKBgQDhyWUnkqd6FzbwIX70
90+ SnaMgKoUv5W/K5T+Sv/PA2CyN8Gu8ih/OsoNZSnI0uqe3XQIvvgN/Fq3wO1ttLzf
91+ z5B6ZC7REfTgcR0190gihk6f5rtcj7d6Fy/oG2CE8sDSXgPnpEaBjvJVgN5v/U2s
92+ HpVaidmHTyGLCfEszoeoy8jyrQKBgQDBX8caGylmzQLc6XNntZChlt3e18Nj8MPA
93+ DxWLcoqgdDoofLDQAmLl+vPKyDmhQjos5eas1jgmVVEM4ge+MysaVezvuLBsSnOh
94+ ihc0i63USU6i7YDE83DrCewCthpFHi/wW1S5FoCAzpVy8y99vwcqO4kOXcmf4O6Y
95+ uW6sMsjvOwKBgQDbFtqB+MtsLCSSBF61W6AHHD5tna4H75lG2623yXZF2NanFLF5
96+ K6muL9DI3ujtOMQETJJUt9+rWJjLEEsJ/dYa/SV0l7D/LKOEnyuu3JZkkLaTzZzi
97+ 6qcA2bfhqdCzEKlHV99WjkfV8hNlpex9rLuOPB8JLh7FVONicBGxF/UojQKBgDXs
98+ IlYaSuI6utilVKQP0kPtEPOKERc2VS+iRSy8hQGXR3xwwNFQSQm+f+sFCGT6VcSd
99+ W0TI+6Fc2xwPj38vP465dTentbKM1E+wdSYW6SMwSfhO6ECDbfJsst5Sr2Kkt1N7
100+ 9FUkfDLu6GfEfnK/KR1SurZB2u51R7NYyg7EnplvAoGAT0aTtOcck0oYN30g5mdf
101+ efqXPwg2wAPYeiec49EbfnteQQKAkqNfJ9K69yE2naf6bw3/5mCBsq/cXeuaBMII
102+ ylysUIRBqt2J0kWm2yCpFWR7H+Ilhdx9A7ZLCqYVt8e+vjO/BOI3cQDe2VPOLPSl
103+ q/1PY4iJviGKddtmfClH3v4=
104+ -----END PRIVATE KEY----- " ;
105+ }
106+
107+ protected function jwkKeyArray (): array
108+ {
109+ return [
110+ 'kty ' => 'RSA ' ,
111+ 'alg ' => 'RS256 ' ,
112+ 'kid ' => '066e52af-8884-4926-801d-032a276f9f2a ' ,
113+ 'use ' => 'sig ' ,
114+ 'e ' => 'AQAB ' ,
115+ 'n ' => 'qo1OmfNKec5S2zQC4SP9DrHuUR0VgCi6oqcGERz7zqO36hqk3A3R3aCgJkEjfnbnMuszRRKs45NbXoOp9pvmzXL16c93Obn7G8x8A3ao6yN5qKO5S5-CETqOZfKN_g75Xlz7VsC3igOhgsXnPx6iiM6sbYbk0U_XpFaT84LXKI8VTIPUo7gTeZN1pTET__i9FlzAOzX-xfWBKdOqlEzl-zihMHCZUUvQu99P-o0MDR0lMUT-vPJ6SJeRfnoHexwt6bZFiNnsZIEL03bX4QNkWvsLta1-jNUee-8IPVhzCO8bvM86NzLaKUJ4k6NZ5IVrmdCFpFsjCWByOrDG8wdw3w ' ,
116+ ];
117+ }
118+ }
0 commit comments