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