[Zope-CMF] Re: Re: Understanding the login mechanism
Dieter Maurer
dieter at handshake.de
Fri Oct 10 14:35:07 EDT 2003
Gitte Wange wrote at 2003-10-10 09:34 +0200:
> On Thu, 09 Oct 2003 21:15:35 +0200, Dieter Maurer wrote:
>
> > Gitte Wange wrote at 2003-10-9 13:28 +0200:
> > > ...
> > > I have 2 sites - mainsite.com and remotesite.com. User gitte logs into
> > > remotesite.com
> > > Then the user goes to mainsite.com
> > > Now mainsite.com asks remotesite.com if user gitte is logged in (by using
> > > XMLRPC)
> >
> > We do something like this using encryption.
> >
> > The link from "remotesite.com" to "mainsite.com" contains
> > the info: "I come from 'remotesite.com'" and an encrypted secret.
> >
> > "remotesite.com" and "mainsite.com" have exchanged encryption
> > keys. "mainsite.com" sees an incoming request from "remotesite.com"
> > and uses its key to decrypt the secret. It gives:
> > the source (i.e. 'remotesite.com'), the user identity and a timestamp.
> > If the sources agree and the timestamp is fresh, then the user
> > is authenticated.
>
> Sounds like a very useable solution :-)
> Do you have any code examples I can look at?
We use it with a partner. He is the "remotesite" and encrypts
while we are the "mainsite" and only decrypt.
The partner sends us an URL of the form
<path>?CallerID=<hisId>&profile=<encryptedProfile>
In the code below "self" represents the partner object (identified
via "CallerID").
from M2Crypto.EVP import Cipher
from base64 import decodestring
from cgi import parse_qsl
def checkEncrypted(self,profile):
'''check whether *profile* is a valid encypted profile.
returns 'None', if there is no encryption for this partner;
otherwise, a dictionary containing the decoded profile is returned.
If the dictionary contains 'Error', it is the first error
detected during verification.
*profile* and the key are expected to be base64 encoded.
'''
p= self._findPolicySpecs(PolicyType_Encrypted) # database lookup
cursor= self._cursor
profile= decodestring(profile)
ec= PolicyEncrypted(cursor,p[0][0]) # database lookup
# decode
dc= Cipher(ec.Name,decodestring(ec.KeyValue),profile[:8],0)
dv= dc.update(profile[8:]) + dc.final()
# make dict
r= {}
for key,val in parse_qsl(dv): r[key]= val
# check CallerID
if r.get('CallerID') != self.CallerID:
r['ErrorCode']= '401'
return r
# check timestamp
ts= r.get('TimeStamp',0)
try: fts= float(ts)
except ValueError: fts= 0
ttl= ec.TimeToLive; mts= time(); diff= abs(mts-fts)
if diff > ttl:
r['ErrorCode']= '403'
return r
# successful
return r
Dieter
More information about the Zope-CMF
mailing list