omniauth-discourse 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f61a5877fb60d7830421987d8f197ae16d975af
4
+ data.tar.gz: 9e9c4dd107e329bacf9038e1be00f611d2639fb4
5
+ SHA512:
6
+ metadata.gz: eeb010c4df0d42a400baaee162e52efaa111564c4dcbc4767d6dbf4dd6e61c2c4a87b315bd0675a49a38f5294987da4043bf20c7489dc4dd7fe8b57fa085758f
7
+ data.tar.gz: 39c5aae8a5e8d070fb0a439c9ae18159cee26b7e6d7a62ca503ae532b9a5d02d62854d3dba01321be6c29411609cf3ad2bfa5fe82da258d04af3023a86e662a7
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rubocop.yml ADDED
@@ -0,0 +1,52 @@
1
+ Metrics/AbcSize:
2
+ Enabled: false
3
+
4
+ Metrics/BlockNesting:
5
+ Max: 2
6
+
7
+ Metrics/LineLength:
8
+ AllowURI: true
9
+ Enabled: false
10
+
11
+ Metrics/MethodLength:
12
+ CountComments: false
13
+ Max: 10
14
+
15
+ Metrics/ParameterLists:
16
+ Max: 4
17
+ CountKeywordArgs: true
18
+
19
+ Style/AccessModifierIndentation:
20
+ EnforcedStyle: outdent
21
+
22
+ Style/CollectionMethods:
23
+ PreferredMethods:
24
+ map: 'collect'
25
+ reduce: 'inject'
26
+ find: 'detect'
27
+ find_all: 'select'
28
+
29
+ Style/Documentation:
30
+ Enabled: false
31
+
32
+ Style/DotPosition:
33
+ EnforcedStyle: trailing
34
+
35
+ Style/DoubleNegation:
36
+ Enabled: false
37
+
38
+ Style/FileName:
39
+ Exclude:
40
+ - 'lib/omniauth-oauth.rb'
41
+
42
+ Style/HashSyntax:
43
+ EnforcedStyle: hash_rockets
44
+
45
+ Style/Lambda:
46
+ Enabled: false
47
+
48
+ Style/SpaceInsideHashLiteralBraces:
49
+ EnforcedStyle: no_space
50
+
51
+ Style/StringLiterals:
52
+ EnforcedStyle: double_quotes
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+
7
+ group :test do
8
+ gem "rack-test"
9
+ gem "rspec", "~> 3.2"
10
+ gem "rubocop", ">= 0.30", :platforms => [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
11
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Noah Lackstein
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # OmniAuth Discourse
2
+ ...
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new
6
+
7
+ begin
8
+ require "rubocop/rake_task"
9
+ RuboCop::RakeTask.new
10
+ rescue LoadError
11
+ task :rubocop do
12
+ $stderr.puts "Rubocop is disabled"
13
+ end
14
+ end
15
+
16
+ task :default => [:spec, :rubocop]
@@ -0,0 +1,2 @@
1
+ require "omniauth-discourse/version"
2
+ require "omniauth/strategies/discourse"
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module Discourse
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,54 @@
1
+ require "omniauth"
2
+ require "omniauth/strategies/discourse/sso"
3
+
4
+ module OmniAuth
5
+ module Strategies
6
+ class Discourse
7
+ include OmniAuth::Strategy
8
+
9
+ args [:sso_secret, :sso_url]
10
+ option :sso_secret, nil
11
+ option :sso_url, nil
12
+
13
+ attr_reader :user_info
14
+
15
+ def request_phase
16
+ sso = SSO.new(options.sso_secret, options.sso_url, callback_url)
17
+ session[:sso_nonce] = sso.nonce
18
+
19
+ redirect sso.request_url
20
+ end
21
+
22
+ def callback_phase
23
+ sso = SSO.new(options.sso_secret, options.sso_url, callback_url, session[:sso_nonce])
24
+ sso.parse(request.params)
25
+ raise OmniAuth::NoSessionError, "Username or password are not valid" if sso.status == "error"
26
+
27
+ @user_info = sso.user_info
28
+
29
+ super
30
+ rescue OmniAuth::NoSessionError => e
31
+ fail!(:invalid_credentials, e)
32
+ end
33
+
34
+ uid do
35
+ user_info[:external_id]
36
+ end
37
+
38
+ info do
39
+ {
40
+ "name" => user_info[:name],
41
+ "email" => user_info[:email],
42
+ "nickname" => user_info[:username]
43
+ }
44
+ end
45
+
46
+ extra do
47
+ {
48
+ "admin" => user_info[:admin] == "true",
49
+ "moderator" => user_info[:moderator] == "true"
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,86 @@
1
+ require "securerandom"
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+ class Discourse
6
+ class SSO
7
+ attr_accessor :nonce, :user_info, :status, :message
8
+
9
+ def initialize(sso_secret, sso_url, return_url, nonce = nil)
10
+ @sso_secret, @sso_url, @return_url = sso_secret, sso_url, return_url
11
+ @nonce = nonce ? nonce : generate_nonce!
12
+ end
13
+
14
+ def generate_nonce!
15
+ SecureRandom.hex()
16
+ end
17
+
18
+ def request_url
19
+ "#{ @sso_url }?sso=#{ url_encoded_payload }&sig=#{ hex_signature }"
20
+ end
21
+
22
+ def parse(params)
23
+ #params should be something that looks like: {"sso": "xxxxxx", "sig": "yyyyyy"}
24
+ if get_hmac_hex_string(params["sso"]) == params["sig"]
25
+ if base64? params["sso"]
26
+ decoded_hash = Rack::Utils.parse_query(Base64.decode64(params["sso"]))
27
+ decoded_hash.symbolize_keys!
28
+ if decoded_hash[:nonce] == @nonce
29
+ @status = "success"
30
+ decoded_hash.delete(:nonce)
31
+ @user_info = decoded_hash
32
+ @message = "SSO verification passed."
33
+ return self
34
+ else
35
+ @status = "error"
36
+ @user_info = nil
37
+ @message = "SSO verification failed. Nonce mismatch."
38
+ return nil
39
+ end
40
+ else
41
+ @status = "error"
42
+ @user_info = nil
43
+ @message = "The sso string is supposed to be encoded in Base64."
44
+ return nil
45
+ end
46
+ else
47
+ @status = "error"
48
+ @user_info = nil
49
+ @message = "HMAC mismatch. The message may have been tampered with."
50
+ return nil
51
+ end
52
+ end
53
+
54
+ private
55
+ def raw_payload
56
+ unless @nonce
57
+ raise "You must generate a nonce by calling generate_nonce! first."
58
+ else
59
+ "nonce=#{ @nonce }&return_sso_url=#{ @return_url }"
60
+ end
61
+ end
62
+
63
+ def base64_encoded_payload
64
+ Base64.encode64(raw_payload)
65
+ end
66
+
67
+ def url_encoded_payload
68
+ URI.escape(base64_encoded_payload)
69
+ end
70
+
71
+ def hex_signature
72
+ get_hmac_hex_string base64_encoded_payload
73
+ end
74
+
75
+ def get_hmac_hex_string payload
76
+ OpenSSL::HMAC.hexdigest("sha256", @sso_secret, payload)
77
+ end
78
+
79
+ def base64? data
80
+ !(data =~ /[^a-zA-Z0-9=\r\n\/+]/m)
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path("../lib/omniauth-discourse/version", __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ["Noah Lackstein"]
5
+ gem.email = ["noah@lackstein.com"]
6
+ gem.description = "A generic strategy for OmniAuth to authenticate against Discourse forum's SSO."
7
+ gem.summary = gem.description
8
+ gem.homepage = "https://github.com/lackstein/omniauth-discourse"
9
+ gem.license = "MIT"
10
+
11
+ gem.add_dependency "omniauth", "~> 1.0"
12
+ gem.add_development_dependency "bundler", "~> 1.9"
13
+
14
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ gem.name = "omniauth-discourse"
18
+ gem.require_paths = ["lib"]
19
+ gem.version = OmniAuth::Discourse::VERSION
20
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-discourse
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Noah Lackstein
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: omniauth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.9'
41
+ description: A generic strategy for OmniAuth to authenticate against Discourse forum's
42
+ SSO.
43
+ email:
44
+ - noah@lackstein.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".rubocop.yml"
51
+ - Gemfile
52
+ - LICENSE
53
+ - README.md
54
+ - Rakefile
55
+ - lib/omniauth-discourse.rb
56
+ - lib/omniauth-discourse/version.rb
57
+ - lib/omniauth/strategies/discourse.rb
58
+ - lib/omniauth/strategies/discourse/sso.rb
59
+ - omniauth-discourse.gemspec
60
+ homepage: https://github.com/lackstein/omniauth-discourse
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.5.1
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: A generic strategy for OmniAuth to authenticate against Discourse forum's
84
+ SSO.
85
+ test_files: []