0
# Python3-OpenID
1
2
A comprehensive Python library implementing the OpenID authentication protocol for both consumers (relying parties) and servers (identity providers). This library provides complete OpenID 1.0, 1.1, and 2.0 support, enabling decentralized identity authentication for web applications with multiple storage backends and extension support.
3
4
## Package Information
5
6
- **Package Name**: python3-openid
7
- **Language**: Python
8
- **Installation**: `pip install python3-openid`
9
- **Optional Dependencies**: `pip install python3-openid[mysql]` or `pip install python3-openid[postgresql]`
10
11
## Core Imports
12
13
```python
14
import openid
15
```
16
17
For consumer (relying party) implementations:
18
19
```python
20
from openid.consumer import consumer
21
from openid.consumer.discover import discover
22
from openid.store.filestore import FileOpenIDStore
23
```
24
25
For server (identity provider) implementations:
26
27
```python
28
from openid.server import server
29
from openid.store.filestore import FileOpenIDStore
30
```
31
32
For extensions:
33
34
```python
35
from openid.extensions import sreg, ax
36
```
37
38
## Basic Usage
39
40
### Consumer Implementation
41
42
```python
43
from openid.consumer import consumer
44
from openid.store.filestore import FileOpenIDStore
45
from openid.consumer.discover import discover
46
47
# Initialize consumer with session and store
48
store = FileOpenIDStore('/tmp/openid_store')
49
openid_consumer = consumer.Consumer({}, store)
50
51
# Start authentication
52
user_url = "https://example.com/user"
53
auth_request = openid_consumer.begin(user_url)
54
55
# Redirect user to identity provider
56
redirect_url = auth_request.redirectURL(
57
realm="https://mysite.com",
58
return_to="https://mysite.com/openid/complete"
59
)
60
61
# Handle return from identity provider
62
query = request.GET # From your web framework
63
current_url = "https://mysite.com/openid/complete"
64
response = openid_consumer.complete(query, current_url)
65
66
if response.status == consumer.SUCCESS:
67
print(f"Authentication successful for {response.identity_url}")
68
elif response.status == consumer.FAILURE:
69
print(f"Authentication failed: {response.message}")
70
```
71
72
### Server Implementation
73
74
```python
75
from openid.server import server
76
from openid.store.filestore import FileOpenIDStore
77
78
# Initialize server with store
79
store = FileOpenIDStore('/tmp/openid_store')
80
openid_server = server.Server(store, op_endpoint="https://myop.com/openid")
81
82
# Handle incoming request
83
query = request.GET # From your web framework
84
openid_request = openid_server.decodeRequest(query)
85
86
if openid_request.mode == "checkid_setup":
87
# Authenticate user and create response
88
if user_authenticated:
89
openid_response = openid_request.answer(
90
allow=True,
91
server_url="https://myop.com/openid",
92
identity=user_identity_url,
93
claimed_id=user_claimed_id
94
)
95
else:
96
# Redirect to login page
97
pass
98
```
99
100
## Architecture
101
102
The library follows a modular architecture with clear separation between consumer and server functionality:
103
104
- **Consumer Package**: Handles relying party operations including discovery, authentication requests, and response processing
105
- **Server Package**: Manages identity provider operations including request handling, user authentication, and response generation
106
- **Store Layer**: Provides pluggable storage backends for associations and nonces (file, memory, SQL databases)
107
- **Extensions**: Implements OpenID extensions like Simple Registration (SREG) and Attribute Exchange (AX)
108
- **Message Layer**: Handles OpenID protocol message parsing, namespace management, and encoding
109
- **Discovery**: Implements Yadis and HTML-based OpenID discovery protocols
110
- **Cryptographic Utilities**: Provides association management, Diffie-Hellman key exchange, and message signing
111
112
## Capabilities
113
114
### Consumer Authentication
115
116
Complete OpenID consumer implementation for web applications acting as relying parties. Handles the full authentication flow from discovery through response processing with support for immediate and setup modes.
117
118
```python { .api }
119
class Consumer:
120
def __init__(self, session, store, consumer_class=None): ...
121
def begin(self, user_url, anonymous=False): ...
122
def complete(self, query, current_url): ...
123
124
class AuthRequest:
125
def redirectURL(self, realm, return_to=None, immediate=False): ...
126
def formMarkup(self, realm, return_to=None, immediate=False, form_tag_attrs=None): ...
127
def addExtension(self, extension_request): ...
128
```
129
130
[Consumer Authentication](./consumer-auth.md)
131
132
### OpenID Discovery
133
134
Comprehensive OpenID discovery system implementing Yadis, XRDS, and HTML-based discovery protocols. Handles service endpoint detection, URL normalization, and service type preference ordering for reliable identity provider discovery.
135
136
```python { .api }
137
class OpenIDServiceEndpoint:
138
def usesExtension(self, extension_uri): ...
139
def preferredNamespace(self): ...
140
def supportsType(self, type_uri): ...
141
def compatibilityMode(self): ...
142
def isOPIdentifier(self): ...
143
144
def discoverURI(uri): ...
145
def normalizeURL(url): ...
146
```
147
148
[OpenID Discovery](./discovery.md)
149
150
### Server Implementation
151
152
Complete OpenID server functionality for identity providers. Handles association requests, authentication requests, and verification with support for multiple session types and response encoding formats.
153
154
```python { .api }
155
class Server:
156
def __init__(self, store, op_endpoint=None, signatoryClass=Signatory, encoderClass=SigningEncoder, decoderClass=Decoder): ...
157
def decodeRequest(self, query): ...
158
def encodeResponse(self, response): ...
159
def handleRequest(self, request): ...
160
161
class CheckIDRequest:
162
def answer(self, allow, server_url=None, identity=None, claimed_id=None): ...
163
def trustRootValid(self): ...
164
def returnToVerified(self): ...
165
```
166
167
[Server Implementation](./server-implementation.md)
168
169
### Storage Backends
170
171
Pluggable storage system for associations and nonces with multiple backend implementations. Supports file-based, in-memory, and SQL database storage with automatic cleanup of expired data.
172
173
```python { .api }
174
class OpenIDStore:
175
def storeAssociation(self, server_url, association): ...
176
def getAssociation(self, server_url, handle=None): ...
177
def removeAssociation(self, server_url, handle): ...
178
def useNonce(self, server_url, timestamp, salt): ...
179
180
class FileOpenIDStore(OpenIDStore): ...
181
class MemoryStore(OpenIDStore): ...
182
class SQLStore(OpenIDStore): ...
183
```
184
185
[Storage Backends](./storage-backends.md)
186
187
### OpenID Extensions
188
189
Implementation of standard OpenID extensions including Simple Registration (SREG) for basic profile data and Attribute Exchange (AX) for flexible attribute sharing between consumers and servers.
190
191
```python { .api }
192
class SRegRequest:
193
def __init__(self, required=None, optional=None, policy_url=None, sreg_ns_uri=ns_uri): ...
194
def requestField(self, field_name, required=False, strict=False): ...
195
def requestFields(self, field_names, required=False, strict=False): ...
196
197
class SRegResponse:
198
def get(self, field_name, default=None): ...
199
def items(self): ...
200
201
class FetchRequest:
202
def add(self, attribute): ...
203
def getRequiredAttrs(self): ...
204
205
class FetchResponse:
206
def getSingle(self, type_uri, default=None): ...
207
def get(self, type_uri): ...
208
```
209
210
[OpenID Extensions](./extensions.md)
211
212
### Association Management
213
214
Handles shared secrets between consumers and servers including creation, serialization, message signing, and expiration management. Supports HMAC-SHA1 and HMAC-SHA256 association types with plain-text and Diffie-Hellman session types.
215
216
```python { .api }
217
class Association:
218
def __init__(self, handle, secret, issued, lifetime, assoc_type): ...
219
def sign(self, pairs): ...
220
def signMessage(self, message): ...
221
def checkMessageSignature(self, message): ...
222
223
class SessionNegotiator:
224
def __init__(self, allowed_types): ...
225
def isAllowed(self, assoc_type, session_type): ...
226
def getAllowedType(self): ...
227
```
228
229
[Association Management](./association-management.md)
230
231
### Message Processing
232
233
OpenID protocol message handling with namespace management, encoding/decoding, and format conversion. Supports key-value form, URL encoding, and HTML form generation with proper namespace aliasing.
234
235
```python { .api }
236
class Message:
237
def __init__(self, openid_namespace=None): ...
238
def fromPostArgs(cls, args): ...
239
def fromKVForm(cls, kvform_string): ...
240
def toURL(self, base_url): ...
241
def toKVForm(self): ...
242
def getArg(self, namespace, key, default=None): ...
243
def setArg(self, namespace, key, value): ...
244
```
245
246
[Message Processing](./message-processing.md)
247
248
### Core Utilities
249
250
Essential utility functions for OpenID implementations including URI normalization, cryptographic operations, key-value form processing, logging, and Diffie-Hellman key exchange.
251
252
```python { .api }
253
def urinorm(uri): ...
254
def autoSubmitHTML(form, title='OpenID transaction in progress'): ...
255
def toBase64(data): ...
256
def fromBase64(data): ...
257
258
class DiffieHellman:
259
def __init__(self, modulus, generator, private=None): ...
260
def getSharedSecret(self, other_public): ...
261
```
262
263
[Core Utilities](./utilities.md)
264
265
## Types
266
267
```python { .api }
268
# Response Status Constants
269
SUCCESS = 'success'
270
FAILURE = 'failure'
271
CANCEL = 'cancel'
272
SETUP_NEEDED = 'setup_needed'
273
274
# Association Types
275
all_association_types = ['HMAC-SHA1', 'HMAC-SHA256']
276
default_association_order = [
277
('HMAC-SHA256', 'no-encryption'),
278
('HMAC-SHA1', 'no-encryption'),
279
('HMAC-SHA256', 'DH-SHA256'),
280
('HMAC-SHA1', 'DH-SHA1'),
281
]
282
283
# OpenID Namespace URIs
284
OPENID1_NS = 'http://openid.net/signon/1.0'
285
OPENID2_NS = 'http://specs.openid.net/auth/2.0'
286
IDENTIFIER_SELECT = 'http://specs.openid.net/auth/2.0/identifier_select'
287
288
# Discovery Service Types
289
OPENID_1_0_NS = 'http://openid.net/signon/1.0'
290
OPENID_IDP_2_0_TYPE = 'http://specs.openid.net/auth/2.0/server'
291
OPENID_2_0_TYPE = 'http://specs.openid.net/auth/2.0/signon'
292
OPENID_1_1_TYPE = 'http://openid.net/signon/1.1'
293
OPENID_1_0_TYPE = 'http://openid.net/signon/1.0'
294
295
# Session Types
296
session_types = ['DH-SHA1', 'DH-SHA256', 'no-encryption']
297
298
# SREG Extension
299
SREG_DATA_FIELDS = {
300
'nickname': 'Any UTF-8 string that the End User wants to use as a nickname.',
301
'email': 'The email address of the End User as specified in section 3.4.1 of [RFC2822]',
302
'fullname': 'UTF-8 string free text representation of the End User\'s full name.',
303
'dob': 'The End User\'s date of birth as YYYY-MM-DD.',
304
'gender': 'The End User\'s gender, "M" for male, "F" for female.',
305
'postcode': 'UTF-8 string free text that SHOULD conform to the End User\'s country\'s postal system.',
306
'country': 'The End User\'s country of residence as specified by ISO3166.',
307
'language': 'End User\'s preferred language as specified by ISO639.',
308
'timezone': 'ASCII string from TimeZone database'
309
}
310
311
# Exception Types
312
313
# Consumer Exceptions
314
class ProtocolError(Exception): ...
315
class DiscoveryFailure(Exception): ...
316
class SetupNeededError(Exception): ...
317
class TypeURIMismatch(Exception): ...
318
319
# Server Exceptions
320
class ServerError(Exception): ...
321
class VersionError(Exception): ...
322
class NoReturnToError(Exception): ...
323
class EncodingError(Exception): ...
324
class AlreadySigned(EncodingError): ...
325
class UntrustedReturnURL(ProtocolError): ...
326
class MalformedReturnURL(Exception): ...
327
class MalformedTrustRoot(Exception): ...
328
329
# Message Processing Exceptions
330
class UndefinedOpenIDNamespace(Exception): ...
331
class InvalidOpenIDNamespace(Exception): ...
332
class NamespaceAliasRegistrationError(Exception): ...
333
334
# Extension Exceptions
335
class SRegNamespaceError(Exception): ...
336
class AXError(Exception): ...
337
class NotAXMessage(Exception): ...
338
339
# Discovery Exceptions
340
class XRDSError(Exception): ...
341
class XRDSFetchingError(XRDSError): ...
342
343
# Trust Root Exceptions
344
class RealmVerificationRedirected(Exception): ...
345
```