wiki:KeyRingProposal

Version 2 (modified by exarkun, 6 years ago) (diff)

refinerments and simplerfications

Prior Art

  1. gnome-keyring - password keyring
  2. ssh-agent - SSH key ring
  3. Apple Keychain

Goal

  1. To create an API by which applications acting as clients may authenticate themselves against servers without concerning themselves with the details of how the authentication is performed.
  2. To centralize the storage and representation of credentials for use by clients.
  3. To integrate with platform keyring services to be able to load credentials which have already been supplied by a user for general use on a system.

API

(incomplete, probably partially inconsistent)

class UsernamePassword(object):
    implements(INetworkUsernamePassword)

    def __init__(self, u, p, h, po):
        self.username = u
        self.password = p
        self.host = h
        self.port = po


class IKeyRing(Interface):
    """
    Represent one or more authentication credentials for a particular client-user-facing account identifier.
    """
    avatarId = Attribute("The client-user-facing account identifier to which all keys in this ring belong.")

    def add(credentials):
        """
        Add the given credentials object (eg, UsernamePassword) to the key ring.
        """

    def remove(credentials):
        pass


    def find(interface, **kwargs):
        """
        Return all credentials which provide the given interface and have attributes matching the given kwargs.
        """



if __name__ == '__main__':
    rings = RingCollection(GnomeKeyRing(), SSHKeyAgent())

    host = "pop3.example.com"
    d = ClientCreator(reactor, POP3Client).connectTCP(host, 110)
    def cbConnected(pop3):
        keysDeferred = rings.find(INetworkUsernamePassword, host=host, port=110)
        def cbGotKeys(keys):
            if not keys:
                username = raw_input("Username? ")
                password = raw_input("Password? ")
                creds = UsernamePassword(username, password, host, 110)
                rings.add(creds)
                return creds
            return keys[0]
        keysDeferred.addCallback(cbGotKeys)
        keysDeferred.addCallback(pop3.login)
        return keysDeferred
    d.addCallback(cbConnected)
    reactor.run()