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 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
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.4.1
7
+ before_install: gem install bundler -v 1.17.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ssomg.gemspec
6
+ gemspec
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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
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,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ module Ssomg
2
+ Engine.routes.draw do
3
+ get '/login', to: 'auth#login'
4
+ get '/verify', to: 'auth#verify'
5
+ get '/logout', to: 'auth#logout'
6
+ end
7
+ end
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Ssomg
2
+ VERSION = "0.1.0"
3
+ end
data/lib/ssomg.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "ssomg/version"
2
+ require "jwt"
3
+ require 'ssomg/controllers/base_controller'
4
+ require 'ssomg/controllers/auth_controller'
5
+ require 'ssomg/engine'
6
+
7
+
8
+ module Ssomg
9
+ class Error < StandardError; end
10
+ end
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: []