TracAuthOpenId-0.4.1/0000755001161100116110000000000011772165550014143 5ustar dairikidairikiTracAuthOpenId-0.4.1/MANIFEST.in0000644001161100116110000000026711772164443015706 0ustar dairikidairikiinclude LICENSE.txt include README.rst include CHANGES.rst exclude .gitignore recursive-include authopenid/htdocs *.css *.gif *.ico *.js recursive-include authopenid/templates *.html TracAuthOpenId-0.4.1/setup.py0000644001161100116110000000314411772164512015654 0ustar dairikidairikifrom setuptools import setup import os import sys PACKAGE = 'TracAuthOpenId' VERSION = '0.4.1' here = os.path.abspath(os.path.dirname(__file__)) README = open(os.path.join(here, 'README.rst')).read() CHANGES = open(os.path.join(here, 'CHANGES.rst')).read() install_requires = [ "python-openid >= 2.1.0", ] if sys.version_info[:2] < (2,6): install_requires.extend([ 'simplejson', ]) setup( name=PACKAGE, version=VERSION, description='OpenID plugin for Trac', long_description=README + "\n\n" + CHANGES, platforms = ['Any'], classifiers=[ "Development Status :: 4 - Beta", "Environment :: Plugins", "Environment :: Web Environment", "Framework :: Trac", "Intended Audience :: System Administrators", "Topic :: Internet :: WWW/HTTP", "Programming Language :: Python :: 2", "License :: OSI Approved :: BSD License", ], keywords='trac openid', author='Dalius Dobravolskas', author_email='dalius@sandbox.lt', maintainer='Jeff Dairiki', maintainer_email='dairiki@dairiki.org', url='https://github.com/dairiki/authopenid-plugin/', license='Trac license (BSD-like)', packages=['authopenid'], package_data={ 'authopenid': [ 'templates/*.html', 'htdocs/css/*.css', 'htdocs/images/*.gif', 'htdocs/images/*.ico', 'htdocs/js/*.js' ], }, entry_points={ 'trac.plugins': [ '%s = authopenid' % PACKAGE, ], }, install_requires=install_requires, ) TracAuthOpenId-0.4.1/README.rst0000644001161100116110000001272511772153005015631 0ustar dairikidairiki============================ OpenID Authentication Plugin ============================ Description =========== This plugin allows to login to Trac using OpenID. I use it with Trac 0.12. It was developed under Trac 0.11, so it should work there too. Version 0.4 of this plugin runs under trac 1.0 (formerly 0.13), but this configuration has not yet been extensively tested or used in production. Download & Source ================= The source repository is on github__. You may submit bug reports and pull requests there. __ https://github.com/dairiki/authopenid-plugin/ There are several ways to install this plugin. 1. You can install directly from PyPI_ using ``easy_install`` or pip_:: easy_install TracAuthOpenId or:: pip install TracAuthOpenId 2. There is `Debian package` for this plugin:: sudo aptitude install trac-authopenid 3. You can clone git repository somewhere in your system:: cd /your/3rdparty/src git clone git://github.com/dairiki/authopenid-plugin.git Then you should do following steps:: cd authopenid-plugin python setup.py install Alternatively, if you use pip_, you can install directly from the git repository:: pip install git+git://github.com/dairiki/authopenid-plugin.git For any of the above methods, if you want to do a system-wide installation, you will have to do this with *root* permissions (e.g. using ``su`` or ``sudo``). .. _PyPI: http://pypi.python.org/pypi/TracAuthOpenId/ .. _Debian package: http://packages.qa.debian.org/t/trac-authopenid.html .. _pip: http://www.pip-installer.org/ How to enable ============= :: [components] trac.web.auth.* = disabled authopenid.* = enabled You don't need to disable default authentication mechanism (trac.web.auth.*) if you are using it. OpenID plugin does not conflict with default authentication mechanism. Options ======= This plugin has number of configuration options. Examples are best way to illustrate them. (NB: some of this is out of date and needs to be updated):: [trac] # Check user IP address. IP addresses are masked because # in some cases user is behind internal proxy and last # number in IP address might vary. Disable check_auth_ip # if you are using IPv6. If you still want to have IPv6 # support please contact me. check_auth_ip = true check_auth_ip_mask = 255.255.255.0 # number of seconds until cookie will expire auth_cookie_lifetime = 86400 [openid] # In some cases company might have internal OpenID server that # automatically identifies user (e.g. windows SSPI). Also known as # single sign-on. default_openid = http://openid.ee Require sreg # data sreg_required = false # If you want username to be written as # "username_in_remote_system " use: #combined_username = true # Default PAPE method to request from OpenID provider. # pape_method = # What is OpenID link. whatis = http://openid.net/what/ # Sign-up link signup = http://openid.net/get # Gmail login button (default: true) # gmail = false # In some cases you might want allow users to login to different # projects using different OpenIDs. In that case don't use # absolute trust root. absolute_trust_root = false # Remove http:// or https:// from URL that is used as # username. (Default: false) strip_protocol = false # Remove trailing slash from URL that is user as username (Defaul: false) strip_trailing_slash = false # Expiration time acts as timeout. E.g. if expiration time is 24 # hour and you login again in those 24 hours. Expiration time is # extended for another 24 hours. (Default: false) timeout = false # White and black lists. # E.g.: Allows all the people from Lithuania, Latvia or Estonia # except delfi domain. # IMPORTANT: strip_protocol and strip_trailing_slash affects what # openid will be given to white_list or black_list #white_list = *.lt, *.lv, *.ee #black_list = *.delfi.lt,*.delfi.lv,*.delfi.ee # In addition to white and black lists you can use external # service for allowing users into trac. To control that you must # use check_list and check_list_key option. It will generate URL: # # check_list?check_list_key=openid&email=email # # email will be attached only if available. # # It expects JSON result in following format: # # {"check_list_key": true} # # IMPORTANT: strip_protocol and strip_trailing_slash affects what # openid will be send to service # NOTE: You can specify check_list_username as well. In that case # JSON service should return new username as # well. E.g. check_list_username=username. Expected result from # JSON service is: # # {"check_list_key": true, "username": "Peter"} # # You can use this option to map your OpenIDs to internal username. #check_list = http://your.site.com/openidallow #check_list_key = check_list #check_list_username= # # You can add one custom openid provider: #custom_provider_name = test #custom_provider_label = Enter openidprovider username: #custom_provider_url = http://openidprovider/{username} #custom_provider_image = http://openidprovider/favicon.png Authors ======= This plugin was written by `Dalius Dobravolskas`_. It is currently being maintained by `Jeff Dairiki`_. .. _Jeff Dairiki: mailto:dairiki@dairiki.org .. _Dalius Dobravolskas: mailto:dalius@sandbox.lt TracAuthOpenId-0.4.1/authopenid/0000755001161100116110000000000011772165550016303 5ustar dairikidairikiTracAuthOpenId-0.4.1/authopenid/htdocs/0000755001161100116110000000000011772165550017567 5ustar dairikidairikiTracAuthOpenId-0.4.1/authopenid/htdocs/js/0000755001161100116110000000000011772165550020203 5ustar dairikidairikiTracAuthOpenId-0.4.1/authopenid/htdocs/js/openid-jquery.js0000644001161100116110000001561711724760763023352 0ustar dairikidairiki/* Simple OpenID Plugin http://code.google.com/p/openid-selector/ This code is licenced under the New BSD License. */ var providers_large = { google: { name: 'Google', url: 'https://www.google.com/accounts/o8/id' }, yahoo: { name: 'Yahoo', url: 'http://yahoo.com/' }, aol: { name: 'AOL', label: 'Enter your AOL screenname.', url: 'http://openid.aol.com/{username}/' }, openid: { name: 'OpenID', label: 'Enter your OpenID.', url: null } }; var providers_small = { myopenid: { name: 'MyOpenID', label: 'Enter your MyOpenID username.', url: 'http://{username}.myopenid.com/' }, livejournal: { name: 'LiveJournal', label: 'Enter your Livejournal username.', url: 'http://{username}.livejournal.com/' }, flickr: { name: 'Flickr', label: 'Enter your Flickr username.', url: 'http://flickr.com/{username}/' }, technorati: { name: 'Technorati', label: 'Enter your Technorati username.', url: 'http://technorati.com/people/technorati/{username}/' }, wordpress: { name: 'Wordpress', label: 'Enter your Wordpress.com username.', url: 'http://{username}.wordpress.com/' }, blogger: { name: 'Blogger', label: 'Your Blogger account', url: 'http://{username}.blogspot.com/' }, verisign: { name: 'Verisign', label: 'Your Verisign username', url: 'http://{username}.pip.verisignlabs.com/' }, vidoop: { name: 'Vidoop', label: 'Your Vidoop username', url: 'http://{username}.myvidoop.com/' }, verisign: { name: 'Verisign', label: 'Your Verisign username', url: 'http://{username}.pip.verisignlabs.com/' }, claimid: { name: 'ClaimID', label: 'Your ClaimID username', url: 'http://claimid.com/{username}' } }; var providers = $.extend({}, providers_large, providers_small); var openid = { cookie_expires: 6*30, // 6 months. cookie_name: 'openid_provider', cookie_path: '/', img_path: 'images/', input_id: null, provider_url: null, init: function(input_id) { var openid_btns = $('#openid_btns'); this.input_id = input_id; $('#openid_choice').show(); $('#openid_input_area').empty(); // add box for each provider for (id in providers_large) { openid_btns.append(this.getBoxHTML(providers_large[id], 'large', '.gif')); } if (providers_small) { openid_btns.append('
'); for (id in providers_small) { openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.ico')); } } $('#openid_form').submit(this.submit); var box_id = this.readCookie(); if (box_id) { this.signin(box_id, true); } }, /* Remove providers that do not match the given RegExp */ filterProviders: function(re) { for (var k in providers) if (!re.test(k)) delete providers[k]; for (var k in providers_small) if (!re.test(k)) delete providers_small[k]; for (var k in providers_large) if (!re.test(k)) delete providers_large[k]; }, getBoxHTML: function(provider, box_size, image_ext) { var box_id = provider["name"].toLowerCase(); return ''; }, /* Provider image click */ signin: function(box_id, onload) { var provider = providers[box_id]; if (! provider) { return; } this.highlight(box_id); this.setCookie(box_id); // prompt user for input? if (provider['label']) { var hidden = $('#'+this.input_id); hidden.remove(); this.useInputBox(provider); this.provider_url = provider['url']; } else { var input_area = $('#openid_input_area'); input_area.empty(); this.setOpenIdUrl(provider['url']); if (! onload) { $('#openid_form').submit(); } } }, /* Sign-in button click */ submit: function() { var url = openid.provider_url; if (url) { url = url.replace('{username}', $('#openid_username').val()); openid.setOpenIdUrl(url); } return true; }, setOpenIdUrl: function (url) { var hidden = $('#'+this.input_id); if (hidden.length > 0) { hidden.value = url; } else { $('#openid_form').append(''); } }, highlight: function (box_id) { // remove previous highlight. var highlight = $('#openid_highlight'); if (highlight) { highlight.replaceWith($('#openid_highlight a')[0]); } // add new highlight. $('.'+box_id).wrap('
'); }, setCookie: function (value) { var date = new Date(); date.setTime(date.getTime()+(this.cookie_expires*24*60*60*1000)); var expires = "; expires="+date.toGMTString(); document.cookie = this.cookie_name+"="+value+expires+"; path=" + this.cookie_path; }, readCookie: function () { var nameEQ = this.cookie_name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); } return null; }, useInputBox: function (provider) { var input_area = $('#openid_input_area'); var html = ''; var id = 'openid_username'; var value = ''; var label = provider['label']; var style = ''; if (label) { html = '

' + label + '

'; } if (provider['name'] == 'OpenID') { id = this.input_id; value = 'http://'; style = 'background:#FFF url('+this.img_path+'openid-inputicon.gif) no-repeat scroll 0 50%; padding-left:18px;'; } html += '' + ''; input_area.empty(); input_area.append(html); $('#'+id).focus(); } }; TracAuthOpenId-0.4.1/authopenid/htdocs/css/0000755001161100116110000000000011772165550020357 5ustar dairikidairikiTracAuthOpenId-0.4.1/authopenid/htdocs/css/openid.css0000644001161100116110000000140611724760763022354 0ustar dairikidairiki#openid_form { width: 470px; } #openid_form legend { font-weight: bold; } #openid_choice { display: none; } #openid_input_area { clear: both; padding: 10px; } #openid_identifier { color: #000000; } #openid_btns, #openid_btns br { clear: both; } #openid_highlight { padding: 3px; background-color: #FFFCC9; float: left; } .openid_large_btn { width: 100px; height: 60px; border: 1px solid #DDD; margin: 3px; float: left; } .openid_small_btn { width: 24px; height: 24px; border: 1px solid #DDD; margin: 3px; float: left; } a.openid_large_btn:focus { outline: none; } a.openid_large_btn:focus { -moz-outline-style: none; } .openid_selected { border: 4px solid #DDD; } TracAuthOpenId-0.4.1/authopenid/htdocs/images/0000755001161100116110000000000011772165550021034 5ustar dairikidairikiTracAuthOpenId-0.4.1/authopenid/htdocs/images/flickr.ico0000644001161100116110000000217611724760763023014 0ustar dairikidairiki h(    cMcccNNMcccccec9ccccce[//Occcccce[xycccccce[xyc9ccccce[/0Occcccec8ccc998O{zӁӁӁTracAuthOpenId-0.4.1/authopenid/htdocs/images/google.gif0000644001161100116110000000307411724760763023007 0ustar dairikidairikiGIF89aK ߌα@af(F`ҔvxʼnݪܐJw JԦ`jHY(mܯnh蔇 ZKpѻʳpʉɅh(Ryؒڲ\Ud ,;qDz8t{۸6)'Z:lkuJF@N{ƷΕֻːܴeد~LJO;l{i "s)d3J[tP(`_ dthӜQH-hzTiEoa6' ˨@Ys12삛Ѳ汩B|>|>|8TracAuthOpenId-0.4.1/authopenid/htdocs/images/openid-inputicon.gif0000644001161100116110000000035511724760763025016 0ustar dairikidairikiGIF89ai kļcfx)о!,j'dieH:ӺBG-FS&O!$ 8[`ApK Q('g%2) z)94#!;TracAuthOpenId-0.4.1/authopenid/htdocs/images/verisign.ico0000644001161100116110000001114611724760763023365 0ustar dairikidairiki F h (>( @  !)9'&'(*&)*(44-=?8BC?U]a di hmt sr{ y zvrz$~**x/*z3+~F7|MNMWXTF@zKNcebkkjsufposuryyyx~~| !%/&.(5%3*;.=:74;1B<F<KMB@LGHGNPIFLLPGUNTL[Ue^iitipqum~IGJHGC_KWP\Vcaeahcvu{zydyy|v^KFIFZamD\G599l?YDY`!={YI7l@ng^Kahd#K~X.cJ#a>{JYuci t;^n*,%CagntnFa_unn6wY@nf trxt).L3O%6Raqf+]4k8rf& 4TW?tGLot.%G"PhnU Muk"<(AA<8211' nbIRz ua V|)d*-.t$ef,yt*/QN}( @iUUUUUT3"#4UUUUUUUUUUS4UUUUUUUUT1"""5UUUUUUUQ#EUTB#UUUUUUS$EUUUUC"4UUUUUAUUUUUUU2#UUUUU!$UUU4UUUS"5UUUT!5UUT5UUT"$UUUR#UUUPUUU2UUUB$UUU0UUUQ"UUU2%UUUUUUT"UUU25UUT5UUT"EUU"5UUPUUU"5UU!EUU0CUUT5UU"5UTTUUU25UU"5U@5TEUT"EUU24TUU0UT!EUU2$T3EUUPES"UUUR#EUUUUT4B#UUUS"EUUUUU02#UUUT"$EUUUUS0%UUUUDUUUUUUUUUUS"4EUUUU@3EUUUUU""4ETUD20UUUUUS""##2"" UUUUUUA"!"3U@@UUUUUUUS"""3UT335UUUUUUUUUUUUTE5UUUUUUUUUUUUUU05CUUUUUUUUUUUUUT34UUUUUUUUUUUUUUP4UUUUUUUUUUUUUUUD( @"# (((998@@?G`dh kjo | ~pqx!u&'u"!y)%yPPOIEW[[ZE@e[[`bc`hjduvt42>:4286FCIDQLWT\S}xvs|y}z}UUUM1&IUUUUUUUUD ):, *UUUUUU1 =SUUUUE&UUUUO 2UUNNUUJ 1UUU+#UUUUUU-UUUUU BU0.FNUP@UU (P7UUS?TUU;FUUUUQ'!UUUS$GUUUUGHUUUUI%8PSQF6UUUUUM# "4UUUUUUUL1,,>UP79UUUUUUUUUUUUUU/.3UUUUUUUUUUUUUUA5U( ffA#EffffQDFffdffeffaFeEfQVfDfdfdffPVeff@@FffdPff`VdUfQVffDfaEffPVfeVfd@FffTTFfffTDVdEfffffffDVffffffeVTracAuthOpenId-0.4.1/authopenid/htdocs/images/openid.gif0000644001161100116110000000134411724760763023007 0ustar dairikidairikiGIF89aKlŠPΰp0v `|3ȩ59@b!,KpH$.Ȥrl:DIZ^=کwLNt,VvL|Ḉa"x zj Z "H T~ #l#D an !Ya!C xB#B!iY B EBE!j! D HK IC 7` 5N!``^&l03@G Tvq DHb`L2愈I`H:qI@AC$u԰C  \gb%A]p= G<"hTAd#/dA.2/vH2b?T?bU1I XL9mT!h XamiTn!?BD- q T(2.,CG#r"VpV\@ hCH"?8B89BX?oY)4!<`H8AQD _InXh1 ?` ?2`E?P1TA zo3=-`$Sʤ.(IH?:'6"%X!G T!2좙(3&\Q |) " `"?l@"U2*#6|Evhv pXR<jppTX5=bB#ivl`Upÿ;9DGC#wьk:Y6 MAIr? O2hlLN 2p""?b ?fG3%Z?޸%'M# mfgHCh&`x@ ~6D$ EvĂfr\P3p "6x P 7Â| tY?c)(J DPa p@+`&fp 0 |0`a;`h !  =\A& $ OBpD 0`Cp W(C/JP+bQ!R61)p[H @%].,`\ |)E 40 LaC1/8)l&$KjZs"P6AnΛ4_8)Mrz H:vF<9EIJJGB570IIJJIIE%;/IIJJII-:IIJJIICGIJJI/< ).IJJI!A13EIJJII &DIJJII,L=# IJJII.?HIJ2II0" $-GII2JJJ 6@''(2KJJ( @ ަG#ep45Vr*+{Pv$/j8wL(bS'%"(,}&*ߪ!#$%(%.Uzf߫ "#$%&')&*+.4GRviQr0]NNNNNNNNnNNNNNNNhH%NNNNNNNNnNNNNNNNg JKNNNNNNNnNNNNNNNH6b4NNNNNNnNNNNNNgIXPdNNNNNNnNNNNNN8)(,$NNNNNNnNNNNNN] "lMNNNNNnNNNNNNEUWbhNNNNNnNNNNNN4aq.zc֒vǽZ,qd`nG`4v]1u[,ulChA}jBZ-sZ,rZ-q}ZpJY,rZ,sxSͿc\/s[-s{WŵqKlFޔwlDxT[,spG|sMi?~rK\-t\0qͿӞȥ^0uᤉmAnMwRvtTᰛߴóہ`pOwPɶwV꩑{󱞼vkH~vô̩լ쥎Ŵ͐oŶͿɼľ³rItyVg±tO]2u^2vqIklY,q!,T p#F9ĵaÇ#JHE`F!!Y&ѐCCJPȲˈz@b8Eq\dIYǀE4&LD4tX8~8Hd0?# *@&h j>bB¿%DEyJ3,b F`&JZᰛ?X&bțNH EE%OvH_ÿ$CQs\}u:Tr\ sf$0 8ϟpӜ! B%d$Í?dhBQ)p&98E(q"i$CxTZyQ8Y D  ey ompp@.pHnt@ic@t.em ra /k> <raTracAuthOpenId-0.4.1/authopenid/htdocs/images/livejournal.ico0000644001161100116110000001214611724760763024072 0ustar dairikidairiki(Fhn  ( DDDDDsDDww@Dwx@Lwx@DDDLLDD@LLDDt@GwLDDw@IODt@DD?( @f3f3f3f3f3f3f3f3f3f3f3f3|z{f3f3f3}FÉNf3f3|EНjΔZwf3f3HϜh֣pzD~dI}f3f3JўiԡnMM|œ^[%f3f3JНiԡnLO͚٦ԟ[/f3f3Hҟkԡn}JQ͚բ͙S'f3f3lA#^-ؤp~KO͛ԡΚT(f3f3f3W5])‘_Нա͘Q%f3f3xP3k=X٥ΙQ$f3f3{aaCjKj:Kf3f3w_~{bpU`1f3f3v\z|eyR;f3f3f3f3f3f3?( @D@DDD@DDDDD@DDHD@DDDDDDDLċDDĸ@DLċ@Dĸ@DLċ@DDDDDDLNDDDDDDLND@DDDDLND@DLDDDGDND@DwDDDGwtDND@DGwtDDDwwDD@DwwDDDGDDD@DtDIOwD@DDtDIDD@DIDDD???( @ f3f3f3f3f3f3f3f3f3f3c/f3f3f3f3f3a+f3f3f3f3c.f3f3^)\$^&f7 qW>~}vaLc(f3f3f3f3Z%e0lCߙsZEd/`+f3Y"l9wC{N"g8 f3f3Y$j7LפpY"~`)f3f3Y#l8Mҟlҟlh/ytn|voZf3Y#l9 Pҟl̙fўkn5yqhmK)d-f3X"m: Pҟl̙f̙fӠmh0~c/f3f3Y"q> Qҟl̙f̙fΛhΚgOqmhΗZf3f3[&s@Wҟl̙f̙fΛhΛhW%tB`-b-V"sBkI,}rW<^&f3Y$q> Uҟk̙f̙fΛhϜiZ'j8ĒΛϜ˗ΛfI^)l< f3X"r?Vҟl̙f̙fΛhΛhZ'j9Λў͚͚Λ٦߮{t@X!f3f3Z%s@Wҟl̙f̙fΛhΛhX&k9ΛϜ̙̙̙֢ץrm9 X"f3f3Y$uBYҟl̙f̙fΛhΛhX%m;ΛϜ̙̙̙բդqk8 X#f3f3Z$wDZўk̙f̙fΛh͚gW%n=ϜϜ̙̙̙բդqk7 X#f3f3Z"_+V#ҟl̙f̙fϜi˘eQn<ϜϜ̙̙̙բ֤qk8 X#f3f3f3}U.}W1g2YНjΛh͚gT!n<ϝϜ̙̙̙բکvn: [&f3f3f3|U/ū\&X%Ӡl͚gU#r@НϜ̙̙̙բӢol9 X!f3f3f3́[6^(r?]+rAОϜ̙̙̙բӢoi7X"f3f3f3c.vԿm?[&a.֣ў̙̙̙բӢnj6Y#f3f3f3qKBqCױd3 i4[ϜӠΛբѠmi5Y$f3f3f3}`*pPɼvI!W!^-کvϝПmh5[%f3f3f3xX]_&tz[^+d/S m9X"f3f3ؘmB.`)}yQ-]([%f3f3f3pG;^&rP篡m>\%f3rBf3ic2n< {^qi7Z"f3tDf3v뒋y[ia-f3]'f3f3f3f3f3f3f3f3f3f3f3f3f3???TracAuthOpenId-0.4.1/authopenid/htdocs/images/aol.gif0000644001161100116110000000423511724760763022306 0ustar dairikidairikiGIF89aQZ^^]1z_Y\e;#qZ[ `hYqncb bC!oyiӤ޲%rX"nO\3{JHA&P$*V#1PG rE4Dj.D;pKC `4uBd 0P BIq ]`p@P`뭻އ ER`1=䰢~Ö4 PZ/dU$ >4 DsIZ@!@O a 㧓 tAR $ BBы^Dh`d?$ (6`T :HܡL_l (B:pK$ ^R(p}@G? R'88N H90 .+x' !IKpg@$ '8l0?bA!Xha , @38`AnQ5@ 2`P dB pQZ )&)b):s!  6@LG$fxN8@輆` S/#D|0T!DrxztBJZ0V P8ԡ  A4`jP@@% }HЇ#X"t!@Jl Ҟ$AIb X OpenID Login

Please click your account provider:

OpenID URL:

What is OpenId? Sign-up

TracAuthOpenId-0.4.1/authopenid/templates/autosubmitform.html0000644001161100116110000000065111724760763024255 0ustar dairikidairiki OpenID transaction in progress ${Markup(form)} TracAuthOpenId-0.4.1/authopenid/authopenid.py0000644001161100116110000007732611772151312021023 0ustar dairikidairiki# -*- coding: utf-8 -*- # # Copyright (C) 2007 Dalius Dobravolskas # All rights reserved. # # This software is licensed using the same licence as Trac: # http://trac.edgewall.org/wiki/TracLicense. # # Author: Dalius Dobravolskas # # Most probably you will want to add following lines to your configuration file: # # [components] # trac.web.auth.* = disabled # authopenid.* = enabled import pkg_resources import cgi import cPickle import re import time import itertools from trac.core import * from trac.config import Option, BoolOption, IntOption from trac.web.chrome import INavigationContributor, ITemplateProvider, add_stylesheet, add_script from trac.env import IEnvironmentSetupParticipant from trac.web.main import IRequestHandler, IAuthenticator from trac.web.session import DetachedSession try: from acct_mgr.web_ui import LoginModule except ImportError: from trac.web.auth import LoginModule from genshi.builder import tag from trac.util import hex_entropy from openid.store.sqlstore import MySQLStore, PostgreSQLStore, SQLiteStore from openid.store.memstore import MemoryStore from openid.consumer import consumer from openid.extensions import sreg, pape, ax from openid import oidutil import socket import struct import urllib try: import json except ImportError: import simplejson as json # python < 2.6 class OpenIdLogger: """ Log all OpenID messages to debug. """ def __init__(self, env): self.env = env def __call__(self, message, level=0): self.env.log.debug(message) class AuthOpenIdPlugin(Component): openid_session_key = 'openid_session_data' openid_session_identity_url_key = 'openid_session_identity_url_data' openid_ax_attrs=dict( email='http://schema.openid.net/contact/email', email2='http://axschema.org/contact/email', firstname='http://axschema.org/namePerson/first', lastname='http://axschema.org/namePerson/last', ) implements(INavigationContributor, IRequestHandler, ITemplateProvider, IAuthenticator, IEnvironmentSetupParticipant) # Do not declare options in the [trac] section. We should not # be creating new declared options there, and we should not be # changing the system defaults for those options. @property def connection_uri(self): return self.env.config.get('trac', 'database', 'sqlite:db/trac.db') @property def check_ip(self): # Whether the IP address of the user should be checked for # authentication (''since 0.9'').""") # NOTE: trac's default value is false. We used to override # that global default to true. return self.env.config.getbool('trac', 'check_auth_ip') # XXX: This appears not to be a standard trac options (as of 0.12) check_ip_mask = Option('trac', 'check_auth_ip_mask', '255.255.255.0', """What mask should be applied to user address.""") # Do not declare these with IntOption... we do not want to create # the options if they do not exist. ('[trac] expires' does not # seem to exist in stock trac 0.12.) @property def trac_auth_cookie_lifetime(self): config = self.env.config for opt in ['auth_cookie_lifetime', 'expires']: if config.has_option('trac', opt): return config.getint('trac', opt) return 60*60*24 timeout = BoolOption('openid', 'timeout', False, """Specify if expiration time should act as timeout. If set, cookie lifetime will be extended to auth_cookie_lifetime on each authenticated access. """) default_openid = Option('openid', 'default_openid', None, """Default OpenID provider for directed identity.""") strip_protocol = BoolOption('openid', 'strip_protocol', False, """Instead of using username beginning with http:// or https:// you can strip the beginning.""") strip_trailing_slash = BoolOption('openid', 'strip_trailing_slash', False, """In case your OpenID is some sub-domain address OpenId library adds trailing slash. This option strips it.""") sreg_required = BoolOption('openid', 'sreg_required', 'false', """Whether SREG data should be required or optional.""") combined_username = BoolOption('openid', 'combined_username', False, """ Username will be written as username_in_remote_system . """) lowercase_authname = BoolOption('openid', 'lowercase_authname', True, """ Whether authnames should always be lower-cased. Setting this to false generally makes more sense, however this is backwards-incompatible if you already have user sessions which you would like to preserve. """) pape_method = Option('openid', 'pape_method', None, """Default PAPE method to request from OpenID provider.""") signup_link = Option('openid', 'signup', 'http://openid.net/get/', """Signup link""") whatis_link = Option('openid', 'whatis', 'http://openid.net/what/', """What is OpenId link.""") absolute_trust_root = BoolOption('openid', 'absolute_trust_root', 'true', """Whether we should use absolute trust root or by project.""") white_list = Option('openid', 'white_list', '', """Comma separated list of allowed OpenId addresses.""") black_list = Option('openid', 'black_list', '', """Comma separated list of denied OpenId addresses.""") email_white_list = Option('openid', 'email_white_list', '', """Comma separated list of allowed users, using the resolved SREG/AX email address. Use in combination with trusted identity patterns in white_list.""") check_list = Option('openid', 'check_list', None, """JSON service for openid check.""") check_list_key = Option('openid', 'check_list_key', 'check_list', """Key for openid Service.""") check_list_username = Option('openid', 'check_list_username', None, """Username for openid Service.""") providers = Option('openid', 'providers', [], """Explicit set of provider names to display. E.g: google, yahoo, ...""") custom_provider_name = Option('openid', 'custom_provider_name', None, """ Custom OpenId provider name. """) custom_provider_label = Option('openid', 'custom_provider_label', 'Enter your username', """ Custom OpenId provider label. """) custom_provider_url = Option('openid', 'custom_provider_url', '', """ Custom OpenId provider URL. E.g.: http://claimid.com/{username} """) custom_provider_image = Option('openid', 'custom_provider_image', '', """ Custom OpenId provider image. """) custom_provider_size = Option('openid', 'custom_provider_size', 'small', """ Custom OpenId provider image size (small or large).""") def _get_masked_address(self, address): if self.check_ip: mask = struct.unpack('>L', socket.inet_aton(self.check_ip_mask))[0] address = struct.unpack('>L', socket.inet_aton(address))[0] return socket.inet_ntoa(struct.pack('>L', address & mask)) return address def generate_re_list(self, list_in_string): """ Generates list of compiled regular expressions from given comma-separated list in string. """ generated_list = [] if list_in_string: for item in list_in_string.split(','): item = item.strip() item = re.escape(item) item = '^' + item.replace('\*', '.*') + '$' generated_list.append(re.compile(item)) self.env.log.debug("Item compiled: %s" % item) return generated_list def __init__(self): db = self.env.get_db_cnx() oidutil.log = OpenIdLogger(self.env) self.env.log.debug("Compiling white-list") self.re_white_list = self.generate_re_list(self.white_list) self.env.log.debug("Compiling black-list") self.re_black_list = self.generate_re_list(self.black_list) self.env.log.debug("Compiling email white-list") self.re_email_white_list = self.generate_re_list(self.email_white_list) self.providers_regexp = '.' if self.providers: self.providers_regexp = '^(' + str.join('|', re.split(' *, *', self.providers)) + ')$' def _getStore(self, db): scheme, rest = self.connection_uri.split(':', 1) if scheme == 'mysql': return MySQLStore(db.cnx.cnx) elif scheme == 'postgres': return PostgreSQLStore(db.cnx.cnx) elif scheme == 'sqlite': return SQLiteStore(db.cnx.cnx) else: return MemoryStore() def _initStore(self, db): store = self._getStore(db) if type(store) is not MemoryStore: store.createTables() # IEnvironmentSetupParticipant methods def environment_created(self): db = self.env.get_db_cnx() self._initStore(db) db.commit() def environment_needs_upgrade(self, db): c = db.cursor() try: c.execute("SELECT count(*) FROM oid_associations") return False except Exception, e: if hasattr(db, 'rollback'): db.rollback() return True def upgrade_environment(self, db): self._initStore(db) # IAuthenticator methods def authenticate(self, req): authname = None if req.remote_user: authname = req.remote_user self.env.log.debug('authenticate. remote_user: %s' % authname) elif req.incookie.has_key('trac_auth'): authname = self._get_name_for_cookie(req, req.incookie['trac_auth']) self.env.log.debug('authenticate. cookie: %s' % authname) if not authname: self.env.log.debug('No OpenId authenticated user.') return None if self.lowercase_authname: authname = authname.lower() return authname # INavigationContributor methods def get_active_navigation_item(self, req): return 'openidlogin' def get_navigation_items(self, req): if req.authname and req.authname != 'anonymous': if not self.env.is_component_enabled(LoginModule): yield ('metanav', 'openidlogin', 'logged in as %s' % (req.session.get('name') or req.authname)) yield ('metanav', 'openidlogout', tag.a('Logout', href=req.href.openidlogout())) else: yield ('metanav', 'openidlogin', tag.a(('OpenID Login'), href=req.href.openidlogin())) # IRequestHandler methods def match_request(self, req): return re.match('/(openidlogin|openidverify|openidprocess|openidlogout)\??.*', req.path_info) def process_request(self, req): if req.path_info.startswith('/openidlogin'): return self._do_login(req) elif req.path_info.startswith('/openidverify'): return self._do_verify(req) elif req.path_info.startswith('/openidprocess'): return self._do_process(req) elif req.path_info.startswith('/openidlogout'): return self._do_logout(req) def _do_login(self, req): # check the referer referer = req.get_header('Referer') if referer and not (referer == req.base_url or referer.startswith(req.base_url.rstrip('/')+'/')): # only redirect to referer if it is from the same site referer = None if referer: req.session['oid.referer'] = referer if self.default_openid: req.args['openid_identifier'] = self.default_openid return self._do_verify(req) add_stylesheet(req, 'authopenid/css/openid.css') add_script(req, 'authopenid/js/openid-jquery.js') return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': 'Login using OpenID.', 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': 'error', 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None def _get_session(self, req): """Returns a session dict that can store any kind of object.""" try: return cPickle.loads(str(req.session[self.openid_session_key])) except KeyError: return {} def _get_trust_root(self, req): href = req.href() abs_href = self.env.abs_href() self.env.log.debug('_get_trust_root href: ' + href) self.env.log.debug('_get_trust_root abs_href: ' + abs_href) if href and abs_href.endswith(href): base_url = abs_href[:-len(href)] else: base_url = abs_href return base_url def _commit_session(self, session, req): req.session[self.openid_session_key] = str(cPickle.dumps(session)) def _get_consumer(self, req, db): s = self._get_session(req) if 'id' not in s: s['id'] = req.session.sid store = self._getStore(db) return consumer.Consumer(s, store), s def _do_verify(self, req): """Process the form submission, initating OpenID verification. """ # First, make sure that the user entered something openid_url = req.args.get('openid_identifier') add_stylesheet(req, 'authopenid/css/openid.css') add_script(req, 'authopenid/js/openid-jquery.js') if not openid_url: return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': 'Enter an OpenID Identifier to verify.', 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': 'error', 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None immediate = 'immediate' in req.args db = self.env.get_db_cnx() oidconsumer, session = self._get_consumer(req, db) try: self.env.log.debug('beginning OpenID authentication.') request = oidconsumer.begin(openid_url) except consumer.DiscoveryFailure, exc: fetch_error_string = 'Error in discovery: %s' % ( cgi.escape(str(exc[0]))) return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': fetch_error_string, 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': 'error', 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None else: if request is None: msg = 'No OpenID services found for %s' % ( cgi.escape(openid_url),) return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': msg, 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': 'error', 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None else: self._commit_session(session, req) # Then, ask the library to begin the authorization. # Here we find out the identity server that will verify the # user's identity, and get a token that allows us to # communicate securely with the identity server. requested_policies = [] if self.pape_method: requested_policies.append(self.pape_method) pape_method = req.args.get('pape_method') if pape_method: requested_policies.append(pape_method) if requested_policies: pape_request = pape.Request(requested_policies) request.addExtension(pape_request) # Let the sreg policy be configurable sreg_opt = [] sreg_req = [] sreg_fields = ['fullname', 'email'] if self.sreg_required: sreg_req = sreg_fields else: sreg_opt = sreg_fields sreg_request = sreg.SRegRequest(optional=sreg_opt, required=sreg_req) request.addExtension(sreg_request) ax_request = ax.FetchRequest() for alias, uri in self.openid_ax_attrs.items(): attr_info = ax.AttrInfo(uri, required=True, alias=alias) ax_request.add(attr_info) request.addExtension(ax_request) trust_root = self._get_trust_root(req) if self.absolute_trust_root: trust_root += '/' else: trust_root += req.href() return_to = self._get_trust_root(req) + req.href.openidprocess() if request.shouldSendRedirect(): redirect_url = request.redirectURL( trust_root, return_to, immediate=immediate) self.env.log.debug('Redirecting to: %s' % redirect_url) req.redirect(redirect_url) else: form_html = request.formMarkup( trust_root, return_to, form_tag_attrs={'id':'openid_message'}, immediate=immediate) return 'autosubmitform.html', { 'id': 'openid_message', 'form': form_html }, None def _do_process(self, req): """Handle the redirect from the OpenID server. """ db = self.env.get_db_cnx() oidconsumer, session = self._get_consumer(req, db) # Ask the library to check the response that the server sent # us. Status is a code indicating the response type. info is # either None or a string containing more information about # the return type. info = oidconsumer.complete(req.args,req.args['openid.return_to']) css_class = 'error' if info.status == consumer.FAILURE and info.identity_url: # In the case of failure, if info is non-None, it is the # URL that we were verifying. We include it in the error # message to help the user figure out what happened. fmt = "Verification of %s failed: %s" message = fmt % (cgi.escape(info.identity_url), info.message) elif info.status == consumer.SUCCESS: # Success means that the transaction completed without # error. If info is None, it means that the user cancelled # the verification. css_class = 'alert' # This is a successful verification attempt. If this # was a real application, we would do our login, # comment posting, etc. here. fmt = "You have successfully verified %s as your identity." message = fmt % (cgi.escape(info.identity_url),) remote_user = info.identity_url sreg_info = sreg.SRegResponse.fromSuccessResponse(info) or {} ax_response = ax.FetchResponse.fromSuccessResponse(info) ax_info = {} if ax_response: for alias, uri in self.openid_ax_attrs.items(): values = ax_response.data.get(uri,[]) if values: ax_info[alias] = values[0] email = (ax_info.get('email') or ax_info.get('email2') or sreg_info.get('email')) fullname = (' '.join(filter(None, map(ax_info.get, ('firstname', 'lastname')))) or sreg_info.get('fullname') or email.split('@',1)[0].replace('.', ' ').title()) if self.strip_protocol: remote_user = remote_user[remote_user.find('://')+3:] if self.strip_trailing_slash and remote_user[-1] == '/': remote_user = remote_user[:-1] if info.endpoint.canonicalID: # You should authorize i-name users by their canonicalID, # rather than their more human-friendly identifiers. That # way their account with you is not compromised if their # i-name registration expires and is bought by someone else. message += (" This is an i-name, and its persistent ID is %s" % (cgi.escape(info.endpoint.canonicalID),)) remote_user = info.endpoint.canonicalID allowed = True if self.re_white_list: self.env.log.debug("Filtering REMOTE_USER '%s' through white-list." % remote_user) allowed = False for item in self.re_white_list: if not allowed and item.match(remote_user): allowed = True self.env.log.debug("User white-listed.") if allowed and self.re_black_list: self.env.log.debug("Filtering REMOTE_USER '%s' through black-list." % remote_user) for item in self.re_black_list: if item.match(remote_user): allowed = False self.env.log.debug("User black-listed.") if allowed and email and self.re_email_white_list: self.env.log.debug("Filtering email '%s' through email white-list." % email) allowed = False for item in self.re_email_white_list: if not allowed and item.match(email): allowed = True self.env.log.debug("User email white-listed.") if allowed and self.check_list: params = {self.check_list_key: remote_user} if email: params['email'] = email url = self.check_list + '?' + urllib.urlencode(params) self.env.log.debug('OpenID check list URL: %s' % url) result = json.load(urllib.urlopen(url)) if not result[self.check_list_key]: allowed = False elif self.check_list_username: new_user = result[self.check_list_username] if new_user: remote_user = new_user if allowed: cookie = hex_entropy() cookie_lifetime = self.trac_auth_cookie_lifetime req.outcookie['trac_auth'] = cookie req.outcookie['trac_auth']['path'] = req.href() if cookie_lifetime > 0: req.outcookie['trac_auth']['expires'] = cookie_lifetime req.session[self.openid_session_identity_url_key] = info.identity_url if email: req.session['email'] = email if fullname: req.session['name'] = fullname self._commit_session(session, req) if req.session.get('name'): authname = req.session['name'] if self.combined_username: authname = '%s <%s>' % (authname, remote_user) # Possibly lower-case the authname. if self.lowercase_authname: authname = authname.lower() # Make authname unique in case of collisions # # XXX: We ought to first look for an existing authenticated # ssession with matching identity_url, and just use that # for the authid. (E.g. what if the user changes his # fullname at the openid provider?) However, trac does # not seem to provide an API for searching sessions other # than by sid/authname. # def authnames(base): yield base for attempt in itertools.count(2): yield "%s (%d)" % (base, attempt) for authname in authnames(authname): ds = DetachedSession(self.env, authname) if ds.last_visit == 0 and len(ds) == 0: # At least in 0.12.2, this mean no session exists. break ds_identity = ds.get(self.openid_session_identity_url_key) if ds_identity == info.identity_url: # No collision break req.authname = authname db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("INSERT INTO auth_cookie (cookie,name,ipnr,time) " "VALUES (%s, %s, %s, %s)", (cookie, authname, self._get_masked_address(req.remote_addr), int(time.time()))) db.commit() req.redirect(req.session.get('oid.referer') or self.env.abs_href()) else: message = 'You are not allowed here.' elif info.status == consumer.CANCEL: # cancelled message = 'Verification cancelled' elif info.status == consumer.SETUP_NEEDED: if info.setup_url: message = 'Setup needed' % ( quoteattr(info.setup_url),) else: # This means auth didn't succeed, but you're welcome to try # non-immediate mode. message = 'Setup needed' else: # Either we don't understand the code or there is no # openid_url included with the error. Give a generic # failure message. The library should supply debug # information in a log. message = 'Verification failed.' self._commit_session(session, req) add_stylesheet(req, 'authopenid/css/openid.css') add_script(req, 'authopenid/js/openid-jquery.js') return 'openidlogin.html', { 'images': req.href.chrome('authopenid/images') + '/', 'action': req.href.openidverify(), 'message': message, 'signup': self.signup_link, 'whatis': self.whatis_link, 'css_class': css_class, 'providers_regexp': self.providers_regexp, 'custom_provider_name': self.custom_provider_name, 'custom_provider_label': self.custom_provider_label, 'custom_provider_url': self.custom_provider_url, 'custom_provider_image': self.custom_provider_image, 'custom_provider_size': self.custom_provider_size, }, None # ITemplateProvider methods def get_htdocs_dirs(self): return [('authopenid', pkg_resources.resource_filename(__name__, 'htdocs'))] def get_templates_dirs(self): return [pkg_resources.resource_filename(__name__, 'templates')] def _do_logout(self, req): """Log the user out. Simply deletes the corresponding record from the auth_cookie table. """ if req.authname == 'anonymous': # Not logged in req.redirect(self.env.abs_href()) # While deleting this cookie we also take the opportunity to delete # cookies older than trac_auth_cookie_lifetime expires = self.trac_auth_cookie_lifetime if expires <= 0: expires = 10 * 24 * 60 * 60 stale = int(time.time()) - expires authcookie = req.incookie.get('trac_auth') db = self.env.get_db_cnx() cursor = db.cursor() if authcookie: cursor.execute("DELETE FROM auth_cookie" " WHERE cookie=%s OR time < %s", (authcookie.value, stale)) else: cursor.execute("DELETE FROM auth_cookie" " WHERE name=%s OR time < %s", (req.authname, stale)) db.commit() self._expire_cookie(req) custom_redirect = self.config['metanav'].get('logout.redirect') if custom_redirect: if custom_redirect.startswith('/'): custom_redirect = req.href(custom_redirect) req.redirect(custom_redirect) req.redirect(self.env.abs_href()) def _expire_cookie(self, req): """Instruct the user agent to drop the auth cookie by setting the "expires" property to a date in the past. """ req.outcookie['trac_auth'] = '' req.outcookie['trac_auth']['path'] = req.href() req.outcookie['trac_auth']['expires'] = -10000 self.env.log.debug('trac_auth cookie expired.') def _get_name_for_cookie(self, req, cookie): masked_addr = self._get_masked_address(req.remote_addr) db = self.env.get_db_cnx() cursor = db.cursor() if self.check_ip: cursor.execute("SELECT name FROM auth_cookie " "WHERE cookie=%s AND ipnr=%s", (cookie.value, masked_addr)) else: cursor.execute("SELECT name FROM auth_cookie WHERE cookie=%s", (cookie.value,)) row = cursor.fetchone() if row: name = row[0] if self.timeout: now = int(time.time()) if self.check_ip: cursor.execute("UPDATE auth_cookie SET time=%s " "WHERE cookie=%s AND ipnr=%s AND name=%s", (now, cookie.value, masked_addr, name)) else: cursor.execute("UPDATE auth_cookie SET time=%s " "WHERE cookie=%s AND name=%s", (now, cookie.value, name)) cookie_lifetime = self.trac_auth_cookie_lifetime if cookie_lifetime > 0: req.outcookie['trac_auth'] = cookie.value req.outcookie['trac_auth']['path'] = req.href() req.outcookie['trac_auth']['expires'] = cookie_lifetime else: # The cookie is invalid but we don't expire it because it might # be generated by different trac authentication mechanism. name = None db.commit() return name TracAuthOpenId-0.4.1/CHANGES.rst0000644001161100116110000000702711772165262015753 0ustar dairikidairiki======= Changes ======= Version 0.4.1 (2012-06-25) ========================== This is a brown bag release. Release 0.4 was unusable. Bug Fixes --------- - Packaging: A number of crucial files were omitted from the manifest. Version 0.4 (2012-06-25) ======================== Configuration Changes --------------------- - The default for ``[trac] check_auth_ip`` is now ``False``. **This has security implications**. If you want authorization to be tied to the clients IP address *you must now explicitly set* this option to ``True``. Prior to this change, if ``check_auth_ip`` was not explicitly set, we ignored the global trac default (``False``) for the setting and behaved as if it were set to ``True``. This change is being made for the sake of backwards compatibility with trac 0.11 whose ``Configuration.has_option`` method does not support the optional ``defaults`` argument added in 0.12. Without that there seems to be no clean way to determine whether a setting is explicitly set in the ``.ini`` file. New Features ------------ - We will now use the json_ package if your python version includes it (python >= 2.6). For older pythons, the simplejson_ package is now required. - A minor hack has been made which allows at least basic functionality under the development branch, trac-1.0 (formerly know as trac-0.13). Note that only very basic tests under trac-1.0 have not been performed. (The code in this plugin still does not adhere to the modern `trac db API`_ usage recommendations.) .. _json: http://docs.python.org/library/json.html .. _simplejson: https://github.com/simplejson/simplejson .. _trac db API: http://trac.edgewall.org/wiki/TracDev/DatabaseApi Version 0.3.6 (2012-03-05) ========================== New Maintainer -------------- Jeff Dairiki has taken over maintenance of this plugin from the original author, Dalius Dobravolskas (who no longer uses trac.) The source repository for the plugin has moved to https://github.com/dairiki/authopenid-plugin. New Features ------------ - Respect the ``[trac] auth_cookie_lifetime`` config value when setting cookie expiration times. Deprecations ------------ - Using the ``[trac] expires`` setting to specify the auth cookie lifetime is deprecated. Use ``[trac] auth_cookie_lifetime`` instead. (The ``expires`` setting does not seem to exist in trac 0.12 or 0.11.) Bug Fixes --------- - Don't override the default value for the ``[trac] check_auth_ip`` configuration setting. Trac declares this to have a default value of *false*; we were overriding that default to *true*. Version 0.3.5 (2011-10-04) ========================== New Features ------------ - Now AX (as well as SREG) are attempted to get the user’s name. This is tested with Google (which does not support SREG). - The new config setting ``[openid] lowercase_authname`` specifies whether to force authnames to lowercase. For backwards compatibility, the default for this option is *true* (see below__). In general, however, I think it makes more sense to set this option to *false*. __ `authnames were being lower-cased`_ Bug Fixes --------- - _`Authnames were being lower-cased` when recovering them from the cookie, but not when generating them initially. This resulted — unless the user’s name was all lower case to start with — in two sessions being created upon initial login, one of which was ignored thereafter. - Always uniquify authnames. When they are lowercased, there’s always a chance of collision, even when they include the identity URL. TracAuthOpenId-0.4.1/PKG-INFO0000644001161100116110000002762611772165550015255 0ustar dairikidairikiMetadata-Version: 1.0 Name: TracAuthOpenId Version: 0.4.1 Summary: OpenID plugin for Trac Home-page: https://github.com/dairiki/authopenid-plugin/ Author: Jeff Dairiki Author-email: dairiki@dairiki.org License: Trac license (BSD-like) Description: ============================ OpenID Authentication Plugin ============================ Description =========== This plugin allows to login to Trac using OpenID. I use it with Trac 0.12. It was developed under Trac 0.11, so it should work there too. Version 0.4 of this plugin runs under trac 1.0 (formerly 0.13), but this configuration has not yet been extensively tested or used in production. Download & Source ================= The source repository is on github__. You may submit bug reports and pull requests there. __ https://github.com/dairiki/authopenid-plugin/ There are several ways to install this plugin. 1. You can install directly from PyPI_ using ``easy_install`` or pip_:: easy_install TracAuthOpenId or:: pip install TracAuthOpenId 2. There is `Debian package` for this plugin:: sudo aptitude install trac-authopenid 3. You can clone git repository somewhere in your system:: cd /your/3rdparty/src git clone git://github.com/dairiki/authopenid-plugin.git Then you should do following steps:: cd authopenid-plugin python setup.py install Alternatively, if you use pip_, you can install directly from the git repository:: pip install git+git://github.com/dairiki/authopenid-plugin.git For any of the above methods, if you want to do a system-wide installation, you will have to do this with *root* permissions (e.g. using ``su`` or ``sudo``). .. _PyPI: http://pypi.python.org/pypi/TracAuthOpenId/ .. _Debian package: http://packages.qa.debian.org/t/trac-authopenid.html .. _pip: http://www.pip-installer.org/ How to enable ============= :: [components] trac.web.auth.* = disabled authopenid.* = enabled You don't need to disable default authentication mechanism (trac.web.auth.*) if you are using it. OpenID plugin does not conflict with default authentication mechanism. Options ======= This plugin has number of configuration options. Examples are best way to illustrate them. (NB: some of this is out of date and needs to be updated):: [trac] # Check user IP address. IP addresses are masked because # in some cases user is behind internal proxy and last # number in IP address might vary. Disable check_auth_ip # if you are using IPv6. If you still want to have IPv6 # support please contact me. check_auth_ip = true check_auth_ip_mask = 255.255.255.0 # number of seconds until cookie will expire auth_cookie_lifetime = 86400 [openid] # In some cases company might have internal OpenID server that # automatically identifies user (e.g. windows SSPI). Also known as # single sign-on. default_openid = http://openid.ee Require sreg # data sreg_required = false # If you want username to be written as # "username_in_remote_system " use: #combined_username = true # Default PAPE method to request from OpenID provider. # pape_method = # What is OpenID link. whatis = http://openid.net/what/ # Sign-up link signup = http://openid.net/get # Gmail login button (default: true) # gmail = false # In some cases you might want allow users to login to different # projects using different OpenIDs. In that case don't use # absolute trust root. absolute_trust_root = false # Remove http:// or https:// from URL that is used as # username. (Default: false) strip_protocol = false # Remove trailing slash from URL that is user as username (Defaul: false) strip_trailing_slash = false # Expiration time acts as timeout. E.g. if expiration time is 24 # hour and you login again in those 24 hours. Expiration time is # extended for another 24 hours. (Default: false) timeout = false # White and black lists. # E.g.: Allows all the people from Lithuania, Latvia or Estonia # except delfi domain. # IMPORTANT: strip_protocol and strip_trailing_slash affects what # openid will be given to white_list or black_list #white_list = *.lt, *.lv, *.ee #black_list = *.delfi.lt,*.delfi.lv,*.delfi.ee # In addition to white and black lists you can use external # service for allowing users into trac. To control that you must # use check_list and check_list_key option. It will generate URL: # # check_list?check_list_key=openid&email=email # # email will be attached only if available. # # It expects JSON result in following format: # # {"check_list_key": true} # # IMPORTANT: strip_protocol and strip_trailing_slash affects what # openid will be send to service # NOTE: You can specify check_list_username as well. In that case # JSON service should return new username as # well. E.g. check_list_username=username. Expected result from # JSON service is: # # {"check_list_key": true, "username": "Peter"} # # You can use this option to map your OpenIDs to internal username. #check_list = http://your.site.com/openidallow #check_list_key = check_list #check_list_username= # # You can add one custom openid provider: #custom_provider_name = test #custom_provider_label = Enter openidprovider username: #custom_provider_url = http://openidprovider/{username} #custom_provider_image = http://openidprovider/favicon.png Authors ======= This plugin was written by `Dalius Dobravolskas`_. It is currently being maintained by `Jeff Dairiki`_. .. _Jeff Dairiki: mailto:dairiki@dairiki.org .. _Dalius Dobravolskas: mailto:dalius@sandbox.lt ======= Changes ======= Version 0.4.1 (2012-06-25) ========================== This is a brown bag release. Release 0.4 was unusable. Bug Fixes --------- - Packaging: A number of crucial files were omitted from the manifest. Version 0.4 (2012-06-25) ======================== Configuration Changes --------------------- - The default for ``[trac] check_auth_ip`` is now ``False``. **This has security implications**. If you want authorization to be tied to the clients IP address *you must now explicitly set* this option to ``True``. Prior to this change, if ``check_auth_ip`` was not explicitly set, we ignored the global trac default (``False``) for the setting and behaved as if it were set to ``True``. This change is being made for the sake of backwards compatibility with trac 0.11 whose ``Configuration.has_option`` method does not support the optional ``defaults`` argument added in 0.12. Without that there seems to be no clean way to determine whether a setting is explicitly set in the ``.ini`` file. New Features ------------ - We will now use the json_ package if your python version includes it (python >= 2.6). For older pythons, the simplejson_ package is now required. - A minor hack has been made which allows at least basic functionality under the development branch, trac-1.0 (formerly know as trac-0.13). Note that only very basic tests under trac-1.0 have not been performed. (The code in this plugin still does not adhere to the modern `trac db API`_ usage recommendations.) .. _json: http://docs.python.org/library/json.html .. _simplejson: https://github.com/simplejson/simplejson .. _trac db API: http://trac.edgewall.org/wiki/TracDev/DatabaseApi Version 0.3.6 (2012-03-05) ========================== New Maintainer -------------- Jeff Dairiki has taken over maintenance of this plugin from the original author, Dalius Dobravolskas (who no longer uses trac.) The source repository for the plugin has moved to https://github.com/dairiki/authopenid-plugin. New Features ------------ - Respect the ``[trac] auth_cookie_lifetime`` config value when setting cookie expiration times. Deprecations ------------ - Using the ``[trac] expires`` setting to specify the auth cookie lifetime is deprecated. Use ``[trac] auth_cookie_lifetime`` instead. (The ``expires`` setting does not seem to exist in trac 0.12 or 0.11.) Bug Fixes --------- - Don't override the default value for the ``[trac] check_auth_ip`` configuration setting. Trac declares this to have a default value of *false*; we were overriding that default to *true*. Version 0.3.5 (2011-10-04) ========================== New Features ------------ - Now AX (as well as SREG) are attempted to get the user’s name. This is tested with Google (which does not support SREG). - The new config setting ``[openid] lowercase_authname`` specifies whether to force authnames to lowercase. For backwards compatibility, the default for this option is *true* (see below__). In general, however, I think it makes more sense to set this option to *false*. __ `authnames were being lower-cased`_ Bug Fixes --------- - _`Authnames were being lower-cased` when recovering them from the cookie, but not when generating them initially. This resulted — unless the user’s name was all lower case to start with — in two sessions being created upon initial login, one of which was ignored thereafter. - Always uniquify authnames. When they are lowercased, there’s always a chance of collision, even when they include the identity URL. Keywords: trac openid Platform: Any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Plugins Classifier: Environment :: Web Environment Classifier: Framework :: Trac Classifier: Intended Audience :: System Administrators Classifier: Topic :: Internet :: WWW/HTTP Classifier: Programming Language :: Python :: 2 Classifier: License :: OSI Approved :: BSD License TracAuthOpenId-0.4.1/LICENSE.txt0000644001161100116110000000263311725216377015774 0ustar dairikidairikiCopyright (C) 2007-2012 Dalius Dobravolskas and Geoffrey T. Dairiki All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. TracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/0000755001161100116110000000000011772165550020447 5ustar dairikidairikiTracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/trac_plugin.txt0000644001161100116110000000002011772151573023507 0ustar dairikidairikiauthopenid TracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/top_level.txt0000644001161100116110000000001311772165550023173 0ustar dairikidairikiauthopenid TracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/requires.txt0000644001161100116110000000002611772165550023045 0ustar dairikidairikipython-openid >= 2.1.0TracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/PKG-INFO0000644001161100116110000002762611772165550021561 0ustar dairikidairikiMetadata-Version: 1.0 Name: TracAuthOpenId Version: 0.4.1 Summary: OpenID plugin for Trac Home-page: https://github.com/dairiki/authopenid-plugin/ Author: Jeff Dairiki Author-email: dairiki@dairiki.org License: Trac license (BSD-like) Description: ============================ OpenID Authentication Plugin ============================ Description =========== This plugin allows to login to Trac using OpenID. I use it with Trac 0.12. It was developed under Trac 0.11, so it should work there too. Version 0.4 of this plugin runs under trac 1.0 (formerly 0.13), but this configuration has not yet been extensively tested or used in production. Download & Source ================= The source repository is on github__. You may submit bug reports and pull requests there. __ https://github.com/dairiki/authopenid-plugin/ There are several ways to install this plugin. 1. You can install directly from PyPI_ using ``easy_install`` or pip_:: easy_install TracAuthOpenId or:: pip install TracAuthOpenId 2. There is `Debian package` for this plugin:: sudo aptitude install trac-authopenid 3. You can clone git repository somewhere in your system:: cd /your/3rdparty/src git clone git://github.com/dairiki/authopenid-plugin.git Then you should do following steps:: cd authopenid-plugin python setup.py install Alternatively, if you use pip_, you can install directly from the git repository:: pip install git+git://github.com/dairiki/authopenid-plugin.git For any of the above methods, if you want to do a system-wide installation, you will have to do this with *root* permissions (e.g. using ``su`` or ``sudo``). .. _PyPI: http://pypi.python.org/pypi/TracAuthOpenId/ .. _Debian package: http://packages.qa.debian.org/t/trac-authopenid.html .. _pip: http://www.pip-installer.org/ How to enable ============= :: [components] trac.web.auth.* = disabled authopenid.* = enabled You don't need to disable default authentication mechanism (trac.web.auth.*) if you are using it. OpenID plugin does not conflict with default authentication mechanism. Options ======= This plugin has number of configuration options. Examples are best way to illustrate them. (NB: some of this is out of date and needs to be updated):: [trac] # Check user IP address. IP addresses are masked because # in some cases user is behind internal proxy and last # number in IP address might vary. Disable check_auth_ip # if you are using IPv6. If you still want to have IPv6 # support please contact me. check_auth_ip = true check_auth_ip_mask = 255.255.255.0 # number of seconds until cookie will expire auth_cookie_lifetime = 86400 [openid] # In some cases company might have internal OpenID server that # automatically identifies user (e.g. windows SSPI). Also known as # single sign-on. default_openid = http://openid.ee Require sreg # data sreg_required = false # If you want username to be written as # "username_in_remote_system " use: #combined_username = true # Default PAPE method to request from OpenID provider. # pape_method = # What is OpenID link. whatis = http://openid.net/what/ # Sign-up link signup = http://openid.net/get # Gmail login button (default: true) # gmail = false # In some cases you might want allow users to login to different # projects using different OpenIDs. In that case don't use # absolute trust root. absolute_trust_root = false # Remove http:// or https:// from URL that is used as # username. (Default: false) strip_protocol = false # Remove trailing slash from URL that is user as username (Defaul: false) strip_trailing_slash = false # Expiration time acts as timeout. E.g. if expiration time is 24 # hour and you login again in those 24 hours. Expiration time is # extended for another 24 hours. (Default: false) timeout = false # White and black lists. # E.g.: Allows all the people from Lithuania, Latvia or Estonia # except delfi domain. # IMPORTANT: strip_protocol and strip_trailing_slash affects what # openid will be given to white_list or black_list #white_list = *.lt, *.lv, *.ee #black_list = *.delfi.lt,*.delfi.lv,*.delfi.ee # In addition to white and black lists you can use external # service for allowing users into trac. To control that you must # use check_list and check_list_key option. It will generate URL: # # check_list?check_list_key=openid&email=email # # email will be attached only if available. # # It expects JSON result in following format: # # {"check_list_key": true} # # IMPORTANT: strip_protocol and strip_trailing_slash affects what # openid will be send to service # NOTE: You can specify check_list_username as well. In that case # JSON service should return new username as # well. E.g. check_list_username=username. Expected result from # JSON service is: # # {"check_list_key": true, "username": "Peter"} # # You can use this option to map your OpenIDs to internal username. #check_list = http://your.site.com/openidallow #check_list_key = check_list #check_list_username= # # You can add one custom openid provider: #custom_provider_name = test #custom_provider_label = Enter openidprovider username: #custom_provider_url = http://openidprovider/{username} #custom_provider_image = http://openidprovider/favicon.png Authors ======= This plugin was written by `Dalius Dobravolskas`_. It is currently being maintained by `Jeff Dairiki`_. .. _Jeff Dairiki: mailto:dairiki@dairiki.org .. _Dalius Dobravolskas: mailto:dalius@sandbox.lt ======= Changes ======= Version 0.4.1 (2012-06-25) ========================== This is a brown bag release. Release 0.4 was unusable. Bug Fixes --------- - Packaging: A number of crucial files were omitted from the manifest. Version 0.4 (2012-06-25) ======================== Configuration Changes --------------------- - The default for ``[trac] check_auth_ip`` is now ``False``. **This has security implications**. If you want authorization to be tied to the clients IP address *you must now explicitly set* this option to ``True``. Prior to this change, if ``check_auth_ip`` was not explicitly set, we ignored the global trac default (``False``) for the setting and behaved as if it were set to ``True``. This change is being made for the sake of backwards compatibility with trac 0.11 whose ``Configuration.has_option`` method does not support the optional ``defaults`` argument added in 0.12. Without that there seems to be no clean way to determine whether a setting is explicitly set in the ``.ini`` file. New Features ------------ - We will now use the json_ package if your python version includes it (python >= 2.6). For older pythons, the simplejson_ package is now required. - A minor hack has been made which allows at least basic functionality under the development branch, trac-1.0 (formerly know as trac-0.13). Note that only very basic tests under trac-1.0 have not been performed. (The code in this plugin still does not adhere to the modern `trac db API`_ usage recommendations.) .. _json: http://docs.python.org/library/json.html .. _simplejson: https://github.com/simplejson/simplejson .. _trac db API: http://trac.edgewall.org/wiki/TracDev/DatabaseApi Version 0.3.6 (2012-03-05) ========================== New Maintainer -------------- Jeff Dairiki has taken over maintenance of this plugin from the original author, Dalius Dobravolskas (who no longer uses trac.) The source repository for the plugin has moved to https://github.com/dairiki/authopenid-plugin. New Features ------------ - Respect the ``[trac] auth_cookie_lifetime`` config value when setting cookie expiration times. Deprecations ------------ - Using the ``[trac] expires`` setting to specify the auth cookie lifetime is deprecated. Use ``[trac] auth_cookie_lifetime`` instead. (The ``expires`` setting does not seem to exist in trac 0.12 or 0.11.) Bug Fixes --------- - Don't override the default value for the ``[trac] check_auth_ip`` configuration setting. Trac declares this to have a default value of *false*; we were overriding that default to *true*. Version 0.3.5 (2011-10-04) ========================== New Features ------------ - Now AX (as well as SREG) are attempted to get the user’s name. This is tested with Google (which does not support SREG). - The new config setting ``[openid] lowercase_authname`` specifies whether to force authnames to lowercase. For backwards compatibility, the default for this option is *true* (see below__). In general, however, I think it makes more sense to set this option to *false*. __ `authnames were being lower-cased`_ Bug Fixes --------- - _`Authnames were being lower-cased` when recovering them from the cookie, but not when generating them initially. This resulted — unless the user’s name was all lower case to start with — in two sessions being created upon initial login, one of which was ignored thereafter. - Always uniquify authnames. When they are lowercased, there’s always a chance of collision, even when they include the identity URL. Keywords: trac openid Platform: Any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Plugins Classifier: Environment :: Web Environment Classifier: Framework :: Trac Classifier: Intended Audience :: System Administrators Classifier: Topic :: Internet :: WWW/HTTP Classifier: Programming Language :: Python :: 2 Classifier: License :: OSI Approved :: BSD License TracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/dependency_links.txt0000644001161100116110000000000111772165550024515 0ustar dairikidairiki TracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/SOURCES.txt0000644001161100116110000000211311772165550022330 0ustar dairikidairikiCHANGES.rst LICENSE.txt MANIFEST.in README.rst setup.cfg setup.py TracAuthOpenId.egg-info/PKG-INFO TracAuthOpenId.egg-info/SOURCES.txt TracAuthOpenId.egg-info/dependency_links.txt TracAuthOpenId.egg-info/entry_points.txt TracAuthOpenId.egg-info/requires.txt TracAuthOpenId.egg-info/top_level.txt TracAuthOpenId.egg-info/trac_plugin.txt authopenid/__init__.py authopenid/authopenid.py authopenid/htdocs/css/openid.css authopenid/htdocs/images/aol.gif authopenid/htdocs/images/blogger.ico authopenid/htdocs/images/claimid.ico authopenid/htdocs/images/facebook.gif authopenid/htdocs/images/flickr.ico authopenid/htdocs/images/google.gif authopenid/htdocs/images/livejournal.ico authopenid/htdocs/images/myopenid.ico authopenid/htdocs/images/openid-inputicon.gif authopenid/htdocs/images/openid.gif authopenid/htdocs/images/technorati.ico authopenid/htdocs/images/verisign.ico authopenid/htdocs/images/vidoop.ico authopenid/htdocs/images/wordpress.ico authopenid/htdocs/images/yahoo.gif authopenid/htdocs/js/openid-jquery.js authopenid/templates/autosubmitform.html authopenid/templates/openidlogin.htmlTracAuthOpenId-0.4.1/TracAuthOpenId.egg-info/entry_points.txt0000644001161100116110000000005411772165550023744 0ustar dairikidairiki[trac.plugins] TracAuthOpenId = authopenid TracAuthOpenId-0.4.1/setup.cfg0000644001161100116110000000023511772165550015764 0ustar dairikidairiki[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [aliases] upload_sdist = egg_info --tag-build '' --no-svn-revision --no-date sdist upload --sign