[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