ssomg 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/README.md +118 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/ssomg/config/routes.rb +7 -0
- data/lib/ssomg/controllers/auth_controller.rb +18 -0
- data/lib/ssomg/controllers/base_controller.rb +107 -0
- data/lib/ssomg/engine.rb +22 -0
- data/lib/ssomg/version.rb +3 -0
- data/lib/ssomg.rb +10 -0
- data/ssomg.gemspec +42 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a63ab61cb909c5033977d9bb959ee2dbc49ee82d
|
4
|
+
data.tar.gz: '09a6599e0c2b37fd432dde7bb07f8990f20f6db7'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 205c2b2d7759f388281fbd823d881fcbe568996310ead2d0e4ca868fbd6bca4d24363770bb279aeb42202d4c6dd5b0d9a95cb9f83f33191867dd64b69e09e0cd
|
7
|
+
data.tar.gz: 7517549388c01a754f982b57f1038c635fe2d51437c745d1d4c1993987d38fd6984480d88dbdb30b4201c7c5f18c898f49bdf4785adc82345daa591e9eeba4db
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# Ssomg
|
2
|
+
This is the Ruby client for the SSOMG single sign on project, designed to work with Rails.
|
3
|
+
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'ssomg'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ssomg
|
20
|
+
|
21
|
+
|
22
|
+
One the gem is installed there are a few things to add in the code.
|
23
|
+
|
24
|
+
In `/config/application.rb`, add the line
|
25
|
+
`Ssomg.configure`
|
26
|
+
Be sure to do this after the necessary environment variables, to ensure the module configures correctly.
|
27
|
+
|
28
|
+
At the top of `/config/routes.rb`, add the line
|
29
|
+
`mount Ssomg::Engine => "auth"`
|
30
|
+
To mount the expected routes for authentication. This adds `/auth/login`, `/auth/logout` and `auth/verify` to the app, none of which have views.
|
31
|
+
|
32
|
+
Then to protect routes, make sure that you application controller inherits from `Ssomg::BaseController` ( which in turn inherits from `ActionController::Base`) :
|
33
|
+
```
|
34
|
+
class ApplicationController < Ssomg::BaseController
|
35
|
+
# your code here
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
### Usage
|
40
|
+
|
41
|
+
Once set up, controllers inheriting from your base controller will have the class variable `@user` set, which you can use to validate requests however you want.
|
42
|
+
|
43
|
+
The controller provides a `protect` method to only allow access to routes if the user has a specific role set.
|
44
|
+
There are a number of ways to do this, as shown in this example controller.
|
45
|
+
|
46
|
+
```
|
47
|
+
class WelcomeController < ApplicationController
|
48
|
+
|
49
|
+
# To protect the whole controller
|
50
|
+
before_action -> { protect(["admin"]) }
|
51
|
+
# or
|
52
|
+
before_action -> { protect("admin") }
|
53
|
+
# or
|
54
|
+
before_action -> { protect(["admin", "read"]) }
|
55
|
+
|
56
|
+
|
57
|
+
def index
|
58
|
+
# Or to protect the method
|
59
|
+
protect(["admin"])
|
60
|
+
# or
|
61
|
+
protect("admin")
|
62
|
+
# or
|
63
|
+
protect(["admin", "myrole"])
|
64
|
+
|
65
|
+
@var = "hello"
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
If a user JWT is set, @user will be set like this:
|
75
|
+
|
76
|
+
```
|
77
|
+
@user => {
|
78
|
+
"_id": "xxxxx",
|
79
|
+
"first_name": "First",
|
80
|
+
"last_name": "Last",
|
81
|
+
"email": "xxxxxxxx@xxxx.xx",
|
82
|
+
"roles": [
|
83
|
+
"App Role 1",
|
84
|
+
"App Role 2"
|
85
|
+
],
|
86
|
+
"refresh_token": "xxxxxxxxx",
|
87
|
+
"iat": xxxxxxxxxx,
|
88
|
+
"exp": xxxxxxxxxx
|
89
|
+
}
|
90
|
+
```
|
91
|
+
|
92
|
+
### Environment ###
|
93
|
+
|
94
|
+
When you register the app and the users in the main SSOMG admin, you'll be issued with an app id and the public key used to verify tokens.
|
95
|
+
You'll need to add the public key to your project, and then add the following attributes to your environment file to make sure it works correctly:
|
96
|
+
|
97
|
+
```
|
98
|
+
PUB_KEY_PATH=./keys/sso
|
99
|
+
APP_ID=xxxxxxxxxxxxxxxxxxxxxxxx
|
100
|
+
SSO_HOST=https://auth.mysite.com
|
101
|
+
```
|
102
|
+
|
103
|
+
In production, the app will automatically use secure and http-only cookies.
|
104
|
+
|
105
|
+
## Gotchas
|
106
|
+
|
107
|
+
Make sure the URLs in the env file and the provider app contain the correct protocol(http(s)), and ports. Without the correct protocols, the app will behave unexpectedly.
|
108
|
+
|
109
|
+
|
110
|
+
## Development
|
111
|
+
|
112
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
113
|
+
|
114
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
115
|
+
|
116
|
+
## Contributing
|
117
|
+
|
118
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ssomg.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ssomg"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ssomg
|
2
|
+
class AuthController < BaseController
|
3
|
+
def verify
|
4
|
+
verify_token
|
5
|
+
end
|
6
|
+
|
7
|
+
def login
|
8
|
+
cookies["ssomg_meta" ] = { :value => "/", :secure => Rails.env.production?, :httponly => true }
|
9
|
+
go_to_provider
|
10
|
+
end
|
11
|
+
|
12
|
+
def logout
|
13
|
+
clear_linked_cookies
|
14
|
+
clear_cookies
|
15
|
+
redirect_to ENV["SSO_HOST"] + "/auth/logout"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Ssomg
|
2
|
+
class BaseController < ::ActionController::Base
|
3
|
+
|
4
|
+
before_action :register_user, unless: -> { request.query_parameters["token"] }
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def register_user
|
9
|
+
if ( cookies["ssomg"] )
|
10
|
+
token = cookies["ssomg"]
|
11
|
+
else
|
12
|
+
token = bearer_token
|
13
|
+
end
|
14
|
+
if( token )
|
15
|
+
begin
|
16
|
+
decoded_token = ::JWT.decode token, Ssomg.PUB_KEY, true, { algorithm: 'RS256' }
|
17
|
+
@user = decoded_token[ 0 ]
|
18
|
+
rescue ::JWT::ExpiredSignature
|
19
|
+
cookies["ssomg_meta" ] = { :value => request.original_url, :secure => Rails.env.production?, :httponly => true }
|
20
|
+
go_to_provider
|
21
|
+
rescue StandardError
|
22
|
+
# invalid token
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def verify_token
|
28
|
+
if request.query_parameters["token"]
|
29
|
+
accessTokens = JSON.parse refresh( request.query_parameters["token"] )
|
30
|
+
cookies["ssomg" ] = { :value => accessTokens[ENV["APP_ID"]], :secure => Rails.env.production?, :httponly => true }
|
31
|
+
withoutMain = accessTokens.except!( ENV["APP_ID"] )
|
32
|
+
cookies["ssomg_all" ] = { :value => withoutMain.keys.join(","), :secure => Rails.env.production?, :httponly => true }
|
33
|
+
withoutMain.each { |key, value|
|
34
|
+
cookies["ssomg_" + key ] = { :value => value, :secure => Rails.env.production?, :httponly => true }
|
35
|
+
}
|
36
|
+
if ( cookies["ssomg_meta"] )
|
37
|
+
path = cookies["ssomg_meta"]
|
38
|
+
cookies.delete "ssomg_meta"
|
39
|
+
redirect_to path and return
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def protect( roles )
|
45
|
+
if ( @user )
|
46
|
+
if !roles.kind_of?(Array)
|
47
|
+
roles = [ roles ]
|
48
|
+
end
|
49
|
+
authorised = false;
|
50
|
+
for role in roles
|
51
|
+
if ( @user["roles"].include? role )
|
52
|
+
authorised = true
|
53
|
+
break
|
54
|
+
end
|
55
|
+
end
|
56
|
+
if ( !authorised )
|
57
|
+
head(403)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
cookies["ssomg_meta" ] = { :value => request.original_url, :secure => Rails.env.production?, :httponly => true }
|
61
|
+
go_to_provider
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def refresh( token )
|
67
|
+
require 'net/http'
|
68
|
+
require 'json'
|
69
|
+
begin
|
70
|
+
uri = URI(ENV["SSO_HOST"] + "/auth/sso")
|
71
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
72
|
+
req = Net::HTTP::Post.new(uri.path, {'Content-Type' =>'application/json'})
|
73
|
+
req.body = { :token => token }.to_json
|
74
|
+
res = http.request(req)
|
75
|
+
jwt = res.body
|
76
|
+
return jwt
|
77
|
+
rescue => e
|
78
|
+
puts "failed #{e}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def bearer_token
|
83
|
+
pattern = /^Bearer /
|
84
|
+
header = request.headers['Authorization']
|
85
|
+
header.gsub(pattern, '') if header && header.match(pattern)
|
86
|
+
end
|
87
|
+
|
88
|
+
def clear_linked_cookies
|
89
|
+
if cookies["ssomg_all"]
|
90
|
+
all_cookies = cookies["ssomg_all"].split(",")
|
91
|
+
all_cookies.each { |key| cookies.delete "ssomg_" + key }
|
92
|
+
cookies.delete "ssomg_all"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def clear_cookies
|
97
|
+
cookies.delete "ssomg_meta"
|
98
|
+
cookies.delete "ssomg"
|
99
|
+
end
|
100
|
+
|
101
|
+
def go_to_provider
|
102
|
+
clear_linked_cookies
|
103
|
+
redirect_to ENV["SSO_HOST"] + "/auth/login?app_id=" + ENV["APP_ID"]
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
data/lib/ssomg/engine.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ssomg
|
2
|
+
puts "TEst"
|
3
|
+
@@PUB_KEY = ""
|
4
|
+
class Engine < Rails::Engine
|
5
|
+
|
6
|
+
paths["app/controllers"] = ["lib/ssomg/controllers"]
|
7
|
+
paths["config/routes.rb"] = ["lib/ssomg/config/routes.rb"]
|
8
|
+
isolate_namespace Ssomg
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configure
|
12
|
+
puts "TEst 2"
|
13
|
+
puts ENV["PUB_KEY_PATH"]
|
14
|
+
puts File.read( ENV["PUB_KEY_PATH"] )
|
15
|
+
@@PUB_KEY = OpenSSL::PKey::RSA.new( File.read( ENV["PUB_KEY_PATH"] ) )
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.PUB_KEY
|
19
|
+
@@PUB_KEY
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/ssomg.rb
ADDED
data/ssomg.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "ssomg/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ssomg"
|
8
|
+
spec.version = Ssomg::VERSION
|
9
|
+
spec.authors = ["Henry McIntosh"]
|
10
|
+
spec.email = ["henry.mcintosh@roardigital.co.uk"]
|
11
|
+
|
12
|
+
spec.summary = "The SSOMG client for Ruby on Rails."
|
13
|
+
spec.description = "This is the Rails gem for setting up SSOMG with the main provider."
|
14
|
+
spec.homepage = "https://bitbucket.org/roardigital/ssomg-gem/src"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
+
spec.metadata["source_code_uri"] = "https://bitbucket.org/roardigital/ssomg-gem/src"
|
23
|
+
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
24
|
+
else
|
25
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
26
|
+
"public gem pushes."
|
27
|
+
end
|
28
|
+
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
|
+
end
|
34
|
+
spec.bindir = "exe"
|
35
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
|
+
spec.require_paths = ["lib"]
|
37
|
+
|
38
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
39
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
40
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
41
|
+
spec.add_dependency "jwt", "~> 1.5.4"
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ssomg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Henry McIntosh
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-08-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: jwt
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.5.4
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.5.4
|
69
|
+
description: This is the Rails gem for setting up SSOMG with the main provider.
|
70
|
+
email:
|
71
|
+
- henry.mcintosh@roardigital.co.uk
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/console
|
83
|
+
- bin/setup
|
84
|
+
- lib/ssomg.rb
|
85
|
+
- lib/ssomg/config/routes.rb
|
86
|
+
- lib/ssomg/controllers/auth_controller.rb
|
87
|
+
- lib/ssomg/controllers/base_controller.rb
|
88
|
+
- lib/ssomg/engine.rb
|
89
|
+
- lib/ssomg/version.rb
|
90
|
+
- ssomg.gemspec
|
91
|
+
homepage: https://bitbucket.org/roardigital/ssomg-gem/src
|
92
|
+
licenses: []
|
93
|
+
metadata:
|
94
|
+
allowed_push_host: https://rubygems.org
|
95
|
+
homepage_uri: https://bitbucket.org/roardigital/ssomg-gem/src
|
96
|
+
source_code_uri: https://bitbucket.org/roardigital/ssomg-gem/src
|
97
|
+
changelog_uri: 'TODO: Put your gem''s CHANGELOG.md URL here.'
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.6.14
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: The SSOMG client for Ruby on Rails.
|
118
|
+
test_files: []
|