123 lines
5.3 KiB
Plaintext
123 lines
5.3 KiB
Plaintext
Introduction
|
|
============
|
|
|
|
At the beginning of every application you need to login or you need to verify if a user is the user he claims to be.
|
|
This is where credentials come into play. The Open Grid Protocol defines two possible types right now
|
|
(see http://wiki.secondlife.com/wiki/Open_Grid_Protocol#Agent_Authentication_.28Resource_Class.29)::
|
|
|
|
{ credential: credential , first_name: string , last_name: string }
|
|
::Note: Currently deployed protocol requires the following arguments: { firstname: string , lastname: string , password: string }
|
|
Note: Alternatively, this can be used: { firstname: string , lastname: string , md5-password: md5sum string }
|
|
|
|
|
|
What we need to implement right now is the current deployed protocol. The problem is that no field defines
|
|
what type of credential it is, except the md5-password or password variant.
|
|
|
|
Creating serialized credentials
|
|
===============================
|
|
|
|
When you want to login to an agent domain you need to send one of these two variants. You can do it like this::
|
|
|
|
>>> from pyogp.lib.base.credentials import PlainPasswordCredential
|
|
>>> credential = PlainPasswordCredential('firstname', 'lastname', 'secret')
|
|
|
|
Now we can serialize it like this::
|
|
|
|
>>> from pyogp.lib.base.credentials import LLSDSerializer
|
|
>>> serializer = LLSDSerializer(credential)
|
|
>>> serializer.serialize()
|
|
'<?xml version="1.0" ?><llsd><map><key>lastname</key><string>lastname</string><key>password</key><string>secret</string><key>firstname</key><string>firstname</string></map></llsd>'
|
|
>>> serializer.content_type
|
|
'application/llsd+xml'
|
|
|
|
Let's try the MD5 version::
|
|
|
|
>>> from pyogp.lib.base.credentials import MD5PasswordCredential
|
|
>>> credential = MD5PasswordCredential('firstname', 'lastname', plainpw = 'secret')
|
|
|
|
Note that you either can pass ``plainpw`` or ``md5pw`` as a password. If ``plainpw`` is given then it will get converted
|
|
to MD5 automatically. Note that the md5 password used in the protocol has no $1$ prepended! If both options are given, ``md5pw``
|
|
takes precedence.
|
|
|
|
Let's try to serialize this::
|
|
|
|
>>> from pyogp.lib.base.credentials import MD5PasswordLLSDSerializer
|
|
>>> serializer = MD5PasswordLLSDSerializer(credential)
|
|
>>> serializer.serialize()
|
|
'<?xml version="1.0" ?><llsd><map><key>lastname</key><string>lastname</string><key>md5-password</key><string>5ebe2294ecd0e0f08eab7690d2a6ee69</string><key>firstname</key><string>firstname</string></map></llsd>'
|
|
>>> serializer.content_type
|
|
'application/llsd+xml'
|
|
|
|
Let's try it with ``md5pw``::
|
|
|
|
>>> credential = MD5PasswordCredential('firstname', 'lastname', md5pw = 'secret')
|
|
>>> serializer = MD5PasswordLLSDSerializer(credential)
|
|
>>> serializer.serialize()
|
|
'<?xml version="1.0" ?><llsd><map><key>lastname</key><string>lastname</string><key>md5-password</key><string>secret</string><key>firstname</key><string>firstname</string></map></llsd>'
|
|
>>> serializer.content_type
|
|
'application/llsd+xml'
|
|
|
|
|
|
Deserializing a credential
|
|
==========================
|
|
|
|
If you want to implement an Agent Domain you also need to deserialize the credential to check it's validity. Unfortunately both types
|
|
of credentials are just XML to the outside. We use a utility which knows about the internals and returns the appropriate credential instance.
|
|
|
|
Let's try it with a plain password credential::
|
|
|
|
>>> s='<?xml version="1.0" ?><llsd><map><key>lastname</key><string>lastname</string><key>password</key><string>secret</string><key>firstname</key><string>firstname</string></map></llsd>'
|
|
|
|
We get the utility for it like this::
|
|
|
|
>>> from pyogp.lib.base.credentials import CredentialLLSDDeserializer
|
|
>>> deserializer = CredentialLLSDDeserializer()
|
|
|
|
|
|
Now let's use this utility::
|
|
|
|
>>> credential = deserializer.deserialize(s)
|
|
>>> credential.__class__.__name__
|
|
'PlainPasswordCredential'
|
|
>>> credential
|
|
PlainPasswordCredential for 'firstname lastname'
|
|
>>> credential.password
|
|
'secret'
|
|
|
|
Let's try the same for the md5 based version::
|
|
|
|
>>> s='<?xml version="1.0" ?><llsd><map><key>lastname</key><string>lastname</string><key>md5-password</key><string>5ebe2294ecd0e0f08eab7690d2a6ee69</string><key>firstname</key><string>firstname</string></map></llsd>'
|
|
>>> credential = deserializer.deserialize(s)
|
|
>>> credential.__class__.__name__
|
|
'MD5PasswordCredential'
|
|
>>> credential
|
|
MD5PasswordCredential for 'firstname lastname'
|
|
>>> credential.password
|
|
'5ebe2294ecd0e0f08eab7690d2a6ee69'
|
|
|
|
|
|
Possible errors
|
|
===============
|
|
|
|
Just for the fun of it let's test what happens if we pass a string which neither has password or md5-password::
|
|
|
|
>>> s='<?xml version="1.0" ?><llsd><map><key>lastname</key><string>lastname</string><key>firstname</key><string>firstname</string></map></llsd>'
|
|
>>> credential = deserializer.deserialize(s)
|
|
Traceback (most recent call last):
|
|
...
|
|
CredentialDeserializerNotFound: deserialization for payload '{'lastname': 'lastname', 'firstname': 'firstname'}' not supported
|
|
|
|
And what if no firstname and lastname was given::
|
|
|
|
>>> s='<?xml version="1.0" ?><llsd><map><key>password</key><string>secret</string></map></llsd>'
|
|
>>> credential = deserializer.deserialize(s)
|
|
Traceback (most recent call last):
|
|
...
|
|
CredentialDeserializerNotFound: deserialization for payload '{'password': 'secret'}' not supported
|
|
|
|
|
|
|
|
|
|
|
|
|