0
# Utilities and Security
1
2
Comprehensive utilities for cryptographic operations, XML processing, URL handling, certificate management, and security validation. These utilities provide the foundational security and processing capabilities that underpin all SAML operations.
3
4
## Capabilities
5
6
### Core SAML Utilities
7
8
Essential utility functions for SAML operations including cryptography, XML processing, URL handling, and time utilities.
9
10
```python { .api }
11
class OneLogin_Saml2_Utils:
12
# Class constants for XPath and time handling
13
RESPONSE_SIGNATURE_XPATH = '/samlp:Response/ds:Signature'
14
ASSERTION_SIGNATURE_XPATH = '/samlp:Response/saml:Assertion/ds:Signature'
15
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
16
ALLOWED_CLOCK_DRIFT = 300 # seconds
17
```
18
19
### URL and Parameter Handling
20
21
Secure URL processing and parameter management for SAML redirects and requests.
22
23
```python { .api }
24
@staticmethod
25
def redirect(url: str, parameters: dict = {}, request_data: dict = {}) -> str:
26
"""
27
Execute redirection with validation and parameter encoding.
28
29
Parameters:
30
- url: Target URL for redirection
31
- parameters: Query parameters to append
32
- request_data: HTTP request context
33
34
Returns:
35
Complete redirection URL with encoded parameters
36
"""
37
38
@staticmethod
39
def get_self_url_host(request_data: dict) -> str:
40
"""
41
Get protocol + current host + port.
42
43
Parameters:
44
- request_data: HTTP request information
45
46
Returns:
47
Base URL (e.g., "https://example.com:8443")
48
"""
49
50
@staticmethod
51
def get_self_url_no_query(request_data: dict) -> str:
52
"""
53
Get current URL without query string.
54
55
Parameters:
56
- request_data: HTTP request information
57
58
Returns:
59
URL without query parameters
60
"""
61
62
@staticmethod
63
def normalize_url(url: str) -> str:
64
"""
65
Normalize URL for comparison (lowercase netloc).
66
67
Parameters:
68
- url: URL to normalize
69
70
Returns:
71
Normalized URL string
72
"""
73
74
@staticmethod
75
def escape_url(url: str, lowercase_urlencoding: bool = False) -> str:
76
"""
77
Escape non-safe symbols in URLs.
78
79
Parameters:
80
- url: URL to escape
81
- lowercase_urlencoding: Use lowercase encoding for ADFS compatibility
82
83
Returns:
84
URL-encoded string
85
"""
86
```
87
88
### Base64 and Compression
89
90
Encoding and compression utilities for SAML message processing.
91
92
```python { .api }
93
@staticmethod
94
def b64encode(data: str) -> str:
95
"""
96
Base64 encoding with string compatibility.
97
98
Parameters:
99
- data: Data to encode
100
101
Returns:
102
Base64 encoded string
103
"""
104
105
@staticmethod
106
def b64decode(data: str) -> str:
107
"""
108
Base64 decoding with proper padding.
109
110
Parameters:
111
- data: Base64 encoded data
112
113
Returns:
114
Decoded string
115
"""
116
117
@staticmethod
118
def deflate_and_base64_encode(value: str) -> str:
119
"""
120
Zlib deflate and base64 encode (for HTTP-Redirect binding).
121
122
Parameters:
123
- value: String to compress and encode
124
125
Returns:
126
Deflated and base64 encoded string
127
"""
128
129
@staticmethod
130
def decode_base64_and_inflate(value: str, ignore_zip: bool = False) -> str:
131
"""
132
Base64 decode and zlib inflate (RFC1951).
133
134
Parameters:
135
- value: Encoded and compressed string
136
- ignore_zip: Skip inflation if True
137
138
Returns:
139
Decoded and inflated string
140
"""
141
```
142
143
### Certificate and Key Management
144
145
X.509 certificate handling and cryptographic key management for SAML security operations.
146
147
```python { .api }
148
@staticmethod
149
def format_cert(cert: str, heads: bool = True) -> str:
150
"""
151
Format X.509 certificate with optional headers/footers.
152
153
Parameters:
154
- cert: Certificate string or PEM data
155
- heads: Whether to include BEGIN/END CERTIFICATE headers
156
157
Returns:
158
Properly formatted certificate string
159
"""
160
161
@staticmethod
162
def format_private_key(key: str, heads: bool = True) -> str:
163
"""
164
Format private key (RSA or PKCS#8) with headers.
165
166
Parameters:
167
- key: Private key string or PEM data
168
- heads: Whether to include BEGIN/END headers
169
170
Returns:
171
Properly formatted private key string
172
"""
173
174
@staticmethod
175
def calculate_x509_fingerprint(x509_cert: str, alg: str = 'sha1') -> str:
176
"""
177
Calculate certificate fingerprint.
178
179
Parameters:
180
- x509_cert: X.509 certificate string
181
- alg: Hash algorithm (sha1, sha256, sha384, sha512)
182
183
Returns:
184
Lowercase fingerprint string without colons
185
"""
186
187
@staticmethod
188
def format_finger_print(fingerprint: str) -> str:
189
"""
190
Format fingerprint by removing colons and converting to lowercase.
191
192
Parameters:
193
- fingerprint: Fingerprint with or without colons
194
195
Returns:
196
Formatted fingerprint string
197
"""
198
```
199
200
### Digital Signatures
201
202
XML digital signature creation and validation with comprehensive security checks.
203
204
```python { .api }
205
@staticmethod
206
def add_sign(xml: str, key: str, cert: str, debug: bool = False, sign_algorithm: str = OneLogin_Saml2_Constants.RSA_SHA256, digest_algorithm: str = OneLogin_Saml2_Constants.SHA256) -> str:
207
"""
208
Add XML digital signature to SAML documents.
209
210
Parameters:
211
- xml: XML document to sign
212
- key: Private key for signing
213
- cert: X.509 certificate
214
- debug: Enable debug mode
215
- sign_algorithm: Signature algorithm (default: RSA-SHA256)
216
- digest_algorithm: Digest algorithm (default: SHA256)
217
218
Returns:
219
Signed XML document
220
"""
221
222
@staticmethod
223
def validate_sign(xml: str, cert: str = None, fingerprint: str = None, fingerprintalg: str = 'sha1', validatecert: bool = False, debug: bool = False, xpath: str = None, multicerts: list = None, raise_exceptions: bool = False) -> bool:
224
"""
225
Validate XML signatures with multiple certificate support.
226
227
Parameters:
228
- xml: XML document to validate
229
- cert: X.509 certificate for validation
230
- fingerprint: Certificate fingerprint
231
- fingerprintalg: Fingerprint algorithm
232
- validatecert: Whether to validate certificate
233
- debug: Enable debug mode
234
- xpath: Specific XPath for signature element
235
- multicerts: List of certificates to try
236
- raise_exceptions: Whether to raise validation exceptions
237
238
Returns:
239
True if signature is valid
240
"""
241
242
@staticmethod
243
def validate_binary_sign(signed_query: str, signature: str, cert: str = None, algorithm: str = OneLogin_Saml2_Constants.RSA_SHA256, debug: bool = False) -> bool:
244
"""
245
Validate binary signatures (for GET requests).
246
247
Parameters:
248
- signed_query: Query string that was signed
249
- signature: Base64 encoded signature
250
- cert: X.509 certificate
251
- algorithm: Signature algorithm
252
- debug: Enable debug mode
253
254
Returns:
255
True if signature is valid
256
"""
257
```
258
259
### Encryption and Decryption
260
261
XML encryption handling for assertions and NameID protection.
262
263
```python { .api }
264
@staticmethod
265
def decrypt_element(encrypted_data: str, key: str, debug: bool = False, inplace: bool = False) -> str:
266
"""
267
Decrypt XML encrypted elements.
268
269
Parameters:
270
- encrypted_data: Encrypted XML element
271
- key: Private key for decryption
272
- debug: Enable debug mode
273
- inplace: Whether to decrypt in-place
274
275
Returns:
276
Decrypted XML element
277
"""
278
279
@staticmethod
280
def generate_name_id(value: str, sp_nq: str, sp_format: str = None, cert: str = None, debug: bool = False, nq: str = None) -> str:
281
"""
282
Generate NameID with optional encryption.
283
284
Parameters:
285
- value: NameID value
286
- sp_nq: SP Name Qualifier
287
- sp_format: NameID format
288
- cert: Certificate for encryption
289
- debug: Enable debug mode
290
- nq: Name Qualifier
291
292
Returns:
293
NameID XML element (encrypted if cert provided)
294
"""
295
```
296
297
### Time and Date Utilities
298
299
SAML timestamp handling with proper format conversion and validation.
300
301
```python { .api }
302
@staticmethod
303
def parse_time_to_SAML(time: int) -> str:
304
"""
305
Convert UNIX timestamp to SAML2 timestamp format.
306
307
Parameters:
308
- time: UNIX timestamp
309
310
Returns:
311
SAML timestamp string (ISO 8601 format)
312
"""
313
314
@staticmethod
315
def parse_SAML_to_time(timestr: str) -> int:
316
"""
317
Convert SAML2 timestamp to UNIX timestamp.
318
319
Parameters:
320
- timestr: SAML timestamp string
321
322
Returns:
323
UNIX timestamp integer
324
"""
325
326
@staticmethod
327
def now() -> int:
328
"""
329
Get current UNIX timestamp.
330
331
Returns:
332
Current timestamp as integer
333
"""
334
335
@staticmethod
336
def parse_duration(duration: str, timestamp: int = None) -> int:
337
"""
338
Interpret ISO8601 duration relative to timestamp.
339
340
Parameters:
341
- duration: ISO8601 duration string (e.g., "PT30M")
342
- timestamp: Base timestamp (default: current time)
343
344
Returns:
345
Resulting timestamp after adding duration
346
"""
347
```
348
349
### Utility Methods
350
351
Additional utility functions for ID generation and session management.
352
353
```python { .api }
354
@staticmethod
355
def generate_unique_id() -> str:
356
"""
357
Generate unique string for assertions using UUID and SHA1.
358
359
Returns:
360
Unique identifier string
361
"""
362
363
@staticmethod
364
def get_status(dom: str) -> dict:
365
"""
366
Extract status information from SAML Response.
367
368
Parameters:
369
- dom: SAML Response XML document
370
371
Returns:
372
Dictionary with status code and message
373
"""
374
375
@staticmethod
376
def delete_local_session(callback: callable = None) -> None:
377
"""
378
Delete local session with optional callback.
379
380
Parameters:
381
- callback: Optional function to call during session deletion
382
"""
383
```
384
385
## XML Processing and Security
386
387
Secure XML processing utilities with protection against XML vulnerabilities and comprehensive XPath operations.
388
389
```python { .api }
390
class OneLogin_Saml2_XML:
391
@staticmethod
392
def to_string(xml: object, **kwargs) -> str:
393
"""
394
Serialize XML element to encoded string with namespace cleanup.
395
396
Parameters:
397
- xml: XML element or document
398
- **kwargs: Additional serialization options
399
400
Returns:
401
Encoded XML string
402
"""
403
404
@staticmethod
405
def to_etree(xml: str) -> object:
406
"""
407
Parse XML from string/bytes to lxml Element with security.
408
409
Parameters:
410
- xml: XML string or bytes
411
412
Returns:
413
lxml Element object
414
415
Security Features:
416
- Forbids DTD processing
417
- Forbids entity resolution
418
- Strips comments and processing instructions
419
"""
420
421
@staticmethod
422
def validate_xml(xml: str, schema: str, debug: bool = False) -> bool:
423
"""
424
Validate XML against XSD schema files.
425
426
Parameters:
427
- xml: XML document to validate
428
- schema: XSD schema file path
429
- debug: Enable debug output
430
431
Returns:
432
True if XML is valid against schema
433
"""
434
```
435
436
### XPath Operations
437
438
Execute XPath queries with SAML namespace support and security features.
439
440
```python { .api }
441
@staticmethod
442
def query(dom: object, query: str, context: object = None, tagid: str = None) -> list:
443
"""
444
Execute XPath queries with SAML namespace support.
445
446
Parameters:
447
- dom: XML document or element
448
- query: XPath expression
449
- context: XPath context element
450
- tagid: Specific tag ID for context
451
452
Returns:
453
List of matching XML elements
454
"""
455
456
@staticmethod
457
def extract_tag_text(xml: str, tagname: str) -> str:
458
"""
459
Extract specific tag content as text.
460
461
Parameters:
462
- xml: XML document string
463
- tagname: Tag name to extract
464
465
Returns:
466
Tag text content
467
"""
468
469
@staticmethod
470
def element_text(node: object) -> str:
471
"""
472
Get element text content with comment stripping.
473
474
Parameters:
475
- node: XML element node
476
477
Returns:
478
Clean text content
479
"""
480
```
481
482
## SAML Constants and Specifications
483
484
Comprehensive constants for SAML 2.0 specifications, algorithms, and URIs.
485
486
```python { .api }
487
class OneLogin_Saml2_Constants:
488
# Clock drift allowance for timestamp validation
489
ALLOWED_CLOCK_DRIFT = 300 # seconds
490
```
491
492
### NameID Formats
493
494
Standard NameID format identifiers for different identity representations.
495
496
```python { .api }
497
# NameID Format Constants
498
NAMEID_EMAIL_ADDRESS = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
499
NAMEID_X509_SUBJECT_NAME = 'urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName'
500
NAMEID_WINDOWS_DOMAIN_QUALIFIED_NAME = 'urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName'
501
NAMEID_UNSPECIFIED = 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
502
NAMEID_KERBEROS = 'urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos'
503
NAMEID_ENTITY = 'urn:oasis:names:tc:SAML:2.0:nameid-format:entity'
504
NAMEID_TRANSIENT = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
505
NAMEID_PERSISTENT = 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
506
NAMEID_ENCRYPTED = 'urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted'
507
```
508
509
### Attribute Name Formats
510
511
Standard attribute name format identifiers for SAML attributes.
512
513
```python { .api }
514
# Attribute Name Format Constants
515
ATTRNAME_FORMAT_UNSPECIFIED = 'urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified'
516
ATTRNAME_FORMAT_URI = 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
517
ATTRNAME_FORMAT_BASIC = 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic'
518
```
519
520
### SAML Bindings
521
522
Protocol bindings for SAML message transport.
523
524
```python { .api }
525
# SAML Binding Constants
526
BINDING_HTTP_POST = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
527
BINDING_HTTP_REDIRECT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
528
BINDING_HTTP_ARTIFACT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'
529
BINDING_SOAP = 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP'
530
BINDING_DEFLATE = 'urn:oasis:names:tc:SAML:2.0:bindings:URL-Encoding:DEFLATE'
531
```
532
533
### XML Namespaces
534
535
Standard XML namespace URIs for SAML processing.
536
537
```python { .api }
538
# SAML Namespaces
539
NS_SAML = 'urn:oasis:names:tc:SAML:2.0:assertion'
540
NS_SAMLP = 'urn:oasis:names:tc:SAML:2.0:protocol'
541
NS_SOAP = 'http://schemas.xmlsoap.org/soap/envelope/'
542
NS_MD = 'urn:oasis:names:tc:SAML:2.0:metadata'
543
NS_XS = 'http://www.w3.org/2001/XMLSchema'
544
NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
545
NS_XENC = 'http://www.w3.org/2001/04/xmlenc#'
546
NS_DS = 'http://www.w3.org/2000/09/xmldsig#'
547
548
# Namespace Prefixes
549
NS_PREFIX_SAML = 'saml'
550
NS_PREFIX_SAMLP = 'samlp'
551
NS_PREFIX_MD = 'md'
552
NS_PREFIX_XS = 'xs'
553
NS_PREFIX_XSI = 'xsi'
554
NS_PREFIX_XSD = 'xsd'
555
NS_PREFIX_XENC = 'xenc'
556
NS_PREFIX_DS = 'ds'
557
558
# Namespace Map (Prefix:Namespace Mappings)
559
NSMAP = {
560
NS_PREFIX_SAMLP: NS_SAMLP,
561
NS_PREFIX_SAML: NS_SAML,
562
NS_PREFIX_DS: NS_DS,
563
NS_PREFIX_XENC: NS_XENC,
564
NS_PREFIX_MD: NS_MD
565
}
566
```
567
568
### Authentication Context
569
570
Authentication context class references for different authentication methods.
571
572
```python { .api }
573
# Authentication Context Constants
574
AC_UNSPECIFIED = 'urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified'
575
AC_PASSWORD = 'urn:oasis:names:tc:SAML:2.0:ac:classes:Password'
576
AC_PASSWORD_PROTECTED = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
577
AC_X509 = 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'
578
AC_SMARTCARD = 'urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard'
579
AC_KERBEROS = 'urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos'
580
```
581
582
### Subject Confirmation
583
584
Subject confirmation method identifiers for assertion validation.
585
586
```python { .api }
587
# Subject Confirmation Methods
588
CM_BEARER = 'urn:oasis:names:tc:SAML:2.0:cm:bearer'
589
CM_HOLDER_KEY = 'urn:oasis:names:tc:SAML:2.0:cm:holder-of-key'
590
CM_SENDER_VOUCHES = 'urn:oasis:names:tc:SAML:2.0:cm:sender-vouches'
591
```
592
593
### Status Codes
594
595
SAML response status codes for success and error conditions.
596
597
```python { .api }
598
# Status Code Constants
599
STATUS_SUCCESS = 'urn:oasis:names:tc:SAML:2.0:status:Success'
600
STATUS_REQUESTER = 'urn:oasis:names:tc:SAML:2.0:status:Requester'
601
STATUS_RESPONDER = 'urn:oasis:names:tc:SAML:2.0:status:Responder'
602
STATUS_VERSION_MISMATCH = 'urn:oasis:names:tc:SAML:2.0:status:VersionMismatch'
603
STATUS_NO_PASSIVE = 'urn:oasis:names:tc:SAML:2.0:status:NoPassive'
604
STATUS_PARTIAL_LOGOUT = 'urn:oasis:names:tc:SAML:2.0:status:PartialLogout'
605
STATUS_PROXY_COUNT_EXCEEDED = 'urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded'
606
```
607
608
### Cryptographic Algorithms
609
610
Algorithm identifiers for digital signatures, encryption, and hashing.
611
612
```python { .api }
613
# Hash Algorithms
614
SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1'
615
SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256'
616
SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#sha384'
617
SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512'
618
619
# Signature Algorithms
620
RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
621
RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
622
RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
623
RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
624
625
# Encryption Algorithms
626
AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
627
AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'
628
AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
629
RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'
630
RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p'
631
632
# Deprecated Algorithms (security warnings)
633
DEPRECATED_ALGORITHMS = [DSA_SHA1, RSA_SHA1, SHA1]
634
```
635
636
## Error Handling
637
638
Comprehensive error classes with detailed error codes for different failure scenarios.
639
640
```python { .api }
641
class OneLogin_Saml2_Error(Exception):
642
def __init__(self, message: str, code: int = 0, errors: list = None):
643
"""
644
General SAML error with categorized error codes.
645
646
Parameters:
647
- message: Error description
648
- code: Numeric error code
649
- errors: List of additional error details
650
"""
651
652
class OneLogin_Saml2_ValidationError(OneLogin_Saml2_Error):
653
def __init__(self, message: str, code: int = 0, errors: list = None):
654
"""
655
SAML validation error with specific validation codes.
656
657
Parameters:
658
- message: Validation error description
659
- code: Validation error code
660
- errors: List of validation failure details
661
"""
662
```
663
664
### Error Code Categories
665
666
**General Error Codes:**
667
- `SETTINGS_FILE_NOT_FOUND` - Configuration file missing
668
- `SETTINGS_INVALID` - Invalid configuration values
669
- `CERT_NOT_FOUND` - Certificate not found
670
- `SAML_RESPONSE_NOT_FOUND` - SAML Response not found
671
- `SAML_SINGLE_LOGOUT_NOT_SUPPORTED` - SLO not supported
672
- `REDIRECT_INVALID_URL` - Invalid redirect URL
673
674
**Validation Error Codes:**
675
- `UNSUPPORTED_SAML_VERSION` - Unsupported SAML version
676
- `MISSING_ID` - Missing ID attribute
677
- `WRONG_NUMBER_OF_ASSERTIONS` - Incorrect assertion count
678
- `STATUS_CODE_IS_NOT_SUCCESS` - Non-success status
679
- `INVALID_SIGNATURE` - Invalid digital signature
680
- `ASSERTION_EXPIRED` - Assertion expired
681
- `WRONG_AUDIENCE` - Wrong audience restriction
682
- `WRONG_ISSUER` - Wrong issuer verification
683
- `RESPONSE_EXPIRED` - SAML Response expired
684
- `DEPRECATED_SIGNATURE_METHOD` - Deprecated signature method used
685
- `DEPRECATED_DIGEST_METHOD` - Deprecated digest method used
686
687
## Secure XML Processing
688
689
XML parsing functions with comprehensive security protections against XML vulnerabilities.
690
691
```python { .api }
692
def parse(source: str, parser: object = None, base_url: str = None, forbid_dtd: bool = True, forbid_entities: bool = True) -> object:
693
"""
694
Secure XML document parsing with vulnerability protection.
695
696
Parameters:
697
- source: XML source (file, URL, or string)
698
- parser: Custom XML parser
699
- base_url: Base URL for relative references
700
- forbid_dtd: Prevent DTD processing (security)
701
- forbid_entities: Prevent entity expansion (security)
702
703
Returns:
704
Parsed XML document tree
705
706
Security Features:
707
- DTD processing disabled
708
- Entity expansion disabled
709
- Network access disabled
710
- Comment and PI removal
711
"""
712
713
def fromstring(text: str, parser: object = None, base_url: str = None, forbid_dtd: bool = True, forbid_entities: bool = True) -> object:
714
"""
715
Secure XML string parsing with security protections.
716
717
Parameters:
718
- text: XML string to parse
719
- parser: Custom XML parser
720
- base_url: Base URL for relative references
721
- forbid_dtd: Prevent DTD processing
722
- forbid_entities: Prevent entity expansion
723
724
Returns:
725
Parsed XML element
726
"""
727
```
728
729
## Compatibility Functions
730
731
Python 2/3 compatibility utilities for consistent string and byte handling across versions.
732
733
```python { .api }
734
def utf8(data: str) -> str:
735
"""
736
Convert data to UTF-8 string with version compatibility.
737
738
Parameters:
739
- data: String or bytes data
740
741
Returns:
742
UTF-8 encoded string (Python version appropriate)
743
"""
744
745
def to_string(data: str) -> str:
746
"""
747
Convert data to string with proper encoding.
748
749
Parameters:
750
- data: String or bytes data
751
752
Returns:
753
String in appropriate format for Python version
754
"""
755
756
def to_bytes(data: str) -> bytes:
757
"""
758
Convert data to bytes with UTF-8 encoding.
759
760
Parameters:
761
- data: String data
762
763
Returns:
764
UTF-8 encoded bytes
765
"""
766
```
767
768
## Usage Patterns
769
770
### Certificate Validation
771
```python
772
from onelogin.saml2.utils import OneLogin_Saml2_Utils
773
774
# Validate XML signature with certificate
775
is_valid = OneLogin_Saml2_Utils.validate_sign(
776
xml_document,
777
cert=idp_certificate,
778
validatecert=True,
779
raise_exceptions=True
780
)
781
782
# Calculate certificate fingerprint
783
fingerprint = OneLogin_Saml2_Utils.calculate_x509_fingerprint(
784
certificate,
785
alg='sha256'
786
)
787
```
788
789
### Time Handling
790
```python
791
# Convert timestamps between formats
792
saml_time = OneLogin_Saml2_Utils.parse_time_to_SAML(time.time())
793
unix_time = OneLogin_Saml2_Utils.parse_SAML_to_time(saml_timestamp)
794
795
# Parse ISO8601 duration
796
expiry_time = OneLogin_Saml2_Utils.parse_duration("PT30M") # 30 minutes from now
797
```
798
799
### Secure XML Processing
800
```python
801
from onelogin.saml2.xml_utils import OneLogin_Saml2_XML
802
from onelogin.saml2.xmlparser import fromstring
803
804
# Secure XML parsing
805
xml_element = fromstring(xml_string, forbid_dtd=True, forbid_entities=True)
806
807
# XPath queries with SAML namespaces
808
assertions = OneLogin_Saml2_XML.query(xml_element, '//saml:Assertion')
809
810
# XML validation against schema
811
is_valid = OneLogin_Saml2_XML.validate_xml(xml_doc, 'saml-schema-assertion-2.0.xsd')
812
```
813
814
### Error Handling
815
```python
816
from onelogin.saml2.errors import OneLogin_Saml2_Error, OneLogin_Saml2_ValidationError
817
818
try:
819
auth.process_response()
820
except OneLogin_Saml2_ValidationError as e:
821
print(f"Validation failed: {e} (Code: {e.code})")
822
except OneLogin_Saml2_Error as e:
823
print(f"SAML error: {e} (Code: {e.code})")
824
```