Methods

Source

LineCode
1
<?php
2
3
namespace AuthStack\SAMLServiceProvider\Model;
4
5
use LightSaml\Credential\KeyHelper;
6
use LightSaml\Credential\X509Certificate;
7
use LightSaml\Model\Context\SerializationContext;
8
use LightSaml\Model\Metadata\AssertionConsumerService;
9
use LightSaml\Model\Metadata\ContactPerson;
10
use LightSaml\Model\Metadata\EntityDescriptor;
11
use LightSaml\Model\Metadata\KeyDescriptor;
12
use LightSaml\Model\Metadata\SingleLogoutService;
13
use LightSaml\Model\Metadata\SpSsoDescriptor;
14
use LightSaml\Model\XmlDSig\SignatureWriter;
15
use RobRichards\XMLSecLibs\XMLSecurityKey;
16
17
class ServiceProvider
18
{
19
    /**
20
     * @return null|string
21
     */
22
    public function getEntityId(): ?string
23
    {
24
        return config('saml.sp.EntityId');
25
    }
26
27
    /**
28
     * @return string
29
     */
30
    public function getIdPEntityId(): string
31
    {
32
        return config('saml.sp.IdentityProvider');
33
    }
34
35
    /**
36
     * @return string
37
     */
38
    public function getBaseUrl(): string
39
    {
40
        return config('saml.sp.baseUrl');
41
    }
42
43
    /**
44
     * @return null|string
45
     */
46
    public function getNameIdFormat(): ?string
47
    {
48
        return config('saml.sp.nameIdFormat');
49
    }
50
51
    /**
52
     * @return bool
53
     */
54
    public function wantsSignedMessages(): bool
55
    {
56
        return config('saml.sp.wantsSignedMessages');
57
    }
58
59
    /**
60
     * @return bool
61
     */
62
    public function wantsSignedAssertions(): bool
63
    {
64
        return config('saml.sp.wantsSignedAssertions');
65
    }
66
67
    /**
68
     * @return bool
69
     */
70
    public function wantsEncryptedAssertions(): bool
71
    {
72
        return config('saml.sp.wantsEncryptedAssertions');
73
    }
74
75
    /**
76
     * @return string
77
     */
78
    public function getACSPath(): string
79
    {
80
        return config('saml.sp.AssertionConsumerService.location');
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    public function getACSUrl(): string
87
    {
88
        return sprintf("%s%s", $this->getBaseUrl(), $this->getACSPath());
89
    }
90
91
    /**
92
     * @return string
93
     */
94
    public function getACSBinding(): string
95
    {
96
        return config('saml.sp.AssertionConsumerService.binding');
97
    }
98
99
    /**
100
     * @return string
101
     */
102
    public function getLogoutServicePath(): string
103
    {
104
        return config('saml.sp.SLO.location');
105
    }
106
107
    /**
108
     * @return string
109
     */
110
    public function getLogoutServiceUrl(): string
111
    {
112
        return sprintf("%s%s", $this->getBaseUrl(), $this->getLogoutServicePath());
113
    }
114
115
    /**
116
     * @return string
117
     */
118
    public function getLogoutServiceBinding(): string
119
    {
120
        return config('saml.sp.SLO.binding');
121
    }
122
123
    public function validateSignature(): bool
124
    {
125
        return config('saml.sp.validate.signature');
126
    }
127
128
    /**
129
     * @return bool
130
     */
131
    public function validateStatus(): bool
132
    {
133
        return config('saml.sp.validate.status');
134
    }
135
136
    /**
137
     * @return bool
138
     */
139
    public function validateIssuer(): bool
140
    {
141
        return config('saml.sp.validate.issuer');
142
    }
143
144
    /**
145
     * @return bool
146
     */
147
    public function validateDestination(): bool
148
    {
149
        return config('saml.sp.validate.destination');
150
    }
151
152
    /**
153
     * @return bool
154
     */
155
    public function validateLifetime(): bool
156
    {
157
        return config('saml.sp.validate.lifetime');
158
    }
159
160
    /**
161
     * @return \DateTime
162
     */
163
    public function getUpperDT(): \DateTime
164
    {
165
        return new \DateTime($this->getValidationUpperTimeBoundary(), new \DateTimeZone('UTC'));
166
    }
167
168
    /**
169
     * @return \DateTime
170
     */
171
    public function getLowerDT(): \DateTime
172
    {
173
        return new \DateTime($this->getValidationLowerTimeBoundary(), new \DateTimeZone('UTC'));
174
    }
175
176
    /**
177
     * @return string
178
     */
179
    public function getValidationUpperTimeBoundary(): string
180
    {
181
        return config('saml.sp.validate.upper');
182
    }
183
184
    /**
185
     * @return string
186
     */
187
    public function getValidationLowerTimeBoundary(): string
188
    {
189
        return config('saml.sp.validate.lower');
190
    }
191
192
    /**
193
     * @return array
194
     */
195
    public function getSigningKey(): array
196
    {
197
        return config('saml.sp.keys.signing', []);
198
    }
199
200
    /**
201
     * @return SignatureWriter
202
     */
203
    public function getSignatureWriter(): SignatureWriter
204
    {
205
        $x509 = new X509Certificate();
206
207
        $x509->setData($this->getSigningKeyX509Cert());
208
209
        $priv = KeyHelper::createPrivateKey(
210
            $this->getSigningPrivateKey(),
211
            $this->getSigningPrivateKeyPassphrase(),
212
            false,
213
            $this->getSigningDigestAlgorithm()
214
        );
215
216
        return new SignatureWriter($x509, $priv);
217
    }
218
219
    /**
220
     * @return XMLSecurityKey
221
     */
222
    public function getSigningPublicKey(): XMLSecurityKey
223
    {
224
        return KeyHelper::createPublicKey(
225
            (new X509Certificate())->setData($this->getSigningKeyX509Cert())
226
        );
227
    }
228
229
    /**
230
     * @return string
231
     */
232
    public function getSigningKeyX509Cert(): string
233
    {
234
        return config('saml.sp.keys.signing.x509');
235
    }
236
237
    /**
238
     * @return string
239
     */
240
    public function getSigningPrivateKey(): string
241
    {
242
        return config('saml.sp.keys.signing.private');
243
    }
244
245
    /**
246
     * @return null|string
247
     */
248
    public function getSigningPrivateKeyPassphrase(): ?string
249
    {
250
        return config('saml.sp.keys.signing.passphrase');
251
    }
252
253
    /**
254
     * @return string
255
     */
256
    public function getSigningDigestAlgorithm(): string
257
    {
258
        return config('saml.sp.keys.signing.algorithm');
259
    }
260
261
    /**
262
     * @return array
263
     */
264
    public function getDecryptionKey(): array
265
    {
266
        return config('saml.sp.keys.encryption', []);
267
    }
268
269
    /**
270
     * @return XMLSecurityKey
271
     */
272
    public function getDecrypter(): XMLSecurityKey
273
    {
274
        return KeyHelper::createPrivateKey(
275
            $this->getDecryptionKeyPrivateKey(),
276
            $this->getDecryptionKeyPassphrase(),
277
            false,
278
            $this->getDecryptionKeyAlgorithm()
279
        );
280
    }
281
282
    /**
283
     * @return null|string
284
     */
285
    public function getDecryptionKeyPrivateKey(): ?string
286
    {
287
        return config('saml.sp.keys.encryption.private');
288
    }
289
290
    /**
291
     * @return null|string
292
     */
293
    public function getDecryptionKeyPassphrase(): ?string
294
    {
295
        return config('saml.sp.keys.encryption.passphrase');
296
    }
297
298
    /**
299
     * @return null|string
300
     */
301
    public function getDecryptionKeyAlgorithm(): ?string
302
    {
303
        return config('saml.sp.keys.encryption.algorithm');
304
    }
305
306
    /**
307
     * @return array
308
     */
309
    public function getContacts(): array
310
    {
311
        return config('saml.sp.contacts', []);
312
    }
313
314
    /**
315
     * @return array
316
     */
317
    public function getKeys(): array
318
    {
319
        return config('saml.sp.keys', []);
320
    }
321
322
    /**
323
     * @return string
324
     */
325
    public function getMetadataXML(): string
326
    {
327
        $entity = new EntityDescriptor($this->getEntityId());
328
        $sp = new SpSsoDescriptor();
329
330
        if($this->wantsSignedAssertions())
331
        {
332
            $sp->setWantAssertionsSigned(true);
333
        }
334
335
        $sp->addNameIDFormat($this->getNameIdFormat());
336
337
        //--------------------------------------------------------------------------------------------------------------
338
        // Add contacts
339
        //--------------------------------------------------------------------------------------------------------------
340
        collect($this->getContacts())->map(function($contact) use (&$sp)
341
        {
342
            $sp->addContactPerson(
343
                (new ContactPerson())
344
                    ->setGivenName(isset($contact['givenName']) ?? 'N/A')
345
                    ->setSurName(isset($contact['surName']) ?? 'N/A')
346
                    ->setContactType(isset($contact['contactType']) ?? 'N/A')
347
                    ->setCompany(isset($contact['company']) ?? 'N/A')
348
                    ->setEmailAddress(isset($contact['emailAddress']) ?? 'N/A')
349
                    ->setTelephoneNumber(isset($contact['telephoneNumber']) ?? 'N/A')
350
            );
351
        });
352
353
        //--------------------------------------------------------------------------------------------------------------
354
        // Add Assertion Consumer Service
355
        //--------------------------------------------------------------------------------------------------------------
356
        $sp->addAssertionConsumerService(
357
            (new AssertionConsumerService())
358
                ->setIsDefault(true)
359
                ->setBinding($this->getACSBinding())
360
                ->setLocation($this->getACSUrl())
361
        );
362
363
        //--------------------------------------------------------------------------------------------------------------
364
        // Add Single Logout Service
365
        //--------------------------------------------------------------------------------------------------------------
366
        $sp->addSingleLogoutService(
367
            (new SingleLogoutService())
368
                ->setBinding($this->getLogoutServiceBinding())
369
                ->setLocation($this->getLogoutServiceUrl())
370
        );
371
372
        //--------------------------------------------------------------------------------------------------------------
373
        // Set keys (signing and encryption)
374
        //--------------------------------------------------------------------------------------------------------------
375
        collect($this->getKeys())->map(function($item, $usage) use (&$sp)
376
        {
377
            $sp->addKeyDescriptor(
378
                (new KeyDescriptor())
379
                    ->setUse($usage)
380
                    ->setCertificate((new X509Certificate())->setData($item['x509']))
381
            );
382
        });
383
384
        $entity->addItem($sp);
385
386
        $context = new SerializationContext();
387
388
        $entity->serialize($context->getDocument(), $context);
389
390
        return $context->getDocument()->saveXML();
391
    }
392
}