]> sipb.mit.edu Git - ikiwiki.git/blob - doc/plugins/plugins/openid/troubleshooting.mdwn
(no commit message)
[ikiwiki.git] / doc / plugins / plugins / openid / troubleshooting.mdwn
1 **TL;DR**
2
3 [[!toc levels=3]]
4
5 # An odyssey through lots of things that have to be right before OpenID works
6
7 Having just (at last) made an ikiwiki installation accept my
8 OpenID, I have learned many of the things that may have to be checked
9 when getting the [[plugins/openid]] plugin to work. (These are probably
10 the reasons why [ikiwiki.info](/) itself won't accept my OpenID!)
11
12 Just to describe my OpenID setup a bit (and why it makes a good stress-test
13 for the OpenID plugin :).
14
15 I'm using my personal home page URL as my OpenID. My page lives at
16 a shared-hosting service I have hired. It contains links that delegate
17 my OpenID processing to [indieauth.com](https://indieauth.com).
18
19 IndieAuth, in turn, uses
20 [rel-me authentication](http://microformats.org/wiki/RelMeAuth) to find
21 an [OAuth](http://microformats.org/wiki/OAuth) provider that can authenticate
22 me. (At present, I am using [github](http://github.com) for that, which
23 is an OAuth provider but not an OpenID provider, so the gatewaying provided
24 by IndieAuth solves that problem.) As far as ikiwiki is concerned,
25 IndieAuth is my OpenID provider; the details beyond that are transparent.
26
27 So, what were the various issues I had to sort out before my first successful
28 login with the [[plugins/openid]] plugin?
29
30 ## no_identity_server: Could not determine ID provider from URL.
31
32 This is the message [ikiwiki.info](/) shows as soon as I enter my home URL
33 as an OpenID. It is also the first one I got on my own ikiwiki installation.
34
35 ### various possible causes ...
36
37 There could be lots of causes. Maybe:
38
39 * the offered OpenID is an `https:` URL and there is an issue in checking
40     the certificate, so the page can't be retrieved?
41 * the page can be retrieved, but it isn't well-formed HTML and the library
42     can't parse it for the needed OpenID links?
43 * ...?
44
45 ### make a luckier setting of useragent ?!
46
47 In my case, it was none of the above. It turns out my shared-hosting provider
48 has a rule that refuses requests with `User-Agent: libwww-perl/6.03` (!!).
49 This is the sort of problem that's really hard to anticipate or plan around.
50 I could fix it (_for this case!_) by changing `useragent:` in `ikiwiki.setup`
51 to a different string that my goofy provider lets through.
52
53 __Recommendation:__ set `useragent:` in `ikiwiki.setup` to some
54 unlikely-to-be-blacklisted value. I can't guess what the best
55 unlikely-to-be-blacklisted value is; if there is one, it's probably the
56 next one all the rude bots will be using anyway, and some goofy provider
57 like mine will blacklist it.
58
59 ## Error: OpenID failure: naive_verify_failed_network: Could not contact ID provider to verify response.
60
61 Again, this could have various causes. It was helpful to bump the debug level
62 and get some logging, to see:
63
64     500 Can't connect to indieauth.com:443 (Net::SSL from Crypt-SSLeay can't
65     verify hostnames; either install IO::Socket::SSL or turn off verification
66     by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0)
67
68 I don't belong to the camp that solves every verification problem by turning
69 verification off, so this meant finding out how to get verification to be done.
70 It turns out there are two different Perl modules that can be used for SSL:
71
72 * `IO::Socket::SSL` (verifies hostnames)
73 * `Net::SSL` (_does not_ verify hostnames)
74
75 Both were installed on my hosted server. How was Perl deciding which one
76 to use?
77
78 ### set `PERL_NET_HTTPS_SSL_SOCKET_CLASS` appropriately
79
80 It turns out
81 [there's an environment variable](https://rt.cpan.org/Public/Bug/Display.html?id=71599).
82 So just set `PERL_NET_HTTPS_SSL_SOCKET_CLASS` to `IO::Socket::SSL` and the
83 right module gets used, right?
84
85 [Wrong](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/fed6f7d7df8619df0754e8883cfad2ac15703a38#diff-2).
86 That change was made to `ParanoidAgent.pm` back in November 2013 because of an
87 unrelated [bug](https://github.com/csirtgadgets/LWPx-ParanoidAgent/issues/4)
88 in `IO::Socket::SSL`. Essentially, _hmm, something goes wrong in
89 `IO::Socket::SSL` when reading certain large documents, so we'll fix it by
90 forcing the use of `Net::SSL` instead (the one that never verifies hostnames!),
91 no matter what the admin has set `PERL_NET_HTTPS_SSL_SOCKET_CLASS` to!_
92
93 ### undo change that broke `PERL_NET_HTTPS_SSL_SOCKET_CLASS`
94
95 Plenty of [comments](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=738493)
96 quickly appeared about how good an idea that wasn't, and it was corrected in
97 June 2014 with [one commit](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/a92ed8f45834a6167ff62d3e7330bb066b307a35)
98 to fix the original reading-long-documents issue in `IO::Socket::SSL` and
99 [another commit](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/815c691ad5554a219769a90ca5f4001ae22a4019)
100 that reverts the forcing of `Net::SSL` no matter how the environment is set.
101
102 Unfortunately, there isn't a release in CPAN yet that includes those two
103 commits, but they are only a few lines to edit into your own locally-installed
104 module.
105
106 ## Still naive_verify_failed_network, new improved reason
107
108     500 Can't connect to indieauth.com:443 (SSL connect attempt failed
109     with unknown error error:14090086:SSL
110     routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed)
111
112 Yay, at least it's trying to verify! Now why can't it verify IndieAuth's
113 certificate?
114
115 [Here's why](https://tools.ietf.org/html/rfc6066#section-3). As it turns out,
116 [indieauth.com](https://indieauth.com/) is itself a virtual host on a shared
117 server. If you naively try
118
119     openssl s_client -connect indieauth.com:443
120
121 you get back a certificate for [indieweb.org](https://indieweb.org/)
122 instead, so the hostname won't verify. If you explicitly indicate what server
123 name you're connecting to:
124
125     openssl s_client -connect indieauth.com:443 -servername indieauth.com
126
127 then, magically, the correct certificate comes back.
128
129 ### ensure `OpenSSL`, `Net::SSLeay`, `IO::Socket::SSL` new enough for SNI
130
131 If your `openssl` doesn't recognize the `-servername` option, it is too old
132 to do SNI, and a newer version needs to be built and installed. In fact,
133 even though SNI support was reportedly backported into OpenSSL 0.9.8f, it will
134 not be used by `IO::Socket::SSL` unless it is
135 [1.0 or higher](http://search.cpan.org/~sullr/IO-Socket-SSL-1.998/lib/IO/Socket/SSL.pod#SNI_Support).
136
137 Then a recent `Net::SSLeay` perl module needs to be built and linked against it.
138
139 ### Local OpenSSL installation will need certs to trust
140
141 Bear in mind that the OpenSSL distribution doesn't come with a collection
142 of trusted issuer certs. If a newer version is built and installed locally
143 (say, on a shared server where the system locations can't be written), it will
144 need to be given a directory of trusted issuer certs, say by linking to the
145 system-provided ones. However, a change to the certificate hash algorithm used
146 for the symlinks in that directory was [reportedly](http://www.cilogon.org/openssl1)
147 made with OpenSSL 1.0.0. So if the system-provided trusted certificate directory
148 was set up for an earlier OpenSSL version, all the certificates in it will be
149 fine but the hash symlinks will be wrong. That can be fixed by linking only the
150 named certificate files from the system directory into the newly-installed one,
151 and then running the new version of `c_rehash` there.
152
153 ## Still certificate verify failed
154
155 Using [SNI](https://tools.ietf.org/html/rfc6066#section-3)-supporting versions
156 of `IO::Socket::SSL`, `Net::SSLeay`, and `OpenSSL` doesn't do any good if an
157 upper layer hasn't passed down the name of the host being connected to so the
158 SSL layer can SNI for it.
159
160 ### ensure that `LWPx::ParanoidAgent` passes server name to SSL layer for SNI
161
162 That was fixed in `LWPx::ParanoidAgent` with
163 [this commit](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/df6df19ccdeeb717c709cccb011af35d3713f546),
164 which needs to be backported by hand if it hasn't made it into a CPAN release
165 yet.
166
167 Only that still doesn't end the story, because that hand didn't know what
168 [this hand](https://github.com/noxxi/p5-io-socket-ssl/commit/4f83a3cd85458bd2141f0a9f22f787174d51d587#diff-1)
169 was doing. What good is passing the name in
170 `PeerHost` if the SSL code looks in `PeerAddr` first ... and then, if that
171 doesn't match a regex for a hostname, decides you didn't supply one at all,
172 without even looking at `PeerHost`?
173
174 Happily, is is possible to assign a key that _explicitly_ supplies the
175 server name for SNI:
176
177     --- LWPx/Protocol/http_paranoid.pm    2014-09-08 03:33:00.000000000 -0400
178     +++ LWPx/Protocol/http_paranoid.pm    2014-09-08 03:33:27.000000000 -0400
179     @@ -73,6 +73,7 @@
180             close($el);
181              $sock = $self->socket_class->new(PeerAddr => $addr,
182                                               PeerHost => $host,
183     +                                         SSL_hostname => $host,
184                                               PeerPort => $port,
185                                               Proto    => 'tcp',
186                                               Timeout  => $conn_timeout,
187
188 ... not submitted upstream yet, so needs to be applied by hand.
189
190 # Success!!
191
192 And with that, ladies and gents, I got my first successful OpenID login!
193 I'm pretty sure that if the same fixes can be applied to
194 [ikiwiki.info](/) itself, a wider range of OpenID logins (like mine, for
195 example :) will work here too.
196
197 -- Chap