oauth2-nginx-auth-backend 0.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 34843ad4d62cf09d89d2263cd138ea003034dfed
4
+ data.tar.gz: b83686fa6849f02934e0f4bb5085f2d8cab4b777
5
+ SHA512:
6
+ metadata.gz: 9dbcfdc27299569cb7d7e498eee4c5be57c7e7157e49e49d2a9cbe578265738541bfc8503c1647845a709116363dc75200b0297e8a9a66ca5b71b944164a9596
7
+ data.tar.gz: e749170db36dbd8e26e5b8fa0456a97daa954c4e4ae0ef01d319577264f7408e5f917c23ca6332e5141b05b2408eb02bee1fbbb7778eca876873bd25c32ee725
@@ -0,0 +1,15 @@
1
+ ---
2
+ pipeline:
3
+
4
+ resolve:
5
+ image: alpine
6
+ commands:
7
+ - cat /etc/resolv.conf
8
+ when:
9
+ status: [ success, failure ]
10
+
11
+ docker:
12
+ image: plugins/docker
13
+ repo: docker-registry.devops.dance/${DRONE_REPO_NAME}
14
+ tags:
15
+ - ${DRONE_COMMIT:0:7}
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
@@ -0,0 +1,2 @@
1
+ Metrics/LineLength:
2
+ Max: 120
@@ -0,0 +1 @@
1
+ 2.4.1
@@ -0,0 +1,12 @@
1
+ FROM ruby:2.4
2
+
3
+ ENV HOME /opt/app
4
+ ENV RUBYLIB=$HOME/lib
5
+ WORKDIR $HOME
6
+
7
+ ADD . $HOME
8
+
9
+ RUN \
10
+ bundler
11
+
12
+ CMD ruby bin/ops_oauth2_server.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ops-oauth2.gemspec
4
+ gemspec
@@ -0,0 +1,59 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ oauth2-nginx-auth-backend (0.2.0)
5
+ httparty (~> 0.15)
6
+ sinatra (~> 2.0)
7
+ sinatra-contrib (~> 2.0)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.4.0)
13
+ backports (3.11.1)
14
+ httparty (0.16.1)
15
+ multi_xml (>= 0.5.2)
16
+ multi_json (1.13.1)
17
+ multi_xml (0.6.0)
18
+ mustermann (1.0.2)
19
+ parallel (1.12.1)
20
+ parser (2.5.0.5)
21
+ ast (~> 2.4.0)
22
+ powerpack (0.1.1)
23
+ rack (2.0.4)
24
+ rack-protection (2.0.1)
25
+ rack
26
+ rainbow (3.0.0)
27
+ rubocop (0.54.0)
28
+ parallel (~> 1.10)
29
+ parser (>= 2.5)
30
+ powerpack (~> 0.1)
31
+ rainbow (>= 2.2.2, < 4.0)
32
+ ruby-progressbar (~> 1.7)
33
+ unicode-display_width (~> 1.0, >= 1.0.1)
34
+ ruby-progressbar (1.9.0)
35
+ sinatra (2.0.1)
36
+ mustermann (~> 1.0)
37
+ rack (~> 2.0)
38
+ rack-protection (= 2.0.1)
39
+ tilt (~> 2.0)
40
+ sinatra-contrib (2.0.1)
41
+ backports (>= 2.0)
42
+ multi_json
43
+ mustermann (~> 1.0)
44
+ rack-protection (= 2.0.1)
45
+ sinatra (= 2.0.1)
46
+ tilt (>= 1.3, < 3)
47
+ tilt (2.0.8)
48
+ unicode-display_width (1.3.0)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ bundler (~> 1.14)
55
+ oauth2-nginx-auth-backend!
56
+ rubocop (~> 0.49)
57
+
58
+ BUNDLED WITH
59
+ 1.16.1
@@ -0,0 +1,57 @@
1
+ # Nginx Configuration
2
+
3
+ ### /etc/nginx/oauth2-auth.conf
4
+ ```
5
+ auth_request /oauth2/verify;
6
+ error_page 401 = https://auth.example.com/oauth2/sign_in;
7
+ auth_request_set $auth_cookie $upstream_http_set_cookie;
8
+ add_header Set-Cookie $auth_cookie;
9
+
10
+ ```
11
+
12
+ ### /etc/nginx/oauth2-location.conf
13
+ ```
14
+ location /oauth2/ {
15
+ proxy_method GET;
16
+ proxy_pass http://127.0.0.1:3000;
17
+ proxy_set_header Content-Length "";
18
+ proxy_set_header Host $host;
19
+ proxy_set_header X-Real-IP $remote_addr;
20
+ proxy_set_header X-Scheme $scheme;
21
+ proxy_set_header X-Auth-Request-Redirect $scheme://$server_name$request_uri;
22
+ }
23
+
24
+ ```
25
+
26
+ ### /etc/oauth2/oauth2.conf example
27
+ ```
28
+ {
29
+ "auth": {
30
+ "cookie_domain": ".devops.dance",
31
+ "cookie_name_permissions": "DDIntranetPermissions",
32
+ "cookie_name_redirect": "DDIntranetRedirect",
33
+ "cookie_name_signature": "DDIntranetSignature",
34
+ "cookie_ttl": 86400,
35
+ "default_redirect_page": "https://oauth.devops.dance/",
36
+ "oauth_shared_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
37
+ },
38
+ "google": {
39
+ "oauth_client_id": "XXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com",
40
+ "oauth_client_secret": "XXXXXXXXXXXXXXXXXXXXXXXX",
41
+ "oauth_redirect_url": "https://oauth.devops.dance/oauth2/google/authorize",
42
+ "oauth_server_url": "https://oauth.devops.dance/",
43
+ "whitelisted_domains": [
44
+ "smatly.com"
45
+ ],
46
+ "whitelisted_emails": []
47
+ },
48
+ "slack": {
49
+ "oauth_client_id": "XXXXXXXXXXXXXXXXXXXXXXXXX",
50
+ "oauth_client_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
51
+ "oauth_redirect_url": "https://oauth.devops.dance/oauth2/slack/authorize",
52
+ "whitelisted_domains": [
53
+ "devops-dance"
54
+ ]
55
+ }
56
+ }
57
+ ```
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sinatra'
4
+ require 'sinatra/cookies'
5
+ require 'ops/oauth2/google'
6
+ require 'ops/oauth2/slack'
7
+ require 'ops/oauth2/auth'
8
+
9
+ # Main HTTPServer class handling requests
10
+ class HTTPServer < Sinatra::Base
11
+ helpers Sinatra::Cookies
12
+
13
+ slack = Slack.new
14
+ google = Google.new
15
+
16
+ set :port, 3000
17
+ set :bind, '0.0.0.0'
18
+ set :cookie_options, domain: Auth.cookie_domain, secure: true, httponly: true
19
+ set :public_folder, 'static'
20
+ set :views, Proc.new { File.join(root, "..", "views") }
21
+ set :environment, :production
22
+
23
+ get '/oauth2/google/sign_in' do
24
+ redirect google.oauth_auth_redirect
25
+ end
26
+
27
+ get '/oauth2/google/authorize' do
28
+ return google.authorize(self)
29
+ end
30
+
31
+ get '/oauth2/slack/sign_in' do
32
+ redirect slack.oauth_auth_redirect
33
+ end
34
+
35
+ get '/oauth2/slack/authorize' do
36
+ return slack.authorize(self)
37
+ end
38
+
39
+ get '/oauth2/verify' do
40
+ Auth.authorized?(cookies, request)
41
+ end
42
+
43
+ get '/oauth2/sign_in' do
44
+ erb :index
45
+ end
46
+ end
47
+
48
+ HTTPServer.run!
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ops/oauth2/version'
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'json'
5
+ require 'openssl'
6
+
7
+ # Authorization
8
+ class Auth
9
+ def self.cookie_name_permissions
10
+ ENV['OAUTH_COOKIE_NAME_PERMISSIONS'] || configuration.dig('auth', 'cookie_name_permissions') || abort('Missing OAUTH_COOKIE_NAME_PERMISSIONS')
11
+ end
12
+
13
+ def self.cookie_name_signature
14
+ 'OKIntranetSignature'
15
+ ENV['OAUTH_COOKIE_NAME_SIGNATURE'] || configuration.dig('auth', 'cookie_name_signature') || abort('Missing OAUTH_COOKIE_NAME_SIGNATURE')
16
+ end
17
+
18
+ def self.cookie_name_redirect
19
+ ENV['OAUTH_COOKIE_NAME_REDIRECT'] || configuration.dig('auth', 'cookie_name_redirect') || abort('Missing OAUTH_COOKIE_NAME_REDIRECT')
20
+ end
21
+
22
+ def self.header_request_redirect_url
23
+ 'HTTP_X_AUTH_REQUEST_REDIRECT'
24
+ end
25
+
26
+ def self.environment
27
+ ENV['OAUTH_ENVIRONMENT'] || configuration.dig('auth', 'running_environment') || abort('Missing OAUTH_ENVIRONMENT')
28
+ end
29
+
30
+ def self.secret
31
+ ENV['OAUTH_SHARED_SECRET'] || configuration.dig('auth', 'oauth_shared_secret') || abort('Missing OAUTH_SHARED_SECRET')
32
+ end
33
+
34
+ def self.default_redirect_page
35
+ ENV['DEFAULT_REDIRECT_PAGE'] || configuration.dig('auth', 'default_redirect_page') || abort('Missing DEFAULT_REDIRECT_PAGE')
36
+ end
37
+
38
+ def self.cookie_domain
39
+ ENV['OAUTH_COOKIE_DOMAIN'] || self.configuration.dig('auth', 'cookie_domain') || abort('Missing OAUTH_COOKIE_DOMAIN')
40
+ end
41
+
42
+ def self.cookie_ttl
43
+ return ENV['OAUTH_COOKIE_TTL'].to_i if ENV['OAUTH_COOKIE_TTL']
44
+ configuration.dig('auth', 'cookie_ttl').to_i || abort('Missing OAUTH_COOKIE_TTL')
45
+ end
46
+
47
+ def self.sign(data)
48
+ digest = OpenSSL::Digest.new('sha256')
49
+ Base64.encode64(OpenSSL::HMAC.digest(digest, secret, data))
50
+ end
51
+
52
+ def self.trusted?(cookies, request)
53
+ cookies[cookie_name_signature] == sign([cookies[cookie_name_permissions], request.user_agent].join)
54
+ end
55
+
56
+ def self.configuration_file
57
+ '/etc/oauth2/oauth2.conf'
58
+ end
59
+
60
+ def self.configuration
61
+ @configuration ||= JSON.parse(File.read(configuration_file))
62
+ rescue
63
+ abort("Missing or invalid #{self.configuration_file}")
64
+ end
65
+
66
+ def self.authorize(info, request)
67
+ cookies = {}
68
+ cookies[cookie_name_permissions] = Base64.encode64(info.to_json)
69
+ cookies[cookie_name_signature] = sign([Base64.encode64(info.to_json), request.user_agent].join)
70
+ cookies
71
+ end
72
+
73
+ def self.go_to_auth(cookies, request)
74
+ cookies[cookie_name_redirect] = request.env[header_request_redirect_url]
75
+ 401
76
+ end
77
+
78
+ def self.untrusted(cookies, request)
79
+ cookies.delete(cookie_name_signature)
80
+ cookies.delete(cookie_name_permissions)
81
+ go_to_auth(cookies, request)
82
+ end
83
+
84
+ def self.authorized?(cookies, request)
85
+ return go_to_auth(cookies, request) unless cookies.key?(cookie_name_permissions)
86
+ return go_to_auth(cookies, request) unless cookies.key?(cookie_name_signature)
87
+ return untrusted(cookies, request) unless trusted?(cookies, request)
88
+ 200
89
+ end
90
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+ require 'httparty'
5
+ require 'json'
6
+ require 'ops/oauth2/auth'
7
+
8
+ # Basic support of google oauth2
9
+ class Google
10
+ def oauth_client_secret
11
+ ENV['GOOGLE_OAUTH_CLIENT_SECRET'] || configuration.dig('google', 'oauth_client_secret') || abort('Missing GOOGLE_OAUTH_CLIENT_SECRET')
12
+ end
13
+
14
+ def oauth_client_id
15
+ ENV['GOOGLE_OAUTH_CLIENT_ID'] || configuration.dig('google', 'oauth_client_id') || abort('Missing GOOGLE_OAUTH_CLIENT_ID')
16
+ end
17
+
18
+ def redirect_url
19
+ ENV['GOOGLE_OAUTH_REDIRECT_URL'] || configuration.dig('google', 'oauth_redirect_url') || abort('Missing GOOGLE_OAUTH_REDIRECT_URL')
20
+ end
21
+
22
+ def state_url
23
+ ENV['OAUTH_SERVER_URL'] || configuration.dig('google', 'oauth_server_url') || abort('Missing OAUTH_SERVER_URL')
24
+ end
25
+
26
+ def google_whitelisted_domains
27
+ ENV['GOOGLE_WHITELISTED_DOMAINS'] || configuration.dig('google', 'whitelisted_domains') || abort('Missing GOOGLE_WHITELISTED_DOMAINS')
28
+ end
29
+
30
+ def google_whitelisted_emails
31
+ ENV['GOOGLE_WHITELISTED_EMAILS'] || configuration.dig('google', 'whitelisted_emails') || abort('Missing GOOGLE_WHITELISTED_EMAILS')
32
+ end
33
+
34
+ def oauth_auth_url
35
+ 'https://accounts.google.com/o/oauth2/auth'
36
+ end
37
+
38
+ def oauth_token_url
39
+ 'https://accounts.google.com/o/oauth2/token'
40
+ end
41
+
42
+ def oauth_userinfo_url
43
+ 'https://www.googleapis.com/oauth2/v2/userinfo'
44
+ end
45
+
46
+ def configuration_file
47
+ '/etc/oauth2/oauth2.conf'
48
+ end
49
+
50
+ def configuration
51
+ @configuration ||= JSON.parse(File.read(configuration_file))
52
+ rescue
53
+ abort("Missing or invalid #{configuration_file}")
54
+ end
55
+
56
+ def oauth_auth_url_params
57
+ [
58
+ "client_id=#{oauth_client_id}",
59
+ 'scope=email',
60
+ 'response_type=code',
61
+ "redirect_uri=#{CGI.escape(redirect_url)}",
62
+ "state=#{CGI.escape(state_url)}",
63
+ 'login_hint='
64
+ ].join('&')
65
+ end
66
+
67
+ def oauth_auth_redirect
68
+ [
69
+ oauth_auth_url,
70
+ '?',
71
+ oauth_auth_url_params
72
+ ].join
73
+ end
74
+
75
+ def permitted?(user_info)
76
+ email = user_info.dig('email')
77
+ return false unless email
78
+ _, domain = email.split('@')
79
+ return true if google_whitelisted_emails.include? email
80
+ return true if google_whitelisted_domains.include? domain
81
+ false
82
+ rescue
83
+ false
84
+ end
85
+
86
+ def user_info(authorization)
87
+ headers = {
88
+ 'Authorization' => "Bearer #{authorization}"
89
+ }
90
+ HTTParty.get(oauth_userinfo_url, headers: headers)
91
+ end
92
+
93
+ def access_token(params)
94
+ response = verify(params[:code])
95
+ response.dig('access_token')
96
+ end
97
+
98
+ def authorize(s)
99
+ if s.params.key? 'code'
100
+ # Make sure we got an access token, otherwise redirect to auth page
101
+ at = access_token(s.params)
102
+ return Auth.go_to_auth(s.cookies, s.request) unless at
103
+
104
+ # Get google user info and make sure it's permitted to get auth.
105
+ ui = user_info(at)
106
+ return 403 unless permitted?(ui)
107
+
108
+ # Naive sanity check of google response
109
+ return Auth.go_to_auth(s.cookies, s.request) unless ui.key? 'email'
110
+
111
+ # Now we're safe to authorize => set cookies
112
+ Auth.authorize(ui, s.request).each do |cookie, value|
113
+ s.cookies.set(cookie, value: value, expires: Time.now + Auth.cookie_ttl)
114
+ end
115
+
116
+ # Redirect user to the original page if redirect cookie present.
117
+ if s.cookies.key?(Auth.cookie_name_redirect)
118
+ redirect_url = s.cookies[Auth.cookie_name_redirect]
119
+ s.cookies.delete(Auth.cookie_name_redirect)
120
+ s.redirect redirect_url
121
+ end
122
+
123
+ # Redirect to default page if you don't have redirect cookie
124
+ s.redirect Auth.default_redirect_page
125
+ else
126
+ Auth.go_to_auth(s.cookies, request)
127
+ end
128
+ end
129
+
130
+ def verify(code)
131
+ options = {
132
+ body: {
133
+ client_id: oauth_client_id,
134
+ client_secret: oauth_client_secret,
135
+ code: code,
136
+ redirect_uri: redirect_url,
137
+ grant_type: 'authorization_code'
138
+ }
139
+ }
140
+ HTTParty.post(oauth_token_url, options)
141
+ end
142
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+ require 'httparty'
5
+ require 'json'
6
+
7
+ # Basic support of slack oauth2
8
+ class Slack
9
+ def oauth_client_secret
10
+ ENV['SLACK_OAUTH_CLIENT_SECRET'] || configuration.dig('slack', 'oauth_client_secret') || abort('Missing SLACK_OAUTH_CLIENT_SECRET')
11
+ end
12
+
13
+ def oauth_client_id
14
+ ENV['SLACK_OAUTH_CLIENT_ID'] || configuration.dig('slack', 'oauth_client_id') || abort('Missing SLACK_OAUTH_CLIENT_ID')
15
+ end
16
+
17
+ def redirect_url
18
+ ENV['SLACK_OAUTH_REDIRECT_URL'] || configuration.dig('slack', 'oauth_redirect_url') || abort('Missing SLACK_OAUTH_REDIRECT_URL')
19
+ end
20
+
21
+ def whitelisted_domains
22
+ return ENV['SLACK_WHITELISTED_DOMAINS'].split(',') if ENV['SLACK_WHITELISTED_DOMAINS']
23
+ configuration.dig('slack', 'whitelisted_domains') || abort('Missing SLACK_WHITELISTED_DOMAINS')
24
+ end
25
+
26
+ def oauth_auth_url
27
+ 'https://slack.com/oauth/authorize'
28
+ end
29
+
30
+ def oauth_token_url
31
+ 'https://slack.com/api/oauth.access'
32
+ end
33
+
34
+ def oauth_scopes
35
+ 'identity.basic,identity.team'
36
+ end
37
+
38
+ def configuration_file
39
+ '/etc/oauth2/oauth2.conf'
40
+ end
41
+
42
+ def configuration
43
+ @configuration ||= JSON.parse(File.read(configuration_file))
44
+ rescue
45
+ abort("Missing or invalid #{configuration_file}")
46
+ end
47
+
48
+ def oauth_auth_url_params
49
+ [
50
+ "client_id=#{oauth_client_id}",
51
+ "scope=#{oauth_scopes}",
52
+ "redirect_uri=#{CGI.escape(redirect_url)}"
53
+ ].join('&')
54
+ end
55
+
56
+ def oauth_auth_redirect
57
+ [
58
+ oauth_auth_url,
59
+ '?',
60
+ oauth_auth_url_params
61
+ ].join
62
+ end
63
+
64
+ def user_info(response)
65
+ payload = JSON.parse(response)
66
+ {
67
+ 'user': payload['user']
68
+ }
69
+ rescue
70
+ nil
71
+ end
72
+
73
+ def domain(response)
74
+ payload = JSON.parse(response)
75
+ payload.dig('team', 'domain')
76
+ rescue
77
+ nil
78
+ end
79
+
80
+ def authorize(s)
81
+ response = verify(s.params)
82
+ return 403 unless response.dig('ok')
83
+
84
+ # get slack response domain and authorize if included in whitelisted
85
+ return 403 unless whitelisted_domains.include? domain(response.body)
86
+
87
+ # make sure we get a proper user info structure
88
+ ui = user_info(response.body)
89
+ return 403 unless ui
90
+
91
+ # build and authorize cookies
92
+ Auth.authorize(ui, s.request).each do |cookie, value|
93
+ s.cookies.set(cookie, value: value, expires: Time.now + Auth.cookie_ttl)
94
+ end
95
+
96
+ # redirect user to a proper place if needed
97
+ if s.cookies.key?(Auth.cookie_name_redirect)
98
+ redirect_url = s.cookies[Auth.cookie_name_redirect]
99
+ s.cookies.delete(Auth.cookie_name_redirect)
100
+ s.redirect redirect_url
101
+ end
102
+
103
+ # redirect to a default page
104
+ s.redirect Auth.default_redirect_page
105
+ end
106
+
107
+ def verify(params)
108
+ return { 'ok': false } unless params.dig('code')
109
+ options = {
110
+ body: {
111
+ client_id: oauth_client_id,
112
+ client_secret: oauth_client_secret,
113
+ code: params.dig('code'),
114
+ redirect_uri: redirect_url
115
+ }
116
+ }
117
+ HTTParty.post(oauth_token_url, options)
118
+ end
119
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ops
4
+ module Oauth2
5
+ VERSION = '0.2.0'
6
+ end
7
+ 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 'ops/oauth2/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'oauth2-nginx-auth-backend'
8
+ spec.version = Ops::Oauth2::VERSION
9
+ spec.authors = ['Bartek Jarocki']
10
+ spec.email = ['bartek@smatly.com']
11
+
12
+ spec.summary = 'oauth2 nginx auth_request backend'
13
+ spec.homepage = 'https://github.com/bjarocki/oauth2-nginx-auth-backend'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = 'bin'
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.14'
23
+ spec.add_development_dependency 'rubocop', '~> 0.49'
24
+
25
+ spec.add_runtime_dependency 'httparty', '~> 0.15'
26
+ spec.add_runtime_dependency 'sinatra', '~> 2.0'
27
+ spec.add_runtime_dependency 'sinatra-contrib', '~> 2.0'
28
+ end
@@ -0,0 +1,81 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta name="generator" content=
5
+ "HTML Tidy for HTML5 for Linux version 5.4.0">
6
+ <link rel="stylesheet" href=
7
+ "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.5.1/css/bulma.min.css">
8
+
9
+ <style>
10
+ .loginBtn {
11
+ box-sizing: border-box;
12
+ position: relative;
13
+ width: 100%;
14
+ margin: 18px 0px 0px 0px;
15
+ padding: 0 15px 0 52px;
16
+ text-align: left;
17
+ line-height: 42px;
18
+ white-space: nowrap;
19
+ border-radius: 0.2em;
20
+ background-color: white;
21
+ font-size: 1.3em;
22
+ color: #333;
23
+ border: 1px solid rgba(10,10,10,0.1);
24
+ }
25
+ .loginBtn:before {
26
+ content: "";
27
+ box-sizing: border-box;
28
+ position: absolute;
29
+ top: 2px;
30
+ left: 2px;
31
+ width: 38px;
32
+ height: 38px;
33
+ }
34
+ .loginBtn:focus {
35
+ outline: none;
36
+ }
37
+ .loginBtn:active {
38
+ box-shadow: inset 0 0 0 32px rgba(0,0,0,0.1);
39
+ }
40
+ .loginBtn--slack {
41
+ }
42
+ .loginBtn--slack:before {
43
+ border-right: rgba(0,0,0,0.1) 1px solid;
44
+ background: url('images/slack-large.png') 0px 0px no-repeat;
45
+ }
46
+ .loginBtn--slack:hover,
47
+ .loginBtn--slack:focus {
48
+ background: #78d4b6
49
+ }
50
+ .loginBtn--google {
51
+ background: #4285f4;
52
+ color: #fff;
53
+ }
54
+ .loginBtn--google:before {
55
+ border-right: rgba(0,0,0,0.1) 1px solid;
56
+ background: url('images/google-large.png') 0px 0px no-repeat;
57
+ }
58
+ .loginBtn--google:hover,
59
+ .loginBtn--google:focus {
60
+ background: #E74B37;
61
+ }
62
+ </style>
63
+ <title></title>
64
+ </head>
65
+ <body>
66
+ <section class="section">
67
+ <div class="columns is-mobile is-centered">
68
+ <div class="column is-one-quarter is-narrow">
69
+ <div class="box">
70
+ <p class="is-centered"></p>
71
+ <figure class="image is-256x256">
72
+ <img src="images/devops-logo.png">
73
+ </figure>
74
+ <p><button class="loginBtn loginBtn--slack" onclick="location.href='/oauth2/slack/sign_in'">Login with Slack</button></p>
75
+ <p><button class="loginBtn loginBtn--google" onclick="location.href='/oauth2/google/sign_in'">Login with Google</button></p>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </section>
80
+ </body>
81
+ </html>
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oauth2-nginx-auth-backend
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Bartek Jarocki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-24 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.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.49'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.49'
41
+ - !ruby/object:Gem::Dependency
42
+ name: httparty
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.15'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.15'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sinatra
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sinatra-contrib
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ description:
84
+ email:
85
+ - bartek@smatly.com
86
+ executables:
87
+ - ops_oauth2_server.rb
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".drone.yml"
92
+ - ".gitignore"
93
+ - ".rubocop.yml"
94
+ - ".ruby-version"
95
+ - Dockerfile
96
+ - Gemfile
97
+ - Gemfile.lock
98
+ - README.md
99
+ - bin/ops_oauth2_server.rb
100
+ - lib/ops/oauth2.rb
101
+ - lib/ops/oauth2/auth.rb
102
+ - lib/ops/oauth2/google.rb
103
+ - lib/ops/oauth2/slack.rb
104
+ - lib/ops/oauth2/version.rb
105
+ - oauth2-nginx-auth-backend.gemspec
106
+ - static/oauth2/images/devops-logo.png
107
+ - static/oauth2/images/google-large.png
108
+ - static/oauth2/images/slack-large.png
109
+ - views/index.erb
110
+ homepage: https://github.com/bjarocki/oauth2-nginx-auth-backend
111
+ licenses: []
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.6.14
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: oauth2 nginx auth_request backend
133
+ test_files: []