linkedin_sign_in 0.3
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 +13 -0
- data/.travis.yml +18 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +155 -0
- data/MIT-LICENSE +20 -0
- data/README.md +154 -0
- data/Rakefile +40 -0
- data/SECURITY.md +3 -0
- data/app/controllers/linkedin_sign_in/authorizations_controller.rb +17 -0
- data/app/controllers/linkedin_sign_in/base_controller.rb +15 -0
- data/app/controllers/linkedin_sign_in/callbacks_controller.rb +27 -0
- data/app/helpers/linkedin_sign_in/button_helper.rb +7 -0
- data/bin/rails +16 -0
- data/config/routes.rb +4 -0
- data/lib/linkedin-id-token.rb +190 -0
- data/lib/linkedin_sign_in/engine.rb +32 -0
- data/lib/linkedin_sign_in/identity.rb +55 -0
- data/lib/linkedin_sign_in/redirect_protector.rb +25 -0
- data/lib/linkedin_sign_in.rb +10 -0
- data/linkedin_sign_in.gemspec +21 -0
- data/test/certificate.pem +19 -0
- data/test/controllers/authorizations_controller_test.rb +26 -0
- data/test/controllers/callbacks_controller_test.rb +36 -0
- data/test/dummy/.ruby-version +1 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/javascripts/cable.js +13 -0
- data/test/dummy/app/assets/javascripts/channels/.keep +0 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/channels/application_cable/channel.rb +4 -0
- data/test/dummy/app/channels/application_cable/connection.rb +4 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +15 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +36 -0
- data/test/dummy/bin/update +31 -0
- data/test/dummy/bin/yarn +11 -0
- data/test/dummy/config/application.rb +20 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +32 -0
- data/test/dummy/config/environments/production.rb +57 -0
- data/test/dummy/config/environments/test.rb +33 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/content_security_policy.rb +25 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/linkedin_sign_in.rb +4 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +34 -0
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/config/storage.yml +34 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/package.json +5 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/helpers/button_helper_test.rb +36 -0
- data/test/key.pem +27 -0
- data/test/models/identity_test.rb +48 -0
- data/test/models/redirect_protector_test.rb +34 -0
- data/test/test_helper.rb +28 -0
- metadata +267 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ad7912381b74e7f64e9bae51e0a684b300b34e2f4c41c85744cb610ff17607cc
|
4
|
+
data.tar.gz: 244c9cff9027b336a4d6bfbdd2028bd5673c1b9f1dc401d7781cdbae5e394a97
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 721a1b383a91a13737ed9ab1e01c4b9c655a1482cc61cd740ec6391004ad7021b6787a24b640a19a361cc4e73265af08062e04f60899389dc3e5b01d3cc921b9
|
7
|
+
data.tar.gz: 71c4e31c993787c14cd7e8ddcd2f1c27c5118e02226527adb5ef4a6a6355416768fa0ae9dccef47f49e247acd0de56ffbe867082b805b95253ba619c0fdc1b4c
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
cache: bundler
|
4
|
+
|
5
|
+
# Bundler/RubyGems incompat on Ruby 2.5.0
|
6
|
+
before_install: gem install bundler
|
7
|
+
|
8
|
+
rvm:
|
9
|
+
- 2.2
|
10
|
+
- 2.3
|
11
|
+
- 2.4
|
12
|
+
- 2.5
|
13
|
+
- ruby-head
|
14
|
+
|
15
|
+
matrix:
|
16
|
+
allow_failures:
|
17
|
+
- rvm: ruby-head
|
18
|
+
fast_finish: true
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
linkedin_sign_in (0.3)
|
5
|
+
oauth2 (>= 1.4.0)
|
6
|
+
rails (>= 5.2.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actioncable (5.2.1)
|
12
|
+
actionpack (= 5.2.1)
|
13
|
+
nio4r (~> 2.0)
|
14
|
+
websocket-driver (>= 0.6.1)
|
15
|
+
actionmailer (5.2.1)
|
16
|
+
actionpack (= 5.2.1)
|
17
|
+
actionview (= 5.2.1)
|
18
|
+
activejob (= 5.2.1)
|
19
|
+
mail (~> 2.5, >= 2.5.4)
|
20
|
+
rails-dom-testing (~> 2.0)
|
21
|
+
actionpack (5.2.1)
|
22
|
+
actionview (= 5.2.1)
|
23
|
+
activesupport (= 5.2.1)
|
24
|
+
rack (~> 2.0)
|
25
|
+
rack-test (>= 0.6.3)
|
26
|
+
rails-dom-testing (~> 2.0)
|
27
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
28
|
+
actionview (5.2.1)
|
29
|
+
activesupport (= 5.2.1)
|
30
|
+
builder (~> 3.1)
|
31
|
+
erubi (~> 1.4)
|
32
|
+
rails-dom-testing (~> 2.0)
|
33
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
34
|
+
activejob (5.2.1)
|
35
|
+
activesupport (= 5.2.1)
|
36
|
+
globalid (>= 0.3.6)
|
37
|
+
activemodel (5.2.1)
|
38
|
+
activesupport (= 5.2.1)
|
39
|
+
activerecord (5.2.1)
|
40
|
+
activemodel (= 5.2.1)
|
41
|
+
activesupport (= 5.2.1)
|
42
|
+
arel (>= 9.0)
|
43
|
+
activestorage (5.2.1)
|
44
|
+
actionpack (= 5.2.1)
|
45
|
+
activerecord (= 5.2.1)
|
46
|
+
marcel (~> 0.3.1)
|
47
|
+
activesupport (5.2.1)
|
48
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
49
|
+
i18n (>= 0.7, < 2)
|
50
|
+
minitest (~> 5.1)
|
51
|
+
tzinfo (~> 1.1)
|
52
|
+
addressable (2.5.2)
|
53
|
+
public_suffix (>= 2.0.2, < 4.0)
|
54
|
+
arel (9.0.0)
|
55
|
+
builder (3.2.3)
|
56
|
+
byebug (10.0.2)
|
57
|
+
concurrent-ruby (1.0.5)
|
58
|
+
crack (0.4.3)
|
59
|
+
safe_yaml (~> 1.0.0)
|
60
|
+
crass (1.0.4)
|
61
|
+
erubi (1.7.1)
|
62
|
+
faraday (0.15.3)
|
63
|
+
multipart-post (>= 1.2, < 3)
|
64
|
+
globalid (0.4.1)
|
65
|
+
activesupport (>= 4.2.0)
|
66
|
+
hashdiff (0.3.7)
|
67
|
+
i18n (1.1.1)
|
68
|
+
concurrent-ruby (~> 1.0)
|
69
|
+
jwt (2.1.0)
|
70
|
+
loofah (2.2.3)
|
71
|
+
crass (~> 1.0.2)
|
72
|
+
nokogiri (>= 1.5.9)
|
73
|
+
mail (2.7.1)
|
74
|
+
mini_mime (>= 0.1.1)
|
75
|
+
marcel (0.3.3)
|
76
|
+
mimemagic (~> 0.3.2)
|
77
|
+
method_source (0.9.1)
|
78
|
+
mimemagic (0.3.2)
|
79
|
+
mini_mime (1.0.1)
|
80
|
+
mini_portile2 (2.3.0)
|
81
|
+
minitest (5.11.3)
|
82
|
+
multi_json (1.13.1)
|
83
|
+
multi_xml (0.6.0)
|
84
|
+
multipart-post (2.0.0)
|
85
|
+
nio4r (2.3.1)
|
86
|
+
nokogiri (1.8.5)
|
87
|
+
mini_portile2 (~> 2.3.0)
|
88
|
+
oauth2 (1.4.1)
|
89
|
+
faraday (>= 0.8, < 0.16.0)
|
90
|
+
jwt (>= 1.0, < 3.0)
|
91
|
+
multi_json (~> 1.3)
|
92
|
+
multi_xml (~> 0.5)
|
93
|
+
rack (>= 1.2, < 3)
|
94
|
+
public_suffix (3.0.3)
|
95
|
+
rack (2.0.5)
|
96
|
+
rack-test (1.1.0)
|
97
|
+
rack (>= 1.0, < 3)
|
98
|
+
rails (5.2.1)
|
99
|
+
actioncable (= 5.2.1)
|
100
|
+
actionmailer (= 5.2.1)
|
101
|
+
actionpack (= 5.2.1)
|
102
|
+
actionview (= 5.2.1)
|
103
|
+
activejob (= 5.2.1)
|
104
|
+
activemodel (= 5.2.1)
|
105
|
+
activerecord (= 5.2.1)
|
106
|
+
activestorage (= 5.2.1)
|
107
|
+
activesupport (= 5.2.1)
|
108
|
+
bundler (>= 1.3.0)
|
109
|
+
railties (= 5.2.1)
|
110
|
+
sprockets-rails (>= 2.0.0)
|
111
|
+
rails-dom-testing (2.0.3)
|
112
|
+
activesupport (>= 4.2.0)
|
113
|
+
nokogiri (>= 1.6)
|
114
|
+
rails-html-sanitizer (1.0.4)
|
115
|
+
loofah (~> 2.2, >= 2.2.2)
|
116
|
+
railties (5.2.1)
|
117
|
+
actionpack (= 5.2.1)
|
118
|
+
activesupport (= 5.2.1)
|
119
|
+
method_source
|
120
|
+
rake (>= 0.8.7)
|
121
|
+
thor (>= 0.19.0, < 2.0)
|
122
|
+
rake (12.3.1)
|
123
|
+
safe_yaml (1.0.4)
|
124
|
+
sprockets (3.7.2)
|
125
|
+
concurrent-ruby (~> 1.0)
|
126
|
+
rack (> 1, < 3)
|
127
|
+
sprockets-rails (3.2.1)
|
128
|
+
actionpack (>= 4.0)
|
129
|
+
activesupport (>= 4.0)
|
130
|
+
sprockets (>= 3.0.0)
|
131
|
+
thor (0.20.0)
|
132
|
+
thread_safe (0.3.6)
|
133
|
+
tzinfo (1.2.5)
|
134
|
+
thread_safe (~> 0.1)
|
135
|
+
webmock (3.4.2)
|
136
|
+
addressable (>= 2.3.6)
|
137
|
+
crack (>= 0.3.2)
|
138
|
+
hashdiff
|
139
|
+
websocket-driver (0.7.0)
|
140
|
+
websocket-extensions (>= 0.1.0)
|
141
|
+
websocket-extensions (0.1.3)
|
142
|
+
|
143
|
+
PLATFORMS
|
144
|
+
ruby
|
145
|
+
|
146
|
+
DEPENDENCIES
|
147
|
+
bundler (~> 1.15)
|
148
|
+
byebug
|
149
|
+
jwt (>= 1.5.6)
|
150
|
+
linkedin_sign_in!
|
151
|
+
rake
|
152
|
+
webmock (>= 3.4.2)
|
153
|
+
|
154
|
+
BUNDLED WITH
|
155
|
+
1.16.4
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2018 Vincent Robert
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
This gem is shamlessly based on [Google SignIn by Basecamp](https://github.com/basecamp/google_sign_in).
|
2
|
+
|
3
|
+
# Linkedin Sign-In for Rails
|
4
|
+
|
5
|
+
This gem allows you to add Linkedin sign-in to your Rails app. You can let users sign up for and sign in to your service
|
6
|
+
with their Linkedin accounts.
|
7
|
+
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add `linkedin_sign_in` to your Rails app’s Gemfile and run `bundle install`:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'linkedin_sign_in'
|
15
|
+
```
|
16
|
+
|
17
|
+
Linkedin Sign-In for Rails requires Rails 5.2 or newer.
|
18
|
+
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
First, set up an OAuth 2.0 Client ID in the Linkedin API Console:
|
23
|
+
|
24
|
+
1. Go to the [Developer Portal](https://www.linkedin.com/developer/apps).
|
25
|
+
|
26
|
+
2. Create an application.
|
27
|
+
|
28
|
+
3. Submit your application information.
|
29
|
+
|
30
|
+
4. You are presented with a client ID and client secret. Save these.
|
31
|
+
|
32
|
+
5. This gem adds a single OAuth callback to your app at `/linkedin_sign_in/callback`. Under **Authorized Redirect URLs**,
|
33
|
+
add that callback for your application’s domain: for example, `https://example.com/linkedin_sign_in/callback`.
|
34
|
+
|
35
|
+
To use Linkedin sign-in in development, you’ll need to add another redirect URI for your local environment, like
|
36
|
+
`http://localhost:3000/linkedin_sign_in/callback`. For security reasons, we recommend using a separate
|
37
|
+
client ID for local development. Repeat these instructions to set up a new client ID for development.
|
38
|
+
|
39
|
+
6. Click the button labeled Update.
|
40
|
+
|
41
|
+
With your client ID set up, configure your Rails application to use it. Run `bin/rails credentials:edit` to edit your
|
42
|
+
app’s [encrypted credentials](https://guides.rubyonrails.org/security.html#custom-credentials) and add the following:
|
43
|
+
|
44
|
+
```yaml
|
45
|
+
linkedin_sign_in:
|
46
|
+
client_id: [Your client ID here]
|
47
|
+
client_secret: [Your client secret here]
|
48
|
+
```
|
49
|
+
|
50
|
+
You’re all set to use Linkedin sign-in now. The gem automatically uses the client ID and client secret in your credentials.
|
51
|
+
|
52
|
+
Alternatively, you can provide the client ID and client secret using ENV variables. Add a new initializer that sets
|
53
|
+
`config.linkedin_sign_in.client_id` and `config.linkedin_sign_in.client_secret`:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# config/initializers/linkedin_sign_in.rb
|
57
|
+
Rails.application.configure do
|
58
|
+
config.linkedin_sign_in.client_id = ENV['linkedin_sign_in_client_id']
|
59
|
+
config.linkedin_sign_in.client_secret = ENV['linkedin_sign_in_client_secret']
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
**⚠️ Important:** Take care to protect your client secret from disclosure to third parties.
|
64
|
+
|
65
|
+
|
66
|
+
## Usage
|
67
|
+
|
68
|
+
This gem provides a `linkedin_sign_in_button` helper. It generates a button which initiates Linkedin sign-in:
|
69
|
+
|
70
|
+
```erb
|
71
|
+
<%= linkedin_sign_in_button 'Sign in with my Linkedin account', proceed_to: create_login_url %>
|
72
|
+
|
73
|
+
<%= linkedin_sign_in_button image_tag('linkedin_logo.png', alt: 'Linkedin'), proceed_to: create_login_url %>
|
74
|
+
|
75
|
+
<%= linkedin_sign_in_button proceed_to: create_login_url do %>
|
76
|
+
Sign in with my <%= image_tag('linkedin_logo.png', alt: 'Linkedin') %> account
|
77
|
+
<% end %>
|
78
|
+
```
|
79
|
+
|
80
|
+
The `proceed_to` argument is required. After authenticating with Linkedin, the gem redirects to `proceed_to`, providing
|
81
|
+
a Linkedin ID token in `flash[:linkedin_sign_in_token]`. Your application decides what to do with it:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# config/routes.rb
|
85
|
+
Rails.application.routes.draw do
|
86
|
+
# ...
|
87
|
+
get 'login', to: 'logins#new'
|
88
|
+
get 'login/create', to: 'logins#create', as: :create_login
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
# app/controllers/logins_controller.rb
|
94
|
+
class LoginsController < ApplicationController
|
95
|
+
def new
|
96
|
+
end
|
97
|
+
|
98
|
+
def create
|
99
|
+
if user = authenticate_with_linkedin
|
100
|
+
cookies.signed[:user_id] = user.id
|
101
|
+
redirect_to user
|
102
|
+
else
|
103
|
+
redirect_to new_session_url, alert: 'authentication_failed'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def authenticate_with_linkedin
|
109
|
+
if flash[:linkedin_sign_in_token].present?
|
110
|
+
User.find_by linkedin_id: LinkedinSignIn::Identity.new(flash[:linkedin_sign_in_token]).user_id
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
(The above example assumes the user has already signed up for your service and that you’re storing their Linkedin user ID
|
117
|
+
in the `User#linkedin_id` attribute.)
|
118
|
+
|
119
|
+
For security reasons, the `proceed_to` URL you provide to `linkedin_sign_in_button` is required to reside on the same
|
120
|
+
origin as your application. This means it must have the same protocol, host, and port as the page where
|
121
|
+
`linkedin_sign_in_button` is used. We enforce this before redirecting to the `proceed_to` URL to guard against
|
122
|
+
[open redirects](https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet).
|
123
|
+
|
124
|
+
### `LinkedinSignIn::Identity`
|
125
|
+
|
126
|
+
The `LinkedinSignIn::Identity` class decodes and verifies the integrity of a Linkedin ID token. It exposes the profile
|
127
|
+
information contained in the token via the following instance methods:
|
128
|
+
|
129
|
+
* `name`
|
130
|
+
|
131
|
+
* `email_address`
|
132
|
+
|
133
|
+
* `user_id`: A string that uniquely identifies a single Linkedin user. Use this, not `email_address`, to associate a
|
134
|
+
Linkedin user with an application user. A Linkedin user’s email address may change, but their `user_id` will remain constant.
|
135
|
+
|
136
|
+
* `email_verified?`
|
137
|
+
|
138
|
+
* `avatar_url`
|
139
|
+
|
140
|
+
* `locale`
|
141
|
+
|
142
|
+
* `hosted_domain`: The user’s hosted G Suite domain, provided only if they belong to a G Suite.
|
143
|
+
|
144
|
+
|
145
|
+
## Security
|
146
|
+
|
147
|
+
For information on our security response procedure, see [SECURITY.md](SECURITY.md).
|
148
|
+
|
149
|
+
|
150
|
+
## License
|
151
|
+
|
152
|
+
Linkedin Sign-In for Rails is released under the [MIT License](https://opensource.org/licenses/MIT).
|
153
|
+
|
154
|
+
Linkedin is a registered trademark of Linkedin LLC. This project is not operated by or in any way affiliated with Linkedin LLC.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rake/testtask"
|
4
|
+
|
5
|
+
Rake::TestTask.new do |test|
|
6
|
+
test.libs << "test"
|
7
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
8
|
+
test.warning = false
|
9
|
+
end
|
10
|
+
|
11
|
+
task default: :test
|
12
|
+
|
13
|
+
desc "Generates an X509 certificate for decoding test ID tokens"
|
14
|
+
task "test:certificate:generate" do
|
15
|
+
require "openssl"
|
16
|
+
require "active_support"
|
17
|
+
require "active_support/core_ext/integer/time"
|
18
|
+
|
19
|
+
key = OpenSSL::PKey::RSA.new(File.read(File.expand_path("test/key.pem", __dir__)))
|
20
|
+
|
21
|
+
certificate = OpenSSL::X509::Certificate.new
|
22
|
+
certificate.subject = certificate.issuer = OpenSSL::X509::Name.parse("/CN=linkedin-sign-in-for-rails.example.com")
|
23
|
+
certificate.not_before = Time.now
|
24
|
+
certificate.not_after = 5.years.from_now
|
25
|
+
certificate.public_key = key.public_key
|
26
|
+
certificate.serial = 0
|
27
|
+
certificate.version = 1
|
28
|
+
|
29
|
+
extension_factory = OpenSSL::X509::ExtensionFactory.new
|
30
|
+
extension_factory.subject_certificate = certificate
|
31
|
+
extension_factory.issuer_certificate = certificate
|
32
|
+
certificate.extensions = [
|
33
|
+
extension_factory.create_extension("basicConstraints", "CA:FALSE", true),
|
34
|
+
extension_factory.create_extension("keyUsage", "digitalSignature", true),
|
35
|
+
extension_factory.create_extension("extendedKeyUsage", "clientAuth", true)
|
36
|
+
]
|
37
|
+
|
38
|
+
certificate.sign(key, OpenSSL::Digest::SHA1.new)
|
39
|
+
File.write(File.expand_path("test/certificate.pem", __dir__), certificate.to_pem)
|
40
|
+
end
|
data/SECURITY.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
class LinkedinSignIn::AuthorizationsController < LinkedinSignIn::BaseController
|
4
|
+
def create
|
5
|
+
redirect_to login_url(scope: 'r_basicprofile r_emailaddress', state: state),
|
6
|
+
flash: { proceed_to: params.require(:proceed_to), state: state }
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def login_url(**params)
|
11
|
+
client.auth_code.authorize_url(prompt: 'login', **params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def state
|
15
|
+
@state ||= SecureRandom.base64(24)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
|
3
|
+
class LinkedinSignIn::BaseController < ActionController::Base
|
4
|
+
protect_from_forgery with: :exception
|
5
|
+
|
6
|
+
private
|
7
|
+
def client
|
8
|
+
@client ||= OAuth2::Client.new \
|
9
|
+
LinkedinSignIn.client_id,
|
10
|
+
LinkedinSignIn.client_secret,
|
11
|
+
authorize_url: 'https://www.linkedin.com/oauth/v2/authorization',
|
12
|
+
token_url: 'https://www.linkedin.com/oauth/v2/accessToken',
|
13
|
+
redirect_uri: callback_url
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_dependency 'linkedin_sign_in/redirect_protector'
|
2
|
+
|
3
|
+
class LinkedinSignIn::CallbacksController < LinkedinSignIn::BaseController
|
4
|
+
def show
|
5
|
+
if valid_request?
|
6
|
+
redirect_to proceed_to_url, flash: { linkedin_sign_in_token: token }
|
7
|
+
else
|
8
|
+
head :unprocessable_entity
|
9
|
+
end
|
10
|
+
rescue LinkedinSignIn::RedirectProtector::Violation => error
|
11
|
+
logger.error error.message
|
12
|
+
head :bad_request
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def valid_request?
|
17
|
+
flash[:state].present? && params.require(:state) == flash[:state] && params[:error].blank?
|
18
|
+
end
|
19
|
+
|
20
|
+
def proceed_to_url
|
21
|
+
flash[:proceed_to].tap { |url| LinkedinSignIn::RedirectProtector.ensure_same_origin(url, request.url) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def token
|
25
|
+
client.auth_code.get_token(params.require(:code)).token
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module LinkedinSignIn::ButtonHelper
|
2
|
+
def linkedin_sign_in_button(text = nil, proceed_to:, **options, &block)
|
3
|
+
form_with url: linkedin_sign_in.authorization_path, local: true do
|
4
|
+
hidden_field_tag(:proceed_to, proceed_to, id: nil) + button_tag(text, name: nil, **options, &block)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
data/bin/rails
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails gems
|
3
|
+
# installed from the root of your application.
|
4
|
+
|
5
|
+
ENGINE_ROOT = File.expand_path('..', __dir__)
|
6
|
+
ENGINE_PATH = File.expand_path('../lib/blorgh/engine', __dir__)
|
7
|
+
APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
|
8
|
+
|
9
|
+
# Set up gems listed in the Gemfile.
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
11
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
12
|
+
|
13
|
+
require 'rails'
|
14
|
+
require 'action_controller/railtie'
|
15
|
+
require 'rails/test_unit/railtie'
|
16
|
+
require 'rails/engine/commands'
|
data/config/routes.rb
ADDED