omniauth-practicefusion 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5648b53f57eb785f9d3ab77ea18dcd6d0784e6df
4
+ data.tar.gz: 0ad8b7b987221e15113a6a480905cac1934b03ab
5
+ SHA512:
6
+ metadata.gz: f3279e687df651a49fd482409053b694516527e7b65ed701fd8191012459c11eacd37c9c87a62321dd8915f00b8acdf94a7d83cbb80d4c048b856bfc033f9b88
7
+ data.tar.gz: 222877ff3c0448268b24631feed9bf8510ab9b3799af2cff558ab011b9de554586a9d9041c4040c247b389fc7ec92443d671ff613560276de1094272f915d5e2
@@ -0,0 +1,28 @@
1
+ *.rbc
2
+ .bundle
3
+ .config
4
+ .yardoc
5
+ Gemfile.lock
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ *.bundle
18
+ *.so
19
+ *.o
20
+ *.a
21
+ *.gem
22
+ mkmf.log
23
+
24
+ /.idea/
25
+
26
+ /.ruby-version
27
+
28
+ /omniauth-practicefusion.iml
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in omniauth-practicefusion.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Sam Contapay
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,131 @@
1
+ # Omniauth::PracticeFusion
2
+
3
+ OAuth 2 strategy for Practice Fusion. Redundant description :\
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ source 'http://gems.hq.practicefusion.com'
10
+ gem 'omniauth-practicefusion'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ ## Usage
17
+
18
+ This works with Devise and Omniauth.
19
+ Get an App ID and Secret from Ken.
20
+ Give him your callback URL (/users/auth/practicefusion/callback).
21
+
22
+ ## Configuration
23
+
24
+ ```
25
+ Rails.application.config.middleware.use OmniAuth::Builder do
26
+ provider OmniAuth::Strategies::PracticeFusion, ENV['PF_OAUTH_CLIENT_ID'], ENV['PF_OAUTH_CLIENT_SECRET'], {
27
+ scope: ENV['PF_OAUTH_SCOPE'],
28
+ path_prefix: '/providers/auth',
29
+ client_options: {
30
+ site: ENV['PF_OAUTH_SITE_URL'],
31
+ }
32
+ }
33
+ end
34
+ ```
35
+
36
+ ## Sample Hash
37
+
38
+ ```
39
+ {
40
+ "provider" => "practicefusion",
41
+ "uid" => "3cbbbd62-159d-4c40-be4c-2cdf784d6c7d",
42
+ "info" => {
43
+ "title" => "Dr",
44
+ "first_name" => "Sam",
45
+ "last_name" => "Withnoname",
46
+ "practice_guid" => "9571286c-c379-4053-9fa3-04caeb62fb69",
47
+ "email" => "sam@dev.practicefusion.com"
48
+ },
49
+ "credentials" => {
50
+ "token" => "3hvHj7PyVFH9TGyDFXaq",
51
+ "refresh_token" => "VqycQpxuBS5tjP_Kaab-",
52
+ "expires_at" => 1412279343,
53
+ "expires" => true
54
+ },
55
+ "extra" => {
56
+ "raw_info" => {
57
+ "title" => "Dr",
58
+ "firstName" => "Sam",
59
+ "lastName" => "Withnoname",
60
+ "practiceGuid" => "9571286c-c379-4053-9fa3-04caeb62fb69",
61
+ "ehrUserGuid" => "3cbbbd62-159d-4c40-be4c-2cdf784d6c7d",
62
+ "loginEmailAddress" => "sam@dev.practicefusion.com"
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### Devise
69
+
70
+ First define your application id and secret in "config/initializers/devise.rb" your scope maybe different. TODO add all available scopes.
71
+
72
+ ```ruby
73
+ config.omniauth :practicefusion, ENV['PF_APP_ID'], ENV['PF_APP_SECRET'], {
74
+ scope: 'user:r_basic',
75
+ response_type: 'code'
76
+ }
77
+ ```
78
+
79
+ Then add the following to 'config/routes.rb' so the callback routes are defined.
80
+
81
+ ```ruby
82
+ devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
83
+ ```
84
+ f
85
+ Devise default callback URL is '/users/auth/practicefusion/callback' with the above route.
86
+
87
+ Make sure your model is omniauthable. Generally this is "/app/models/user.rb"
88
+
89
+ ```ruby
90
+ devise :omniauthable, :omniauth_providers => [:practicefusion]
91
+ ```
92
+
93
+ Then make sure your callbacks controller is setup.
94
+
95
+ ```ruby
96
+ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
97
+ def practicefusion
98
+ @user = User.find_for_practicefusion(request.env['omniauth.auth'], current_user)
99
+
100
+ if @user.persisted?
101
+ sign_in_and_redirect @user, event: :authentication
102
+ else
103
+ redirect_to new_user_registration_url
104
+ end
105
+ end
106
+ end
107
+ ```
108
+
109
+ and bind to or create the user
110
+
111
+ ```ruby
112
+ def self.find_for_practicefusion(access_token, signed_in_resource = nil)
113
+ user = User.where(ehr_user_guid: access_token['uid']).first
114
+ unless user
115
+ user = User.create(name: access_token['info']['first_name'] + ' ' + access_token['info']['last_name'], ehr_user_guid: access_token['uid'], email: access_token['info']['email'], password: Devise.friendly_token[0,20])
116
+ end
117
+ user
118
+ end
119
+ ```
120
+
121
+ For your views you can login using:
122
+
123
+ ```ruby
124
+ <%= link_to "Sign in with Practice Fusion", user_omniauth_authorize_path(:practicefusion) %>
125
+ ```
126
+
127
+
128
+
129
+ ## Contributing
130
+
131
+ YES PLEASE LIKE SPECS
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,2 @@
1
+ require 'omniauth/practicefusion'
2
+
@@ -0,0 +1,2 @@
1
+ require 'omniauth/practicefusion/version'
2
+ require 'omniauth/strategies/practicefusion'
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module PracticeFusion
3
+ VERSION = '2.2.0'
4
+ end
5
+ end
@@ -0,0 +1,127 @@
1
+ require 'omniauth/strategies/oauth2'
2
+ require 'jwt'
3
+
4
+ module OmniAuth
5
+ module Strategies
6
+ class PracticeFusion < OmniAuth::Strategies::OAuth2
7
+
8
+ option :name, 'practicefusion'
9
+
10
+ option :authorize_options, [:response_type, :client_id, :redirect_uri, :Fauthcode, :scope]
11
+ option :client_options, {
12
+ site: 'https://api.practicefusion.com',
13
+ authorize_url: '/ehr/oauth2/auth',
14
+ token_url: '/ehr/oauth2/token'
15
+ }
16
+
17
+ uid { raw_info['ehrUserGuid'] }
18
+
19
+ info do
20
+ prune!({
21
+ title: value_or_blank(raw_info['title']),
22
+ first_name: value_or_blank(raw_info['firstName']),
23
+ last_name: value_or_blank(raw_info['lastName']),
24
+ provider_guid: value_or_blank(raw_info['providerGuid']),
25
+ practice_guid: value_or_blank(raw_info['practiceGuid']),
26
+ email: value_or_blank(raw_info['loginEmailAddress'])
27
+ })
28
+ end
29
+
30
+ extra do
31
+ hash = {}
32
+ hash[:raw_info] = raw_info
33
+ prune! hash
34
+ end
35
+
36
+ credentials do
37
+ # these are copy-paste from OmniAuth::Strategy::OAuth2
38
+ hash = {'token' => access_token.token}
39
+ hash.merge!('refresh_token' => access_token.refresh_token) if access_token.expires? && access_token.refresh_token
40
+ hash.merge!('expires_at' => access_token.expires_at) if access_token.expires?
41
+ hash.merge!('expires' => access_token.expires?)
42
+
43
+ # additional parameters returned by Practice Fusion
44
+ hash.merge!('token_type' => access_token['token_type'])
45
+ hash.merge!('scope' => access_token['scope'])
46
+ hash.merge!('resource_owner' => access_token['resource_owner'])
47
+ hash.merge!('resource_owner_authority' => access_token['resource_owner_authority'])
48
+ hash.merge!('pf_session_token' => access_token['pf_session_token']) if access_token.params.key?('pf_session_token')
49
+ hash
50
+ end
51
+
52
+ # override callback_url so we don't include query parameters
53
+ # See https://github.com/intridea/omniauth-oauth2/issues/81 for more details
54
+ def callback_url
55
+ full_host + script_name + callback_path
56
+ end
57
+
58
+ def raw_info
59
+ @raw_info ||= access_token.get('/ehr/v1/users/me').parsed
60
+ end
61
+
62
+ # add the 'authCookie' parameter to the outbound request
63
+ # the 'state' parameter becomes an encrypted JWT of the session
64
+ def authorize_params
65
+ super.merge(session['omniauth.params'].slice('authCookie')).tap do |authz_params|
66
+ # so omniauth decided (in their infinite wisdom) that instead of setting the
67
+ # omniauth.origin parameter using their session method, they were gonna access
68
+ # env['rack.session'] directly, so we need to pull that out into the session
69
+ session['omniauth.origin'] = env['rack.session']['omniauth.origin']
70
+ authz_params[:state] = JWT.encode(session, options.client_secret)
71
+ end
72
+ end
73
+
74
+ # override the callback_phase so we can validate the state token signature
75
+ def callback_phase
76
+ # If decode_state_parameter returns the correct state token, then
77
+ # request.params['state'] == session['omniauth.state']
78
+ # which passes the CSRF check of omniauth-oauth2
79
+
80
+ # If decode_state_parameter returns nil, then this is true:
81
+ # request.params['state'].to_s.empty?
82
+ # which fails the CSRF check of omniauth-oauth2
83
+ request.params['state'] = decode_state_parameter
84
+
85
+ # omniauth sets the environment up _before_ the callback_phase
86
+ # begins, but we need to set it up after we've decoded the session
87
+ @env['omniauth.origin'] = session.delete('omniauth.origin')
88
+ @env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
89
+ @env['omniauth.params'] = session.delete('omniauth.params')
90
+
91
+ # And now back to our regularly scheduled program
92
+ super
93
+ end
94
+
95
+ # instead of using the session store, just collect into a hash
96
+ def session
97
+ @fake_session ||= {}
98
+ end
99
+
100
+ def session=(obj)
101
+ @fake_session = obj
102
+ end
103
+
104
+ private
105
+
106
+ def prune!(hash)
107
+ hash.delete_if do |_, v|
108
+ prune!(v) if v.is_a?(Hash)
109
+ v.nil? || (v.respond_to?(:empty?) && v.empty?)
110
+ end
111
+ end
112
+
113
+ def value_or_blank(value)
114
+ (value.blank?) ? '' : value
115
+ end
116
+
117
+ def decode_state_parameter
118
+ # this will throw an exception if the state parameter is not valid ciphertext
119
+ # otherwise, decode the JWT and stick the object back into our fake session
120
+ self.session, _jwt = JWT.decode(request.params["state"].to_s, options.client_secret)
121
+ session['omniauth.state']
122
+ rescue JWT::VerificationError, JWT::DecodeError
123
+ nil
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'omniauth/practicefusion/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.add_dependency 'omniauth', '> 1.0'
8
+
9
+ spec.name = "omniauth-practicefusion"
10
+ spec.version = OmniAuth::PracticeFusion::VERSION
11
+ spec.authors = ["Sam Contapay, Shaun Guth"]
12
+ spec.email = ["scontapay@practicefusion.com", "sguth@practicefusion.com"]
13
+ spec.summary = %q{omniauth strategy for Practice Fusion}
14
+ spec.description = %q{Lets you use Practice Fusion as a strategy for your omniauth login flows}
15
+ spec.homepage = ""
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_runtime_dependency 'omniauth-oauth2', '~> 1.5'
24
+ spec.add_runtime_dependency 'json-jwt', '~> 1.0', '>= 1.0.3'
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.6"
27
+ spec.add_development_dependency "rake"
28
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-practicefusion
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Contapay, Shaun Guth
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-09-29 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: omniauth-oauth2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json-jwt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 1.0.3
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '1.0'
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.0.3
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.6'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.6'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description: Lets you use Practice Fusion as a strategy for your omniauth login flows
90
+ email:
91
+ - scontapay@practicefusion.com
92
+ - sguth@practicefusion.com
93
+ executables: []
94
+ extensions: []
95
+ extra_rdoc_files: []
96
+ files:
97
+ - ".gitignore"
98
+ - Gemfile
99
+ - LICENSE.txt
100
+ - README.md
101
+ - Rakefile
102
+ - lib/omniauth-practicefusion.rb
103
+ - lib/omniauth/practicefusion.rb
104
+ - lib/omniauth/practicefusion/version.rb
105
+ - lib/omniauth/strategies/practicefusion.rb
106
+ - omniauth-practicefusion.gemspec
107
+ homepage: ''
108
+ licenses:
109
+ - MIT
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.6.11
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: omniauth strategy for Practice Fusion
131
+ test_files: []