Login

OpenID Form Field

Author:
jpwatts
Posted:
January 25, 2008
Language:
Python
Version:
.96
Tags:
field openid inames openid2 newforms identity forms fields form
Score:
2 (after 2 ratings)

This is a newforms field for OpenID 1 & 2.

It normalizes and validates OpenID identifiers according to the spec:

  • xri://=joelwatts to =joelwatts
  • joelwatts.com to http://joelwatts.com/
  • www.joelwatts.com to http://joelwatts.com/

An identifier that is well-formed, but not an OpenID (e.g. example.com), will cause a validation error.

Requires Python OpenID Library 2.x.x.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from django import newforms as forms
from openid.consumer.discover import discover, DiscoveryFailure
from openid.fetchers import HTTPFetchingError
from openid.yadis import xri


def identifierScheme(identifier):
    """Wrap openid.yadis.xri.identifierScheme to keep URI/URL consistent."""
    scheme = xri.identifierScheme(identifier)
    if scheme == 'XRI':
        return scheme
    return 'URL'


class OpenIDField(forms.CharField):
    """Field to normalize and validate an OpenID.

    Adds 'http://' prefix to URLs that don't have a scheme, appends trailing '/'
    if no path is provided, strips URL fragments and follows HTTP redirects.

    Strips 'xri://' prefix from XRIs.

    http://openid.net/specs/openid-authentication-2_0.html#normalization

    """
    default_error_messages = {
        'discovery': u"This %s doesn't appear to be an OpenID.",
        'invalid': u'Enter a valid OpenID.',
        'invalid_link': u'This URL appears to be a broken link.',
        'required': u'Enter an OpenID.'
    }

    def __init__(self, max_length=255, *args, **kwargs):
        super(OpenIDField, self).__init__(max_length, *args, **kwargs)

    def clean(self, value):
        value = super(OpenIDField, self).clean(value)

        if value in forms.fields.EMPTY_VALUES:
            return u''

        scheme = identifierScheme(value)

        if scheme == 'XRI' and value.startswith('xri://'):
            value = value[6:]

        try:
            claimed_id, endpoints = discover(value)
        except DiscoveryFailure:
            # resource not found
            raise forms.ValidationError(self.error_messages['invalid_link'])
        except HTTPFetchingError:
            # server not found or invalid URL
            raise forms.ValidationError(self.error_messages['invalid'])
        else:
            # valid URL/XRI with no OpenID endpoints
            if not endpoints:
                raise forms.ValidationError(
                    self.error_messages['discovery'] % scheme
                )
            self.endpoints = endpoints

        return claimed_id

    def widget_attrs(self, widget):
        # CSS hook for http://openid.net/logos/
        return {'class': 'openid'}

More like this

  1. XFN Form Field by jpwatts 7 years, 6 months ago
  2. create_update for newforms (ModelForm) by Rozza 7 years, 5 months ago
  3. models.py with django_dag models for parts hierarchy by j_syk 4 years, 1 month ago
  4. List all errors in a form +bootstrap highlighting by ibrahimlawal 2 years, 11 months ago
  5. NonceField for disabling autocompletion by johnnoone 6 years, 6 months ago

Comments

Please login first before commenting.