mauth-client 4.0.1
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 +8 -0
- data/.travis.yml +13 -0
- data/.yardopts +4 -0
- data/CHANGELOG.md +119 -0
- data/CONTRIBUTING.md +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +19 -0
- data/README.md +235 -0
- data/Rakefile +7 -0
- data/doc/implementations.md +6 -0
- data/doc/mauth-client_CLI.md +59 -0
- data/doc/mauth-proxy.md +71 -0
- data/doc/mauth.yml.md +73 -0
- data/examples/Gemfile +4 -0
- data/examples/Gemfile.lock +41 -0
- data/examples/README.md +33 -0
- data/examples/config.yml +8 -0
- data/examples/get_user_info.rb +58 -0
- data/examples/mauth_key +0 -0
- data/exe/mauth-client +264 -0
- data/exe/mauth-proxy +40 -0
- data/lib/mauth/autoload.rb +8 -0
- data/lib/mauth/client.rb +487 -0
- data/lib/mauth/core_ext.rb +7 -0
- data/lib/mauth/dice_bag/mauth.rb.dice +12 -0
- data/lib/mauth/dice_bag/mauth.yml.dice +14 -0
- data/lib/mauth/dice_bag/mauth_key.dice +1 -0
- data/lib/mauth/dice_bag/mauth_templates.rb +19 -0
- data/lib/mauth/fake/rack.rb +45 -0
- data/lib/mauth/faraday.rb +87 -0
- data/lib/mauth/middleware.rb +23 -0
- data/lib/mauth/proxy.rb +77 -0
- data/lib/mauth/rack.rb +137 -0
- data/lib/mauth/request_and_response.rb +73 -0
- data/lib/mauth/version.rb +3 -0
- data/lib/mauth-client.rb +1 -0
- data/lib/rack/mauth.rb +1 -0
- data/mauth-client.gemspec +36 -0
- metadata +292 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
mauth-client (3.1.4)
|
5
|
+
coderay (~> 1.0)
|
6
|
+
dice_bag (>= 0.9, < 2.0)
|
7
|
+
faraday (~> 0.7)
|
8
|
+
faraday_middleware (~> 0.9)
|
9
|
+
rack
|
10
|
+
term-ansicolor (~> 1.0)
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
coderay (1.1.1)
|
16
|
+
dice_bag (1.1.1)
|
17
|
+
diff-lcs (~> 1.0)
|
18
|
+
rake
|
19
|
+
thor (~> 0.0)
|
20
|
+
diff-lcs (1.2.5)
|
21
|
+
faraday (0.9.2)
|
22
|
+
multipart-post (>= 1.2, < 3)
|
23
|
+
faraday_middleware (0.10.0)
|
24
|
+
faraday (>= 0.7.4, < 0.10)
|
25
|
+
multipart-post (2.0.0)
|
26
|
+
rack (2.0.1)
|
27
|
+
rake (11.2.2)
|
28
|
+
term-ansicolor (1.3.2)
|
29
|
+
tins (~> 1.0)
|
30
|
+
thor (0.19.1)
|
31
|
+
tins (1.11.0)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
ruby
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
faraday (~> 0.9.0)
|
38
|
+
mauth-client!
|
39
|
+
|
40
|
+
BUNDLED WITH
|
41
|
+
1.12.5
|
data/examples/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Examples
|
2
|
+
|
3
|
+
## Configuration
|
4
|
+
|
5
|
+
After obtaining valid credentials you need to edit the `config.yml` file and set the `app_uuid` accordingly.
|
6
|
+
You also need to provide a mauth key and put it in the `mauth_key` file.
|
7
|
+
See [the mauth config file doc](../doc/mauth.yml.md) for more information.
|
8
|
+
|
9
|
+
This folder contains its own Gemfile and Gemfile.lock files to manage dependencies so you need to run
|
10
|
+
```
|
11
|
+
bundle install
|
12
|
+
```
|
13
|
+
before trying any of the scripts.
|
14
|
+
|
15
|
+
|
16
|
+
## Fetching a given user's info
|
17
|
+
|
18
|
+
Simply run the provided shell script by passing an user's UUID, for instance:
|
19
|
+
```
|
20
|
+
./get_user_info.rb 4735d013-8d78-4980-8846-fbecf0db0b8e
|
21
|
+
```
|
22
|
+
|
23
|
+
This should print the user's info, something along the lines of:
|
24
|
+
```
|
25
|
+
{
|
26
|
+
"user": {
|
27
|
+
"login": "name",
|
28
|
+
"email": "the.email.address@example.com",
|
29
|
+
"uuid": "4735d013-8d78-4980-8846-fbecf0db0b8e",
|
30
|
+
...
|
31
|
+
}
|
32
|
+
}
|
33
|
+
```
|
data/examples/config.yml
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
abort "USAGE: ./#{__FILE__} <USER UUID>" unless ARGV.size == 1
|
4
|
+
|
5
|
+
require 'bundler/setup'
|
6
|
+
Bundler.require(:default)
|
7
|
+
|
8
|
+
def config
|
9
|
+
@conf ||= YAML.load(File.open("./config.yml"))
|
10
|
+
end
|
11
|
+
|
12
|
+
# get user information
|
13
|
+
def get_user_info_mauth(user_uuid)
|
14
|
+
get_data_from_imedidata "users/#{user_uuid}.json"
|
15
|
+
end
|
16
|
+
|
17
|
+
# fetch data from iMedidata
|
18
|
+
def get_data_from_imedidata(resource_name)
|
19
|
+
puts "fetching #{resource_name}..."
|
20
|
+
begin
|
21
|
+
connection = Faraday::Connection.new(url: config["imedidata"]["host"]) do |builder|
|
22
|
+
builder.use MAuth::Faraday::RequestSigner, config["mauth"]
|
23
|
+
builder.adapter Faraday.default_adapter
|
24
|
+
end
|
25
|
+
|
26
|
+
# get the data
|
27
|
+
response = connection.get "/api/v2/#{resource_name}"
|
28
|
+
puts "HTTP #{response.status}"
|
29
|
+
|
30
|
+
# return the user info
|
31
|
+
if response.status == 200
|
32
|
+
result = JSON.parse(response.body)
|
33
|
+
puts JSON.pretty_generate(result)
|
34
|
+
result
|
35
|
+
else
|
36
|
+
puts response.body
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
rescue JSON::ParserError => e
|
40
|
+
puts "Error parsing data from imedidata: #{e.inspect}"
|
41
|
+
puts e.backtrace.join("\n")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
get_user_info_mauth(ARGV[0])
|
46
|
+
|
47
|
+
|
48
|
+
### OTHER EXAMPLES
|
49
|
+
|
50
|
+
#### get study groups for an user
|
51
|
+
def get_study_groups_mauth(user_uuid)
|
52
|
+
get_data_from_imedidata "users/#{user_uuid}/study_groups.json"
|
53
|
+
end
|
54
|
+
|
55
|
+
#### get roles for a user in an application study
|
56
|
+
def get_user_study_roles_mauth(user_uuid, study_uuid)
|
57
|
+
get_data_from_imedidata "users/#{user_uuid}/studies/#{study_uuid}/apps/#{config["mauth"]["app_uuid"]}/roles.json"
|
58
|
+
end
|
data/examples/mauth_key
ADDED
File without changes
|
data/exe/mauth-client
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'faraday'
|
7
|
+
require 'faraday_middleware'
|
8
|
+
require 'logger'
|
9
|
+
require 'mauth/client'
|
10
|
+
require 'mauth/faraday'
|
11
|
+
require 'yaml'
|
12
|
+
require 'term/ansicolor'
|
13
|
+
|
14
|
+
# OPTION PARSER
|
15
|
+
|
16
|
+
require 'optparse'
|
17
|
+
|
18
|
+
# $options default values
|
19
|
+
$options = {
|
20
|
+
:authenticate_response => true,
|
21
|
+
:verbose => true,
|
22
|
+
:color => nil,
|
23
|
+
:no_ssl_verify => false,
|
24
|
+
}
|
25
|
+
|
26
|
+
additional_headers = []
|
27
|
+
opt_parser = OptionParser.new do |opts|
|
28
|
+
opts.banner = "Usage: mauth-client [options] <verb> <url> [body]"
|
29
|
+
|
30
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely - output is like curl -v (this is the default)") do |v|
|
31
|
+
$options[:verbose] = v
|
32
|
+
end
|
33
|
+
opts.on("-q", "Run quietly - only outputs the response body (same as --no-verbose)") do |v|
|
34
|
+
$options[:verbose] = !v
|
35
|
+
end
|
36
|
+
opts.on("--[no-]authenticate", "Authenticate the response received") do |v|
|
37
|
+
$options[:authenticate_response] = v
|
38
|
+
end
|
39
|
+
opts.on("--[no-]color", "Color the output (defaults to color if the output device is a TTY)") do |v|
|
40
|
+
$options[:color] = v
|
41
|
+
end
|
42
|
+
opts.on("-t", "--content-type CONTENT-TYPE", "Sets the Content-Type header of the request") do |v|
|
43
|
+
$options[:content_type] = v
|
44
|
+
end
|
45
|
+
opts.on("-H", "--header LINE", "accepts a json string of additional headers to included. IE 'cache-expirey: 10, other: value") do |v|
|
46
|
+
additional_headers << v
|
47
|
+
end
|
48
|
+
opts.on("--no-ssl-verify", "Disables SSL verification - use cautiously!") do
|
49
|
+
$options[:no_ssl_verify] = true
|
50
|
+
end
|
51
|
+
$options[:additional_headers] =additional_headers
|
52
|
+
end
|
53
|
+
opt_parser.parse!
|
54
|
+
abort(opt_parser.help) unless (2..3).include?(ARGV.size)
|
55
|
+
|
56
|
+
# FIND MAUTH CONFIG
|
57
|
+
|
58
|
+
possible_mauth_config_files = [
|
59
|
+
# whoops, I called this MAUTH_CONFIG_YML in one place and MAUTH_CONFIG_YAML in another. supporting both for now.
|
60
|
+
ENV['MAUTH_CONFIG_YML'],
|
61
|
+
ENV['MAUTH_CONFIG_YAML'],
|
62
|
+
'~/.mauth_config.yml',
|
63
|
+
'./config/mauth.yml',
|
64
|
+
'./mauth.yml',
|
65
|
+
].compact
|
66
|
+
|
67
|
+
mauth_config_yml = possible_mauth_config_files.detect do |filename|
|
68
|
+
File.exists?(File.expand_path(filename))
|
69
|
+
end
|
70
|
+
unless mauth_config_yml
|
71
|
+
message = "could not find mauth config. giving up. please place a mauth config in one of the standard places, " +
|
72
|
+
"or point the MAUTH_CONFIG_YML environment variable at an existing one. standard places are:" +
|
73
|
+
possible_mauth_config_files.map{|f| "\n\t#{f}" }.join
|
74
|
+
abort message
|
75
|
+
end
|
76
|
+
|
77
|
+
mauth_config = MAuth::Client.default_config(:mauth_config_yml => File.expand_path(mauth_config_yml))
|
78
|
+
|
79
|
+
# INSTANTIATE MAUTH CLIENT
|
80
|
+
|
81
|
+
logger = Logger.new(STDERR)
|
82
|
+
mauth_client = MAuth::Client.new(mauth_config.merge('logger' => logger))
|
83
|
+
|
84
|
+
# OUTPUTTERS FOR FARADAY THAT SHOULD MOVE TO A LIB SOMEWHERE
|
85
|
+
|
86
|
+
# outputs the response body to the given output device (defaulting to STDOUT)
|
87
|
+
class FaradayOutputter < Faraday::Middleware
|
88
|
+
def initialize(app, outdev=STDOUT)
|
89
|
+
@app=app
|
90
|
+
@outdev = outdev
|
91
|
+
end
|
92
|
+
|
93
|
+
def call(request_env)
|
94
|
+
@app.call(request_env).on_complete do |response_env|
|
95
|
+
@outdev.puts(response_env[:body] || '')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# this is to approximate `curl -v`s output. but it's all faked, whereas curl gives you
|
101
|
+
# the real text written and read for request and response. whatever, close enough.
|
102
|
+
class FaradayCurlVOutputter < FaradayOutputter
|
103
|
+
|
104
|
+
# defines a method with the given name, applying coloring defined by any additional arguments.
|
105
|
+
# if $options[:color] is set, respects that; otherwise, applies color if the output device is a tty.
|
106
|
+
def self.color(name, *color_args)
|
107
|
+
define_method(name) do |arg|
|
108
|
+
if color?
|
109
|
+
color_args.inject(arg) do |result, color_arg|
|
110
|
+
Term::ANSIColor.send(color_arg, result)
|
111
|
+
end
|
112
|
+
else
|
113
|
+
arg
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
color :info, :intense_yellow
|
119
|
+
color :info_body, :yellow
|
120
|
+
color :protocol
|
121
|
+
|
122
|
+
color :request, :intense_cyan
|
123
|
+
color :request_verb, :bold
|
124
|
+
color :request_header
|
125
|
+
color :request_blankline, :intense_cyan, :bold
|
126
|
+
|
127
|
+
color :response, :intense_green
|
128
|
+
color :response_status, :bold, :green
|
129
|
+
color :response_header
|
130
|
+
color :response_blankline, :intense_green, :bold
|
131
|
+
|
132
|
+
def call(request_env)
|
133
|
+
@outdev.puts "#{info('*')} #{info_body("connect to #{request_env[:url].host} on port #{request_env[:url].port}")}"
|
134
|
+
@outdev.puts "#{info('*')} #{info_body("getting our SSL on")}" if request_env[:url].scheme=='https'
|
135
|
+
@outdev.puts "#{request('>')} #{request_verb(request_env[:method].to_s.upcase)} #{request_env[:url].path} #{protocol('HTTP/1.1' || 'or something - TODO')}"
|
136
|
+
request_env[:request_headers].each do |k, v|
|
137
|
+
@outdev.puts "#{request('>')} #{request_header(k)}#{request(':')} #{v}"
|
138
|
+
end
|
139
|
+
@outdev.puts "#{request_blankline('>')} "
|
140
|
+
request_body = color_body_by_content_type(request_env[:body], request_env[:request_headers]['Content-Type'])
|
141
|
+
(request_body || '').split("\n", -1).each do |line|
|
142
|
+
@outdev.puts "#{request('>')} #{line}"
|
143
|
+
end
|
144
|
+
@app.call(request_env).on_complete do |response_env|
|
145
|
+
@outdev.puts "#{response('<')} #{protocol('HTTP/1.1' || 'or something - TODO')} #{response_status(response_env[:status].to_s)}"
|
146
|
+
request_env[:response_headers].each do |k, v|
|
147
|
+
@outdev.puts "#{response('<')} #{response_header(k)}#{response(':')} #{v}"
|
148
|
+
end
|
149
|
+
@outdev.puts "#{response_blankline ('<')} "
|
150
|
+
response_body = color_body_by_content_type(response_env[:body], response_env[:response_headers]['Content-Type'])
|
151
|
+
(response_body || '').split("\n", -1).each do |line|
|
152
|
+
@outdev.puts "#{response('<')} #{line}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# whether to use color
|
158
|
+
def color?
|
159
|
+
$options[:color].nil? ? @outdev.tty? : $options[:color]
|
160
|
+
end
|
161
|
+
|
162
|
+
# a mapping for each registered CodeRay scanner to the Media Types which represent
|
163
|
+
# that language. extremely incomplete!
|
164
|
+
CodeRayForMediaTypes = {
|
165
|
+
:c => [],
|
166
|
+
:cpp => [],
|
167
|
+
:clojure => [],
|
168
|
+
:css => ['text/css', 'application/css-stylesheet'],
|
169
|
+
:delphi => [],
|
170
|
+
:diff => [],
|
171
|
+
:erb => [],
|
172
|
+
:groovy => [],
|
173
|
+
:haml => [],
|
174
|
+
:html => ['text/html'],
|
175
|
+
:java => [],
|
176
|
+
:java_script => ['application/javascript', 'text/javascript', 'application/x-javascript'],
|
177
|
+
:json => ['application/json', %r(\Aapplication/.*\+json\z)],
|
178
|
+
:php => [],
|
179
|
+
:python => ['text/x-python'],
|
180
|
+
:ruby => [],
|
181
|
+
:sql => [],
|
182
|
+
:xml => ['text/xml', 'application/xml', %r(\Aapplication/.*\+xml\z)],
|
183
|
+
:yaml => [],
|
184
|
+
}
|
185
|
+
|
186
|
+
# takes a body and a content type; returns the body, with coloring (ansi colors for terminals)
|
187
|
+
# possibly added, if it's a recognized content type and #color? is true
|
188
|
+
def color_body_by_content_type(body, content_type)
|
189
|
+
if body && color?
|
190
|
+
# kinda hacky way to get the media_type. faraday should supply this ...
|
191
|
+
require 'rack'
|
192
|
+
media_type = ::Rack::Request.new({'CONTENT_TYPE' => content_type}).media_type
|
193
|
+
coderay_scanner = CodeRayForMediaTypes.reject{|k,v| !v.any?{|type| type === media_type} }.keys.first
|
194
|
+
if coderay_scanner
|
195
|
+
require 'coderay'
|
196
|
+
if coderay_scanner == :json
|
197
|
+
body = begin
|
198
|
+
JSON.pretty_generate(JSON.parse(body))
|
199
|
+
rescue JSON::ParserError
|
200
|
+
body
|
201
|
+
end
|
202
|
+
end
|
203
|
+
body = CodeRay.scan(body, coderay_scanner).encode(:terminal)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
body
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# CONFIGURE THE FARADAY CONNECTION
|
211
|
+
faraday_options = {}
|
212
|
+
if $options[:no_ssl_verify]
|
213
|
+
faraday_options[:ssl] = {:verify => false}
|
214
|
+
end
|
215
|
+
connection = Faraday.new(faraday_options) do |builder|
|
216
|
+
builder.use MAuth::Faraday::MAuthClientUserAgent, "MAuth-Client CLI"
|
217
|
+
builder.use MAuth::Faraday::RequestSigner, :mauth_client => mauth_client
|
218
|
+
if $options[:authenticate_response]
|
219
|
+
builder.use MAuth::Faraday::ResponseAuthenticator, :mauth_client => mauth_client
|
220
|
+
end
|
221
|
+
builder.use $options[:verbose] ? FaradayCurlVOutputter : FaradayOutputter
|
222
|
+
builder.adapter Faraday.default_adapter
|
223
|
+
end
|
224
|
+
|
225
|
+
httpmethod, url, body = *ARGV
|
226
|
+
|
227
|
+
unless Faraday::Connection::METHODS.map{|m| m.to_s.downcase }.include?(httpmethod.downcase)
|
228
|
+
abort "Unrecognized HTTP method given: #{httpmethod}\n\n" + opt_parser.help
|
229
|
+
end
|
230
|
+
|
231
|
+
headers = {}
|
232
|
+
if $options[:content_type]
|
233
|
+
headers['Content-Type'] = $options[:content_type]
|
234
|
+
else
|
235
|
+
if body
|
236
|
+
# I'd rather not have a default content-type, but if none is set then the HTTP adapter sets this to
|
237
|
+
# application/x-www-form-urlencoded anyway. application/json is a better default for our purposes.
|
238
|
+
headers['Content-Type'] = 'application/json'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
if $options[:additional_headers]
|
243
|
+
$options[:additional_headers].each do |cur|
|
244
|
+
raise "Headers must be in the format of [key]:[value]" unless cur.include?(':')
|
245
|
+
key, throw_away ,value = cur.partition(':')
|
246
|
+
headers[key] = value
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# OH LOOK IT'S FINALLY ACTUALLY CONNECTING TO SOMETHING
|
251
|
+
|
252
|
+
begin
|
253
|
+
response = connection.run_request(httpmethod.downcase.to_sym, url, body, headers)
|
254
|
+
rescue MAuth::InauthenticError, MAuth::UnableToAuthenticateError => e
|
255
|
+
if $options[:color].nil? ? STDERR.tty? : $options[:color]
|
256
|
+
class_color = Term::ANSIColor.method(e.is_a?(MAuth::InauthenticError) ? :intense_red : :intense_yellow)
|
257
|
+
message_color = Term::ANSIColor.method(e.is_a?(MAuth::InauthenticError) ? :red : :yellow)
|
258
|
+
else
|
259
|
+
class_color = proc{|s| s }
|
260
|
+
message_color = proc{|s| s }
|
261
|
+
end
|
262
|
+
STDERR.puts(class_color.call(e.class.to_s))
|
263
|
+
STDERR.puts(message_color.call(e.message))
|
264
|
+
end
|
data/exe/mauth-proxy
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'mauth/proxy'
|
7
|
+
require 'rack'
|
8
|
+
|
9
|
+
headers = []
|
10
|
+
headers_index = ARGV.find_index('--header')
|
11
|
+
while(headers_index) do
|
12
|
+
headers << ARGV[headers_index + 1]
|
13
|
+
ARGV.delete_at(headers_index + 1)
|
14
|
+
ARGV.delete_at(headers_index)
|
15
|
+
headers_index = ARGV.find_index('--header')
|
16
|
+
end
|
17
|
+
|
18
|
+
authenticate_responses = !ARGV.delete('--no-authenticate')
|
19
|
+
browser_proxy = !(ARGV.delete('--browser_proxy').nil?)
|
20
|
+
|
21
|
+
target_uri = browser_proxy ? ARGV : ARGV.pop
|
22
|
+
|
23
|
+
if !target_uri || target_uri.empty?
|
24
|
+
abort("Usage: mauth-proxy [rack options] --browser_proxy [--no-authenticate] <target URI> <target URI> ...\n" +
|
25
|
+
"or: mauth-proxy [rack options] <target URI>")
|
26
|
+
end
|
27
|
+
|
28
|
+
rack_server_options = Rack::Server::Options.new.parse!(ARGV)
|
29
|
+
|
30
|
+
# for security, this rack server will only accept local connections, so override Host
|
31
|
+
# to 127.0.0.1 (from the default of 0.0.0.0)
|
32
|
+
#
|
33
|
+
# this means that the '-o' / '--host' option to Rack::Server::Options is ignored.
|
34
|
+
rack_server_options[:Host] = "127.0.0.1"
|
35
|
+
|
36
|
+
rack_server_options[:app] = MAuth::Proxy.new(target_uri, :authenticate_responses => authenticate_responses,
|
37
|
+
:browser_proxy => browser_proxy, :headers => headers)
|
38
|
+
|
39
|
+
mauth_proxy_server = Rack::Server.new(rack_server_options)
|
40
|
+
mauth_proxy_server.start
|