Working commit

This commit is contained in:
Eugen Rochko 2016-10-22 14:54:20 +02:00
parent e99e83fe90
commit 63309f0857
4 changed files with 97 additions and 4 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
coverage
doc
.yardoc
*.gem

View File

@ -1,2 +1,39 @@
OmniAuth::Mastodon
==================
[![Gem Version](http://img.shields.io/gem/v/omniauth-mastodon.svg)][gem]
[gem]: https://rubygems.org/gems/omniauth-mastodon
Authentication strategy for federated Mastodon instances. This is just slightly more complicated than a traditional OAuth2 flow: We do not know the URL of the OAuth end-points in advance, nor can we be sure that
we already have client credentials for that Mastodon instance.
## Installation
gem 'mastodon-api', require: 'mastodon'
gem 'omniauth-mastodon'
gem 'omniauth'
## Configuration
Example:
```ruby
Rails.application.config.middleware.use OmniAuth::Builder do
provider :mastodon, credentials: lambda { |domain, callback_url|
Rails.logger.info "Requested credentials for #{domain} with callback URL #{callback_url}"
existing = MastodonClient.find_by(domain: domain)
return [existing.client_id, existing.client_secret] unless existing.nil?
client = Mastodon::REST::Client.new(base_url: "https://#{domain}")
app = client.create_app('OmniAuth Test Harness', callback_url)
MastodonClient.create!(domain: domain, client_id: app.client_id, client_secret: app.client_secret)
[app.client_id, app.client_secret]
}
end
```
The only configuration key you need to set is a lambda for `:credentials`. That lambda will be called whenever we need to get client credentials for OAuth2 requests. The example above uses an ActiveRecord model to store client credentials for different Mastodon domains, and uses the `mastodon-api` gem to fetch them dynamically if they're not stored yet.

View File

@ -8,11 +8,11 @@ module OmniAuth
end
def minor
0
9
end
def patch
1
0
end
def pre

View File

@ -5,9 +5,15 @@ module OmniAuth
class Mastodon < OmniAuth::Strategies::OAuth2
option :name, 'mastodon'
option :domain
option :credentials
option :identifier
uid { [raw_info['username'], '@', options.domain].join }
option :client_options, {
authorize_url: '/oauth/authorize',
token_url: '/oauth/token'
}
uid { identifier }
info do
{
@ -22,9 +28,55 @@ module OmniAuth
{ raw_info: raw_info }
end
# Before we can redirect the user to authorize access, we must know where the user is from
# If the identifier param is not already present, a form will be shown for entering it
def request_phase
identifier ? start_oauth : get_identifier
end
def callback_phase
set_options_from_identifier
super
end
def raw_info
@raw_info ||= access_token.get('api/v1/accounts/verify_credentials').parsed
end
def callback_url
full_host + script_name + callback_path
end
private
def get_identifier
form = OmniAuth::Form.new(title: 'Mastodon Login')
form.text_field 'Your full Mastodon identifier', 'identifier'
form.button 'Login'
form.to_response
end
def start_oauth
set_options_from_identifier
redirect client.auth_code.authorize_url({:redirect_uri => callback_url}.merge(authorize_params))
end
def identifier
i = options.identifier || request.params['identifier'] || (env['omniauth.params'].is_a?(Hash) ? env['omniauth.params']['identifier'] : nil)
i = i.downcase.strip unless i.nil?
i = nil if i == ''
i
end
def set_options_from_identifier
username, domain = identifier.split('@')
client_id, client_secret = options.credentials.call(domain, callback_url)
options.identifier = identifier
options.client_options[:site] = "https://#{domain}"
options.client_id = client_id
options.client_secret = client_secret
end
end
end
end