Attachment 'RemoteHttpAuth.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - auth plugin using remote http(s) server with
4 authentication.
5 Based on a code found here:
6 http://www.voidspace.org.uk/python/articles/authentication.shtml
7
8 @copyright: 2009 Jakub Schmidtke <sjakub-at-gmail.com>
9 @license: GNU GPL, see COPYING for details.
10 """
11
12 import urllib2
13 import sys
14 import re
15 import base64
16 from urlparse import urlparse
17
18 from MoinMoin import config, user
19
20 from MoinMoin.auth import BaseAuth, CancelLogin, ContinueLogin
21
22 class RemoteHttpAuth(BaseAuth):
23 """
24 Auth plugin using remote http(s) authentication
25 """
26 name = 'remote_http'
27 login_inputs = ['username', 'password']
28 logout_possible = True
29
30 def __init__(self,
31 auth_url, # url used for authentication:
32 # http(s)://server_with_authentication/some_page
33 auth_hint = None, # login hint
34 required_web_content = None, # Content required from URL if properly authenticated.
35 # Content fetched from URL should be equal to this value\
36 # (if specified, if not this test is not performed)
37 auto_email_domain = None, # if set, it will be used for registering automatic
38 # email for new users, in form: username@auto_email_domain
39 autocreate = False, # should new users be created?
40 ):
41 BaseAuth.__init__(self)
42 self.auth_url = auth_url
43 self.auth_hint = auth_hint
44 self.required_web_content = required_web_content
45 self.auto_email_domain = auto_email_domain
46 self.autocreate = autocreate;
47
48 def login_hint(self, request):
49 if self.auth_hint:
50 return request.getText(self.auth_hint)
51
52 return None
53
54 def login(self, request, user_obj, **kw):
55 username = kw.get('username')
56 password = kw.get('password')
57 _ = request.getText
58
59 if not username or not password:
60 return ContinueLogin(user_obj)
61
62 req = urllib2.Request(self.auth_url)
63
64 try:
65 handle = urllib2.urlopen(req)
66 except IOError, e:
67 # here we *want* to fail
68 pass
69 else:
70 # If we don't fail then the page isn't protected
71 return ContinueLogin(user_obj, _("Error Authenticating: URL used for RemoteHttpAuth "
72 " does not require authentication. Please contact administrator."))
73
74 if not hasattr(e, 'code') or e.code != 401:
75 # we got an error - but not a 401 error
76 return ContinueLogin(user_obj, _("Error Authenticating: URL used for RemoteHttpAuth "
77 "does not require authentication or failed for antoher reason. "
78 "Please contact administrator."))
79
80 authline = e.headers['www-authenticate']
81 # this gets the www-authenticate line from the headers
82 # which has the authentication scheme and realm in it
83
84 authobj = re.compile(r'''(?:\s*www-authenticate\s*:)?\s*(\w*)\s+realm=['"]([^'"]+)['"]''', re.IGNORECASE)
85 # this regular expression is used to extract scheme and realm
86 matchobj = authobj.match(authline)
87
88 if not matchobj:
89 # if the authline isn't matched by the regular expression
90 # then something is wrong
91 return ContinueLogin(user_obj, _("Error Authenticating: Authentication header received from URL "
92 "used for RemoteHttpAuth is badly formed. Please contact administrator."))
93
94 scheme = matchobj.group(1)
95 realm = matchobj.group(2)
96 # here we've extracted the scheme
97 # and the realm from the header
98 if scheme.lower() != 'basic':
99 return ContinueLogin(user_obj, _("Error Authenticating: RemoteHttpAuth requires BASIC authentication "
100 "instead of '" + scheme + "'. Please contact administrator."))
101
102 base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
103 authheader = "Basic %s" % base64string
104 req.add_header("Authorization", authheader)
105
106 try:
107 handle = urllib2.urlopen(req)
108 except IOError, e:
109 # here we shouldn't fail if the username/password is right
110 return ContinueLogin(user_obj, _("Incorrect username or password."))
111
112 thepage = handle.read()
113
114 if self.required_web_content:
115 if thepage != self.required_web_content:
116 return ContinueLogin(user_obj, _("Authorization failed: '%s'" %(str(thepage))))
117
118 u = user.User(request, name=username, auth_username=username, auth_method=self.name,
119 auth_attribs=('name', 'auth_username', 'password'))
120
121 if self.autocreate and self.auto_email_domain and not u.email:
122 u.email = username + "@" + self.auto_email_domain
123
124 u.valid = True
125
126 if u and self.autocreate:
127 u.create_or_update(True)
128
129 return ContinueLogin(u)
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.