├── urns.yml ├── LICENSE ├── README.md └── webfinger_generator.rb /urns.yml: -------------------------------------------------------------------------------- 1 | # maps string keys to best practice fully qualified URNs 2 | 3 | # some references: 4 | # http://webfinger.net/rel/ 5 | # http://www.packetizer.com/webfinger/link_relations.html 6 | 7 | # names of people 8 | name: "http://schema.org/name" 9 | full_name: "http://schema.org/name" 10 | 11 | # pictures of people 12 | avatar: http://webfinger.net/rel/avatar 13 | picture: http://webfinger.net/rel/avatar 14 | photo: http://webfinger.net/rel/avatar 15 | 16 | # homepages of people 17 | profile_page: http://webfinger.net/rel/profile-page 18 | profile: http://webfinger.net/rel/profile-page 19 | website: http://webfinger.net/rel/profile-page 20 | url: http://webfinger.net/rel/profile-page 21 | homepage: http://webfinger.net/rel/profile-page 22 | 23 | # OpenID Connect 24 | openid: http://openid.net/specs/connect/1.0/issuer 25 | open_id: http://openid.net/specs/connect/1.0/issuer -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Eric Mill 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * 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. 8 | * Neither the name of Eric Mill nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## A Webfinger plugin for Jekyll. 2 | 3 | An easy Jekyll plugin for adding Webfinger support to your domain. 4 | 5 | **Note**: This won't work with Github Pages, which doesn't allow plugins, unless you're building your site yourself and then committing the rendered pages directly. 6 | 7 | ### What is Webfinger? 8 | 9 | It's a way to attach information to your email address. 10 | 11 | Take an email address, and ask its domain about it using HTTPS. For example, information about `eric@konklone.com` is available in JSON at: 12 | 13 | ``` 14 | https://konklone.com/.well-known/webfinger?resource=acct:eric@konklone.com 15 | ``` 16 | 17 | See [webfinger.net](http://webfinger.net), [Paul E. Jones' description](http://www.packetizer.com/webfinger/), or Webfinger's official standard at [RFC 7033](http://tools.ietf.org/html/rfc7033) for more information. 18 | 19 | ### Using jekyll-webfinger 20 | 21 | Create a `_plugins` folder in your project if it doesn't exist, and place `webfinger_generator.rb` into it. 22 | 23 | Then, create a `_webfinger.yml` in the root of your project, that looks something like this: 24 | 25 | ```yaml 26 | eric@konklone.com: 27 | name: Eric Mill 28 | website: https://konklone.com 29 | ``` 30 | 31 | When your Jekyll site is built, it will create a URL at `/.well-known/webfinger` that returns: 32 | 33 | ```json 34 | { 35 | "subject": "eric@konklone.com", 36 | "properties": { 37 | "http://schema.org/name": "Eric Mill" 38 | }, 39 | "links": [ 40 | { 41 | "rel": "http://webfinger.net/rel/profile-page", 42 | "href": "https://konklone.com" 43 | } 44 | ] 45 | } 46 | ``` 47 | 48 | The response will actually be compact (not indented, like the above example). 49 | 50 | ### Caveats 51 | 52 | * Webfinger **requires HTTPS**. If you set this up on a non-secure website (`http://`), be prepared for most Webfinger clients to not find your data. 53 | * Since this is static file hosting, the query string is being ignored. So **all Webfinger requests will return the same data**. This in violation of the spec, but I'm not aware of how else to implement Webfinger using static files. 54 | * It's on you to configure your web server to set the `Content-Type` to `application/jrd+json` for `/.well-known/webfinger`. If you don't, it will probably be set to `application/octet-stream`, which is in violation of the spec (though most clients will probably still parse it fine). 55 | * As I said at the top, this **won't work on Github Pages** unless you pre-build the site yourself. Github blocks all plugins during its build process, so you can only use `jekyll-webfinger` if you build the site yourself. 56 | 57 | ### MIT License 58 | 59 | This project is published [under the MIT License](LICENSE). 60 | -------------------------------------------------------------------------------- /webfinger_generator.rb: -------------------------------------------------------------------------------- 1 | # Webfinger data generator. 2 | # 3 | # Generates a /.well-known/webfinger endpoint that responds with 4 | # the details given in _webfinger.yml (in the root of the project). 5 | # 6 | # Example Webfinger configuration at _webfinger.yml: 7 | # 8 | # eric@konklone.com: 9 | # name: Eric Mill 10 | # website: https://konklone.com 11 | # 12 | # This will create a page at /.well-known/.webfinger that returns: 13 | # 14 | # { 15 | # "subject": "eric@konklone.com", 16 | # "properties": { 17 | # "http://schema.org/name": "Eric Mill" 18 | # }, 19 | # "links": [ 20 | # { 21 | # "rel": "http://webfinger.net/rel/profile-page", 22 | # "href": "https://konklone.com" 23 | # } 24 | # ] 25 | # } 26 | # 27 | # See the README for more details. 28 | # 29 | # Author: Eric Mill 30 | # Site: https://konklone.com 31 | # Plugin Source: https://github.com/konklone/jekyll-webfinger 32 | # Plugin License: MIT 33 | 34 | require 'json' # uses built-in stdlib json 35 | 36 | module Jekyll 37 | 38 | class WebfingerGenerator < Generator 39 | 40 | def generate(site) 41 | @site = site 42 | 43 | config_file = File.join File.dirname(__FILE__), "../_webfinger.yml" 44 | return unless File.exist?(config_file) 45 | config = YAML.load_file config_file 46 | 47 | webfinger_dir = File.join @site.dest, ".well-known" 48 | webfinger_file = File.join webfinger_dir, "webfinger" 49 | 50 | FileUtils.mkdir_p webfinger_dir 51 | File.open(webfinger_file, "w") do |file| 52 | file.write jrd_for_config(config) 53 | end 54 | 55 | @site.static_files << Jekyll::WebfingerFile.new(@site, @site.dest, ".well-known/webfinger", "") 56 | end 57 | 58 | # generates JRD for the first and only email listed 59 | def jrd_for_config(config) 60 | resource = config.keys.first 61 | 62 | acct = resource.start_with?("acct:") ? resource : "acct:#{resource}" 63 | 64 | response = { 65 | subject: acct, 66 | properties: {}, 67 | links: [] 68 | } 69 | 70 | config[resource].each do |field, value| 71 | field = field.to_s # allow symbols 72 | field_urn = URI.parse(field) rescue nil 73 | if field_urn and field_urn.scheme and field_urn.scheme.start_with?("http") 74 | # do nothing, field is already a URN 75 | else 76 | # check if we have a best practice mapping for this field 77 | field = Jekyll::WebfingerGenerator.fields[field] || field 78 | end 79 | 80 | uri = URI.parse(value) rescue nil 81 | if uri and uri.scheme and uri.scheme.start_with?("http") 82 | response[:links] << {rel: field, href: value} 83 | else 84 | response[:properties][field] = value 85 | end 86 | end 87 | 88 | JSON.generate response 89 | end 90 | 91 | def self.fields 92 | @fields ||= YAML.load_file(File.join(File.dirname(__FILE__), "urns.yml")) 93 | end 94 | 95 | end 96 | 97 | class WebfingerFile < StaticFile 98 | require 'set' 99 | 100 | def destination(dest) 101 | File.join(dest, @dir) 102 | end 103 | 104 | def modified? 105 | return false 106 | end 107 | 108 | def write(dest) 109 | return true 110 | end 111 | end 112 | end --------------------------------------------------------------------------------