stormpath-rails 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -19
  3. data/CHANGELOG.md +6 -0
  4. data/README.md +63 -1
  5. data/app/assets/stylesheets/stormpath.css.scss +31 -1
  6. data/app/controllers/stormpath/rails/facebook/create_controller.rb +30 -0
  7. data/app/controllers/stormpath/rails/github/create_controller.rb +30 -0
  8. data/app/controllers/stormpath/rails/google/create_controller.rb +26 -0
  9. data/app/controllers/stormpath/rails/linkedin/create_controller.rb +26 -0
  10. data/app/controllers/stormpath/rails/login/create_controller.rb +20 -4
  11. data/app/controllers/stormpath/rails/social_controller.rb +32 -0
  12. data/app/forms/stormpath/rails/login_form.rb +1 -11
  13. data/app/forms/stormpath/rails/social_login_form.rb +49 -0
  14. data/app/helpers/social_helper.rb +53 -4
  15. data/app/views/stormpath/rails/forgot_password/new.html.erb +1 -1
  16. data/app/views/stormpath/rails/layouts/stormpath.html.erb +0 -5
  17. data/app/views/stormpath/rails/login/new.html.erb +5 -0
  18. data/app/views/stormpath/rails/shared/_social_login.html.erb +24 -0
  19. data/lib/stormpath/rails/config/dynamic_configuration.rb +18 -0
  20. data/lib/stormpath/rails/config/social_login_verification.rb +41 -0
  21. data/lib/stormpath/rails/configuration.rb +7 -0
  22. data/lib/stormpath/rails/controller.rb +4 -1
  23. data/lib/stormpath/rails/errors/no_facebook_authorization_error.rb +9 -0
  24. data/lib/stormpath/rails/errors/no_github_authorization_error.rb +9 -0
  25. data/lib/stormpath/rails/facebook_auth_code_exchange.rb +44 -0
  26. data/lib/stormpath/rails/github_auth_code_exchange.rb +44 -0
  27. data/lib/stormpath/rails/router.rb +21 -0
  28. data/lib/stormpath/rails/social.rb +3 -20
  29. data/lib/stormpath/rails/version.rb +1 -1
  30. data/lib/stormpath/rails.rb +5 -0
  31. metadata +14 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db6a4d230306b6c5faf0906c6bdb1f7369ce5a57
4
- data.tar.gz: 6c392883dcfb9608965a6e5866b5a291be4d26b3
3
+ metadata.gz: 48bb07c0dcc20fc47b52dc66c81bdd8cf8a0825b
4
+ data.tar.gz: 35f2d306d8993fa41f790fdf43a379830f3cf424
5
5
  SHA512:
6
- metadata.gz: c5e85671ba7ab1768a3d88abb6bc2d1d2d33645389323ba49bb84c686fad51fc768ad5131ae3a8f8280d0e47bc4a3704335648fc17c6a1a2408b745d3a54e363
7
- data.tar.gz: 32f1cc547828bbf8212fc8f92eea53e7ead58732d112d79e100537cfec5359ad1a5c06c26a6c26af258d916d953cda07f8b9ad8dc2088ee866fe89dc287e3f4d
6
+ metadata.gz: 6b25c56c5d57352816707e3f8e85df6d9f7da0f282606fc22d2b11c2ba5705c93ac3605a454d88dbc8e0fc4a08a7731b79dbceb47d1809ab6559a13e32984c8a
7
+ data.tar.gz: c61c4c909484d3bceaf12eeb733773989e63e6836cd7b391793ebeb772d296b2ee2750643f83ee12b1cc31ad665ca26f055041e4f07c471e6934fe52a8bba5cf
data/.travis.yml CHANGED
@@ -13,28 +13,15 @@ install:
13
13
  - pip install --user sphinx
14
14
  script:
15
15
  - travis_retry rake
16
- # - cd docs
17
- # - make html
18
- # - cd ..
19
16
  after_success:
20
17
  - CURRENT_HASH=`git rev-parse HEAD`
21
- - RELEASE_VERSION=`git tag | xargs -I@ git log --format=format:"%ai @%n" -1 @ | sort | awk '{print $4}' | tail -n 1`
18
+ - RELEASE_VERSION=`git tag | xargs -I@ git log --format=format:"%ai @%n" -1 @ | sort
19
+ | awk '{print $4}' | tail -n 1`
22
20
  - RELEASE_HASH=`git rev-list $RELEASE_VERSION -n 1`
23
21
  - if [ "$CURRENT_HASH" = "$RELEASE_HASH" ]; then DEPLOY_DOCS=true; fi
24
- #- test -z "$DEPLOY_DOCS" || git clone git@github.com:stormpath/stormpath.github.io.git
25
- #- test -z "$DEPLOY_DOCS" || cd stormpath.github.io
26
- #- test -z "$DEPLOY_DOCS" || git fetch origin source:source
27
- #- test -z "$DEPLOY_DOCS" || git checkout source
28
- #- test -z "$DEPLOY_DOCS" || mkdir -p source/ruby/rails
29
- #- test -z "$DEPLOY_DOCS" || rm -rf source/ruby/rails/latest
30
- #- test -z "$DEPLOY_DOCS" || cp -r ../docs/_build/html source/ruby/rails/latest
31
- #- test -z "$DEPLOY_DOCS" || cp -r ../docs/_build/html source/ruby/rails/$RELEASE_VERSION
32
- #- test -z "$DEPLOY_DOCS" || git add --all
33
- #- test -z "$DEPLOY_DOCS" || git commit -m "stormpath-rails release $RELEASE_VERSION"
34
- #- test -z "$DEPLOY_DOCS" || git push origin source
35
22
  env:
36
23
  global:
37
- - STORMPATH_APPLICATION_URL=https://api.stormpath.com/v1/applications/3nZlLKVMIOPu71YC7TFR0o
38
- - secure: WJgw02cTjVKwGJMq+n3L8e7uVTK3mnEqxArw2w/X1h4s09XIQM0B2b8PuM/2o01rkQWUfhd6lTLDEsQE916lSS8REJbnbsZ1VyH83yeHL4VgJNaJDHvEAq+iFzHnvtLwWkyWm8fEb7DCnEXXA7M3sGt1girhfs0xfITpXputCHE=
39
- - secure: JpErPQAz1b/l3rpwt/N9J7SZiy4/UB1DOI+9Kq4OrC9kuq2vUw3VIAKIojqvwy+7OaKAxyWcsx1kQ3BCLOPV/OkORq1/bMpP4SL0/0KYX+WjBWZ+En+gx3aCY3kOLkkVpDS6gD2pulOeHubGNwhDrFLjKFtbuUBfZuEuAGVNnP8=
40
- - secure: hgaOzbsR8H6i5gYXLpqUTsPsio39aCjaPbMwk5ylbI7HRD91qfQbJwuzsAa7+ocLi6NQ7LBL1xa317mLBO2uqWIhN85sTRIut2bO6S+8cgS7GWikMKnwkgU8gpUdNjGYh0Y8nrgwPDo5PZTv0jyUZNCeEqoa1HhDF3DjTMFrXHA=
24
+ - STORMPATH_APPLICATION_URL=https://api.stormpath.com/v1/applications/4BiS1Hc1LuBEbszdDrOwyz
25
+ - secure: VMjIMI42vIPTMPTr0fnzSPiIjzuSAnT7iNWjhAXP9WsdaCmxwHp1vOlry4QuX8DzpKHv2MQubeUN/UA227Nk1xn+CVu9mujWOqvvjmL9m20wMJvwT4ctn7zG+FJK76id9TEyx0mCTlH4ZrRoDMGfM9yzhpsg8FtSebBDdHxePaM=
26
+ - secure: IhR6H9qxmxCDNbLK0ebYuIXQRsGA/JhD6In4V/hnSMJ8lPi2kwRn6eKclNCHGNjcy6QF1V5vddKIfKOkFFZvIyP26reygTX1g5Mfa8SqTGKh3DAW4WP+T+yaE4z4UBDK1zZpbV0Zbkw/HC0xeD8UPnjRzERX1LVZp1qeEjhQrks=
27
+ - secure: a5woUmOQPRW6FBQBaxKJATfggUD/BVTBfeRaS07u1SQOpMoGJZLY0m29PVx4fHwRD1E7ho31YIeH8wk1vMMrimIHSdE1B4pm4n8bUTi/gDFwavXq9KgTdH8f6Eli37nAXZum78m4NgL9+OlrKeJKCcROdzniZPvFaLrnOwBGzVs=
data/CHANGELOG.md CHANGED
@@ -1,6 +1,12 @@
1
1
  Stormpath Rails Changelog
2
2
  ============================
3
3
 
4
+ Version 2.2.0
5
+ -------------
6
+ Released on Nov 07, 2016
7
+ - Implement Authentication with Social Providers (Facebook, Google, Linkedin, Github)
8
+
9
+
4
10
  Version 2.1.0
5
11
  -------------
6
12
  Released on Nov 02, 2016
data/README.md CHANGED
@@ -85,7 +85,6 @@ Check below on how to override default routes.
85
85
  ## Configuration
86
86
 
87
87
  The gem is highly configurable through it's configuration file (config/stormpath.yml).
88
- Currently the only configurations not working are for social logins and ID Site (because they are still not implemented in the gem).
89
88
 
90
89
  You can use embedded ruby (ERB) in the configuration file:
91
90
 
@@ -176,6 +175,12 @@ Stormpath::Rails::Profile::ShowController
176
175
 
177
176
  Stormpath::Rails::Oauth2::NewController
178
177
  Stormpath::Rails::Oauth2::CreateController
178
+
179
+ Stormpath::Rails::SocialController
180
+ Stormpath::Rails::Facebook::CreateController
181
+ Stormpath::Rails::Github::CreateController
182
+ Stormpath::Rails::Google::CreateController
183
+ Stormpath::Rails::Linkedin::CreateController
179
184
  ```
180
185
 
181
186
  ### Routes
@@ -202,10 +207,67 @@ stormpath/rails/change_password/new.html.erb
202
207
  stormpath/rails/forgot_password/new.html.erb
203
208
 
204
209
  stormpath/rails/shared/_input.html.erb
210
+ stormpath/rails/shared/_social_login.html.erb
205
211
 
206
212
  stormpath/rails/verify_email/new.html.erb
207
213
  ```
208
214
 
215
+ ## Social Authentication
216
+
217
+ In order to successfully authenticate via a social provider you need to set up your directories and account stores on your application. The Social Login Providers currently supported by Stormpath are Facebook, GitHub, Google and LinkedIn.
218
+
219
+ Social Directories are a kind of mirrored Directory, in that they are used to mirror user information found in an external database. This means that entities like Groups can only exist in a your Stormpath Social Directory if they are mirrored in from the external Social provider.
220
+
221
+ ### Google
222
+ - create an application in the [Google Developer Console](https://console.developers.google.com/start)
223
+ - enable Google Login for your Google application
224
+ - copy the OAuth Credentials (Client ID and Secret) for your Google application
225
+ - in the Credentials tab you will see the Restrictions section. Write the origin URI of your application in the Authorized JavaScript origins field. For example, if you want to test logging in via Google locally, you can write http://localhost:3000
226
+ - In the authorized redirect URIs type in the callback URI to which Google is going to redirect after successful authentication: http://localhost:3000/callbacks/google
227
+ - log in to [your stormpath dashboard](https://api.stormpath.com/login) and visit the Directories section
228
+ - click on Create Directory and choose Google as the Directory Type. Name it and describe it however you want
229
+ - paste the copied OAuth Credentials that you copied when you created the Google application in the Google Client ID and secret fields
230
+ - paste the same authorized redirect URI as you did in the Google dashboard
231
+ - visit the Applications section and click on the application you're using
232
+ - click on Account Stores in the left sidebar and click on Add Account Store button
233
+ - after you add your newly created Google directory try starting up your server and visit /login. You should see the 1-click Google login button
234
+
235
+ ### Facebook
236
+ - create an application on the [Facebook Developer Site](https://developers.facebook.com/)
237
+ - copy your OAuth credentials (App ID and App Secret)
238
+ - add your application’s private and public root URLs. You can use http://localhost:3000 if you're testing logging in locally
239
+ - make sure you make your application public by clicking on the App review tab in the left sidebar and activating your Facebook application
240
+ - log in to [your stormpath dashboard](https://api.stormpath.com/login) and visit the Directories section
241
+ - click on Create Directory and choose Facebook as the Directory Type. Name it and describe it however you want
242
+ - paste the copied OAuth Credentials that you copied when you created the Facebook application in the Facebook Client ID and secret fields
243
+ - visit the Applications section and click on the application you're using
244
+ - click on Account Stores in the left sidebar and click on Add Account Store button
245
+ - after you add your newly created Facebook directory try starting up your server and visit /login. You should see the 1-click Facebook login button
246
+
247
+ ### GitHub
248
+ - create an application in the [GitHub Developer Site](https://github.com/settings/applications/new)
249
+ - copy the OAuth Credentials (Client ID and Secret) for your GitHub application
250
+ - add your application’s redirect URL, which is the URL the user will be returned to after successful authentication. You can use http://localhost:3000 if you're testing logging in locally
251
+ - log in to [your stormpath dashboard](https://api.stormpath.com/login) and visit the Directories section
252
+ - click on Create Directory and choose GitHub as the Directory Type. Name it and describe it however you want
253
+ - paste the copied OAuth Credentials that you copied when you created the GitHub application in the GitHub Client ID and secret fields
254
+ - visit the Applications section and click on the application you're using
255
+ - click on Account Stores in the left sidebar and click on Add Account Store button
256
+ - after you add your newly created GitHub directory try starting up your server and visit /login. You should see the 1-click GitHub login button
257
+
258
+ ### LinkedIn
259
+ - create an application in the [LinkedIn Developer Site](https://www.linkedin.com/secure/developer?newapp=)
260
+ - add your application’s redirect URLs, which are the URL the user will be returned to after successful authentication. If you're testing locally you can write http://localhost:3000/callbacks/linkedin
261
+ - copy OAuth Credentials (Client ID and Secret) for your LinkedIn application
262
+ - make sure you check r_basicprofile and r_emailaddress under the Default Application Permissions
263
+ - log in to [your stormpath dashboard](https://api.stormpath.com/login) and visit the Directories section
264
+ - click on Create Directory and choose LinkedIn as the Directory Type. Name it and describe it however you want
265
+ - paste the copied OAuth Credentials that you copied when you created the LinkedIn application in the LinkedIn Client ID and secret fields
266
+ - paste the redirect URI that you also saved in your LinkedIn dashboard http://localhost:3000/callbacks/linkedin
267
+ - visit the Applications section and click on the application you're using
268
+ - click on Account Stores in the left sidebar and click on Add Account Store button
269
+ - after you add your newly created LinkedIn directory try starting up your server and visit /login. You should see the 1-click LinkedIn login button
270
+
209
271
  ## Migrate Devise Account information to Stormpath
210
272
 
211
273
  If you already have a Rails application that uses devise and need to transfer all users, accounts, or however you named your model there's a nifty
@@ -60,6 +60,7 @@ p {
60
60
  color: #fff;
61
61
  font-size: 16px;
62
62
  border-radius: 3px;
63
+ padding: 9px 12px;
63
64
  }
64
65
  .btn-social:hover,
65
66
  .btn-social:focus {
@@ -93,6 +94,35 @@ p {
93
94
  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#e8503c, endColorstr=#ea604e);
94
95
  -ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#e8503c, endColorstr=#ea604e)";
95
96
  }
97
+ .btn-github {
98
+ background: -webkit-linear-gradient(#848282 50%, #7B7979 50%);
99
+ background: linear-gradient(#848282 50%, #7B7979 50%);
100
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#848282, endColorstr=#7B7979);
101
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#848282, endColorstr=#7B7979)";
102
+ }
103
+ .btn-github:hover,
104
+ .btn-github:focus {
105
+ color: #fff;
106
+ background: -webkit-linear-gradient(#8C8888 50%, #848080 50%);
107
+ background: linear-gradient(#8C8888 50%, #848080 50%);
108
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#8C8888, endColorstr=#848080);
109
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#8C8888, endColorstr=#848080)";
110
+ }
111
+ .btn-linkedin {
112
+ background: -webkit-linear-gradient(#007cbc 50%, #0077B5 50%);
113
+ background: linear-gradient(#007cbc 50%, #0077B5 50%);
114
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#007cbc, endColorstr=#0077B5);
115
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#007cbc, endColorstr=#0077B5)";
116
+ }
117
+
118
+ .btn-linkedin:hover,
119
+ .btn-linkedin:focus {
120
+ color: #fff;
121
+ background: -webkit-linear-gradient(#007cbc 50%, #0077B5 50%);
122
+ background: linear-gradient(#007cbc 50%, #0077B5 50%);
123
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#007cbc, endColorstr=#0077B5);
124
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#007cbc, endColorstr=#0077B5)";
125
+ }
96
126
  .btn-register {
97
127
  font-size: 16px;
98
128
  }
@@ -274,7 +304,7 @@ p {
274
304
  padding: 0px;
275
305
  }
276
306
  }
277
- .login-view .social-area button {
307
+ .login-view .social-area button, .login-view .social-area .btn {
278
308
  display: block;
279
309
  width: 100%;
280
310
  margin-bottom: 15px;
@@ -0,0 +1,30 @@
1
+ module Stormpath
2
+ module Rails
3
+ module Facebook
4
+ class CreateController < Stormpath::Rails::SocialController
5
+ def call
6
+ begin
7
+ login_the_account(account)
8
+ respond_with_success
9
+ rescue NoFacebookAuthorizationError => error
10
+ respond_with_error(error)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def access_token
17
+ FacebookAuthCodeExchange.new(root_url, params[:code]).access_token
18
+ end
19
+
20
+ def account_request
21
+ Stormpath::Provider::AccountRequest.new(:facebook, :access_token, access_token)
22
+ end
23
+
24
+ def account
25
+ Stormpath::Rails::Client.application.get_provider_account(account_request).account
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ module Stormpath
2
+ module Rails
3
+ module Github
4
+ class CreateController < Stormpath::Rails::SocialController
5
+ def call
6
+ begin
7
+ login_the_account(account)
8
+ respond_with_success
9
+ rescue NoGithubAuthorizationError => error
10
+ respond_with_error(error)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def access_token
17
+ GithubAuthCodeExchange.new(root_url, params[:code]).access_token
18
+ end
19
+
20
+ def account_request
21
+ Stormpath::Provider::AccountRequest.new(:github, :access_token, access_token)
22
+ end
23
+
24
+ def account
25
+ Stormpath::Rails::Client.application.get_provider_account(account_request).account
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ module Stormpath
2
+ module Rails
3
+ module Google
4
+ class CreateController < Stormpath::Rails::SocialController
5
+ def call
6
+ begin
7
+ login_the_account(account)
8
+ respond_with_success
9
+ rescue InvalidSptokenError, NoSptokenError => error
10
+ respond_with_error(error)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def account_request
17
+ Stormpath::Provider::AccountRequest.new(:google, :code, params[:code])
18
+ end
19
+
20
+ def account
21
+ Stormpath::Rails::Client.application.get_provider_account(account_request).account
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Stormpath
2
+ module Rails
3
+ module Linkedin
4
+ class CreateController < Stormpath::Rails::SocialController
5
+ def call
6
+ begin
7
+ login_the_account(account)
8
+ respond_with_success
9
+ rescue InvalidSptokenError, NoSptokenError => error
10
+ respond_with_error(error)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def account_request
17
+ Stormpath::Provider::AccountRequest.new(:linkedin, :code, params[:code])
18
+ end
19
+
20
+ def account
21
+ Stormpath::Rails::Client.application.get_provider_account(account_request).account
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -7,9 +7,9 @@ module Stormpath
7
7
  def call
8
8
  begin
9
9
  form.save!
10
- set_cookies
10
+ set_cookies unless social_login?
11
11
  respond_with_success
12
- rescue Stormpath::Error, LoginForm::FormError => error
12
+ rescue Stormpath::Error, LoginForm::FormError, SocialLoginForm::FormError => error
13
13
  respond_with_error(error)
14
14
  end
15
15
  end
@@ -17,7 +17,11 @@ module Stormpath
17
17
  private
18
18
 
19
19
  def form
20
- @form ||= LoginForm.new(params[:login], params[:password])
20
+ @form ||= if social_login?
21
+ SocialLoginForm.new(provider, access_token, cookies)
22
+ else
23
+ LoginForm.new(params[:login], params[:password])
24
+ end
21
25
  end
22
26
 
23
27
  def respond_with_success
@@ -44,7 +48,7 @@ module Stormpath
44
48
  end
45
49
 
46
50
  def serialized_account
47
- AccountSerializer.to_h(form.authentication_result.account)
51
+ AccountSerializer.to_h(form.account)
48
52
  end
49
53
 
50
54
  def login_redirect_route
@@ -54,6 +58,18 @@ module Stormpath
54
58
  stormpath_config.web.login.next_uri
55
59
  end
56
60
  end
61
+
62
+ def provider
63
+ params[:providerData][:providerId]
64
+ end
65
+
66
+ def access_token
67
+ params[:providerData][:accessToken]
68
+ end
69
+
70
+ def social_login?
71
+ params[:providerData].present?
72
+ end
57
73
  end
58
74
  end
59
75
  end
@@ -0,0 +1,32 @@
1
+ module Stormpath
2
+ module Rails
3
+ class SocialController < Stormpath::Rails::BaseController
4
+ def login_the_account(account)
5
+ AccountLoginWithStormpathToken.new(
6
+ cookies, account,
7
+ Stormpath::Rails::Client.application,
8
+ Stormpath::Rails::Client.client.data_store.api_key
9
+ ).call
10
+ end
11
+
12
+ def respond_with_success
13
+ respond_to do |format|
14
+ format.json { render nothing: true, status: :ok }
15
+ format.html { redirect_to stormpath_config.web.login.next_uri }
16
+ end
17
+ end
18
+
19
+ def respond_with_error(error)
20
+ respond_to do |format|
21
+ format.html do
22
+ flash.now[:error] = error.message
23
+ render stormpath_config.web.login.view
24
+ end
25
+ format.json do
26
+ render json: { status: error.status, message: error.message }, status: error.status
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,6 +3,7 @@ module Stormpath
3
3
  class LoginForm
4
4
  attr_accessor :login, :password
5
5
  attr_accessor :authentication_result
6
+ delegate :account, to: :authentication_result
6
7
 
7
8
  def initialize(login, password)
8
9
  @login = login
@@ -17,17 +18,6 @@ module Stormpath
17
18
  end
18
19
  end
19
20
 
20
- # def save
21
- # return false if invalid?
22
- # result = Client.authenticate_oauth(password_grant_request)
23
- #
24
- # if result.success?
25
- # self.authentication_result = result.authentication_result
26
- # else
27
- # errors.add(:base, result.error_message) && false
28
- # end
29
- # end
30
-
31
21
  def save!
32
22
  self.authentication_result = application.authenticate_oauth(password_grant_request)
33
23
  end
@@ -0,0 +1,49 @@
1
+ module Stormpath
2
+ module Rails
3
+ class SocialLoginForm
4
+ attr_accessor :provider, :access_token, :cookies, :account
5
+
6
+ def initialize(provider, access_token, cookies)
7
+ @provider = provider
8
+ @access_token = access_token
9
+ @cookies = cookies
10
+ validate_provider_presence
11
+ validate_access_token_presence
12
+ end
13
+
14
+ class FormError < ArgumentError
15
+ def status
16
+ 400
17
+ end
18
+ end
19
+
20
+ def save!
21
+ AccountLoginWithStormpathToken.new(
22
+ cookies, account,
23
+ Stormpath::Rails::Client.application,
24
+ Stormpath::Rails::Client.client.data_store.api_key
25
+ ).call
26
+ end
27
+
28
+ def account
29
+ Stormpath::Rails::Client.application.get_provider_account(request).account
30
+ end
31
+
32
+ private
33
+
34
+ def request
35
+ Stormpath::Provider::AccountRequest.new(provider.to_sym, :access_token, access_token)
36
+ end
37
+
38
+ def validate_provider_presence
39
+ return if provider.present?
40
+ raise FormError, "providerId can't be blank"
41
+ end
42
+
43
+ def validate_access_token_presence
44
+ return if access_token.present?
45
+ raise FormError, "access_token can't be blank"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,14 +1,63 @@
1
- # Legacy but will be used when social logins start.
2
1
  module SocialHelper
3
2
  def box_class
4
- facebook_login_enabled? ? 'small col-sm-8' : 'large col-sm-12'
3
+ social_providers_present? ? 'small col-sm-8' : 'large col-sm-12'
5
4
  end
6
5
 
7
6
  def label_class
8
- facebook_login_enabled? ? 'col-sm-12' : 'col-sm-4'
7
+ social_providers_present? ? 'col-sm-12' : 'col-sm-4'
9
8
  end
10
9
 
11
10
  def input_class
12
- facebook_login_enabled? ? 'col-sm-12' : 'col-sm-8'
11
+ social_providers_present? ? 'col-sm-12' : 'col-sm-8'
12
+ end
13
+
14
+ def facebook_oauth_url
15
+ URI::HTTPS.build(
16
+ host: 'www.facebook.com',
17
+ path: '/dialog/oauth',
18
+ query: {
19
+ client_id: Stormpath::Rails.config.web.facebook_app_id,
20
+ redirect_uri: facebook_callback_url,
21
+ scope: Stormpath::Rails.config.web.social.facebook.scope
22
+ }.to_query
23
+ ).to_s
24
+ end
25
+
26
+ def github_oauth_url
27
+ URI::HTTPS.build(
28
+ host: 'www.github.com',
29
+ path: '/login/oauth/authorize',
30
+ query: {
31
+ client_id: Stormpath::Rails.config.web.github_app_id,
32
+ redirect_uri: github_callback_url,
33
+ scope: Stormpath::Rails.config.web.social.github.scope
34
+ }.to_query
35
+ ).to_s
36
+ end
37
+
38
+ def google_oauth_url
39
+ URI::HTTPS.build(
40
+ host: 'accounts.google.com',
41
+ path: '/o/oauth2/auth',
42
+ query: {
43
+ client_id: Stormpath::Rails.config.web.google_app_id,
44
+ redirect_uri: google_callback_url,
45
+ scope: Stormpath::Rails.config.web.social.google.scope,
46
+ response_type: 'code'
47
+ }.to_query
48
+ ).to_s
49
+ end
50
+
51
+ def linkedin_oauth_url
52
+ URI::HTTPS.build(
53
+ host: 'www.linkedin.com',
54
+ path: '/oauth/v2/authorization',
55
+ query: {
56
+ client_id: Stormpath::Rails.config.web.linkedin_app_id,
57
+ redirect_uri: linkedin_callback_url,
58
+ scope: Stormpath::Rails.config.web.social.linkedin.scope,
59
+ response_type: 'code'
60
+ }.to_query
61
+ ).to_s
13
62
  end
14
63
  end
@@ -28,7 +28,7 @@
28
28
  <div class="form-group group-email">
29
29
  <%= form.label :email, class: "col-sm-4" %>
30
30
  <div class="col-sm-8">
31
- <%= form.text_field :email, placeholder: 'Email', class: "form-control", name: :email %>
31
+ <%= form.email_field :email, placeholder: 'Email', class: "form-control", name: :email %>
32
32
  </div>
33
33
  </div>
34
34
  <div>
@@ -19,11 +19,6 @@
19
19
  <div class="alert alert-success"><%= flash[:success] %></div>
20
20
  <% end %>
21
21
 
22
- <% if signed_in? %>
23
- <p>Logged in as: <%= current_account.given_name %></p>
24
- <%= link_to "Log out", logout_path, method: :post %>
25
- <% end %>
26
-
27
22
  <%= yield %>
28
23
 
29
24
  <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
@@ -3,7 +3,12 @@
3
3
  <div class="view login-view container">
4
4
  <div class="box row">
5
5
  <%= render partial: 'stormpath/rails/login/form' %>
6
+
7
+ <% if Stormpath::Rails.config.web.has_social_providers %>
8
+ <%= render 'stormpath/rails/shared/social_login' %>
9
+ <% end %>
6
10
  </div>
11
+
7
12
  <% if Stormpath::Rails.config.web.forgot_password.enabled %>
8
13
  <%= link_to "Forgot Password?", new_forgot_password_path, class: "forgot" %>
9
14
  <% end %>
@@ -0,0 +1,24 @@
1
+ <div class="social-area col-xs-12 col-sm-4">
2
+ <div class="header">
3
+ &nbsp;
4
+ </div>
5
+
6
+ <label>Easy 1-click login:</label>
7
+
8
+ <% if Stormpath::Rails.config.web.facebook_app_id %>
9
+ <%= link_to 'Facebook', facebook_oauth_url, class: 'btn btn-social btn-facebook' %>
10
+ <% end %>
11
+
12
+ <% if Stormpath::Rails.config.web.google_app_id %>
13
+ <%= link_to 'Google', google_oauth_url, class: 'btn btn-social btn-google' %>
14
+ <% end %>
15
+
16
+ <% if Stormpath::Rails.config.web.linkedin_app_id %>
17
+ <%= link_to 'LinkedIn', linkedin_oauth_url, class: 'btn btn-social btn-linkedin' %>
18
+ <% end %>
19
+
20
+ <% if Stormpath::Rails.config.web.github_app_id %>
21
+ <%= link_to 'GitHub', github_oauth_url, class: 'btn btn-social btn-github' %>
22
+ <% end %>
23
+
24
+ </div>
@@ -4,6 +4,16 @@ module Stormpath
4
4
  class DynamicConfiguration
5
5
  attr_reader :static_config
6
6
 
7
+ delegate(
8
+ :facebook_app_id,
9
+ :facebook_app_secret,
10
+ :github_app_id,
11
+ :github_app_secret,
12
+ :google_app_id,
13
+ :linkedin_app_id,
14
+ to: :social_login_verification
15
+ )
16
+
7
17
  def initialize(static_config)
8
18
  @static_config = static_config
9
19
  proccess_account_store_verification
@@ -26,6 +36,10 @@ module Stormpath
26
36
  password_reset_enabled?
27
37
  end
28
38
 
39
+ def has_social_providers?
40
+ facebook_app_id || github_app_id || google_app_id || linkedin_app_id
41
+ end
42
+
29
43
  def verify_email_enabled?
30
44
  return false if static_config.stormpath.web.verify_email.enabled == false
31
45
  email_verification_enabled?
@@ -54,6 +68,10 @@ module Stormpath
54
68
  static_config.stormpath.web.register.enabled
55
69
  ).call
56
70
  end
71
+
72
+ def social_login_verification
73
+ @social_login_verification ||= SocialLoginVerification.new(app.href)
74
+ end
57
75
  end
58
76
  end
59
77
  end
@@ -0,0 +1,41 @@
1
+ module Stormpath
2
+ module Rails
3
+ module Config
4
+ class SocialLoginVerification
5
+ attr_reader :app,
6
+ :facebook_app_id,
7
+ :facebook_app_secret,
8
+ :github_app_id,
9
+ :github_app_secret,
10
+ :google_app_id,
11
+ :linkedin_app_id
12
+
13
+ def initialize(app_href)
14
+ @app = Stormpath::Rails::Client.client.applications.get(app_href)
15
+ initialize_directories
16
+ end
17
+
18
+ private
19
+
20
+ def initialize_directories
21
+ app.account_store_mappings.each do |mapping|
22
+ account_store = mapping.account_store
23
+ next unless account_store.class == Stormpath::Resource::Directory
24
+ case account_store.provider.provider_id
25
+ when 'facebook'
26
+ @facebook_app_id = account_store.provider.client_id
27
+ @facebook_app_secret = account_store.provider.client_secret
28
+ when 'github'
29
+ @github_app_id = account_store.provider.client_id
30
+ @github_app_secret = account_store.provider.client_secret
31
+ when 'google'
32
+ @google_app_id = account_store.provider.client_id
33
+ when 'linkedin'
34
+ @linkedin_app_id = account_store.provider.client_id
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -26,6 +26,13 @@ module Stormpath
26
26
  config.stormpath.application.href = dynamic_config.app.href
27
27
  config.stormpath.web.forgot_password.enabled = dynamic_config.forgot_password_enabled?
28
28
  config.stormpath.web.change_password.enabled = dynamic_config.change_password_enabled?
29
+ config.stormpath.web.facebook_app_id = dynamic_config.facebook_app_id
30
+ config.stormpath.web.facebook_app_secret = dynamic_config.facebook_app_secret
31
+ config.stormpath.web.github_app_id = dynamic_config.github_app_id
32
+ config.stormpath.web.github_app_secret = dynamic_config.github_app_secret
33
+ config.stormpath.web.google_app_id = dynamic_config.google_app_id
34
+ config.stormpath.web.linkedin_app_id = dynamic_config.linkedin_app_id
35
+ config.stormpath.web.has_social_providers = dynamic_config.has_social_providers?
29
36
  config.stormpath.web.verify_email.enabled = dynamic_config.verify_email_enabled?
30
37
  end
31
38
  end
@@ -28,7 +28,10 @@ module Stormpath
28
28
  return if signed_in?
29
29
  respond_to do |format|
30
30
  format.html { redirect_to "#{stormpath_config.web.login.uri}?next=#{request.path}" }
31
- format.json { render nothing: true, status: 401 }
31
+ format.json do
32
+ response.headers['WWW-Authenticate'] = "Bearer realm=\"My Application\""
33
+ render nothing: true, status: 401
34
+ end
32
35
  end
33
36
  end
34
37
 
@@ -0,0 +1,9 @@
1
+ module Stormpath
2
+ module Rails
3
+ class NoFacebookAuthorizationError < ArgumentError
4
+ def message
5
+ 'An error occured while authenticating your account on Facebook'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Stormpath
2
+ module Rails
3
+ class NoGithubAuthorizationError < ArgumentError
4
+ def message
5
+ 'An error occured while authenticating your account on GitHub'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ module Stormpath
2
+ module Rails
3
+ class FacebookAuthCodeExchange
4
+ FACEBOOK_EXCHANGE_URL = URI('https://graph.facebook.com/v2.7/oauth/access_token')
5
+
6
+ attr_reader :root_url, :code
7
+
8
+ def initialize(root_url, code)
9
+ raise(NoFacebookAuthorizationError) if code.nil?
10
+ @root_url = root_url
11
+ @code = code
12
+ end
13
+
14
+ def access_token
15
+ @access_token ||= fetch_access_token(exchange_auth_code.body)
16
+ end
17
+
18
+ private
19
+
20
+ def exchange_auth_code
21
+ http_client.post(FACEBOOK_EXCHANGE_URL, encoded_params)
22
+ end
23
+
24
+ def fetch_access_token(response_body)
25
+ JSON.parse(response_body)['access_token']
26
+ end
27
+
28
+ def encoded_params
29
+ URI.encode_www_form(
30
+ client_id: Stormpath::Rails.config.web.facebook_app_id,
31
+ client_secret: Stormpath::Rails.config.web.facebook_app_secret,
32
+ redirect_uri: URI.join(root_url, Stormpath::Rails.config.web.social.facebook.uri).to_s,
33
+ code: code
34
+ )
35
+ end
36
+
37
+ def http_client
38
+ client = Net::HTTP.new(FACEBOOK_EXCHANGE_URL.host, FACEBOOK_EXCHANGE_URL.port)
39
+ client.use_ssl = true
40
+ client
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ module Stormpath
2
+ module Rails
3
+ class GithubAuthCodeExchange
4
+ GITHUB_EXCHANGE_URL = URI('https://github.com/login/oauth/access_token')
5
+
6
+ attr_reader :root_url, :code
7
+
8
+ def initialize(root_url, code)
9
+ raise(NoGithubAuthorizationError) if code.nil?
10
+ @root_url = root_url
11
+ @code = code
12
+ end
13
+
14
+ def access_token
15
+ @access_token ||= fetch_access_token(exchange_auth_code.body)
16
+ end
17
+
18
+ private
19
+
20
+ def exchange_auth_code
21
+ http_client.post(GITHUB_EXCHANGE_URL, encoded_params, 'Accept' => 'application/json')
22
+ end
23
+
24
+ def fetch_access_token(response_body)
25
+ JSON.parse(response_body)['access_token']
26
+ end
27
+
28
+ def encoded_params
29
+ URI.encode_www_form(
30
+ client_id: Stormpath::Rails.config.web.github_app_id,
31
+ client_secret: Stormpath::Rails.config.web.github_app_secret,
32
+ redirect_uri: URI.join(root_url, Stormpath::Rails.config.web.social.github.uri).to_s,
33
+ code: code
34
+ )
35
+ end
36
+
37
+ def http_client
38
+ client = Net::HTTP.new(GITHUB_EXCHANGE_URL.host, GITHUB_EXCHANGE_URL.port)
39
+ client.use_ssl = true
40
+ client
41
+ end
42
+ end
43
+ end
44
+ end
@@ -16,6 +16,10 @@ module Stormpath
16
16
  'oauth2#create' => 'stormpath/rails/oauth2/create#call',
17
17
  'verify_email#show' => 'stormpath/rails/verify_email/show#call',
18
18
  'verify_email#create' => 'stormpath/rails/verify_email/create#call',
19
+ 'facebook#create' => 'stormpath/rails/facebook/create#call',
20
+ 'github#create' => 'stormpath/rails/github/create#call',
21
+ 'google#create' => 'stormpath/rails/google/create#call',
22
+ 'linkedin#create' => 'stormpath/rails/linkedin/create#call',
19
23
  'id_site_login#new' => 'stormpath/rails/id_site_login/new#call',
20
24
  'id_site_logout#new' => 'stormpath/rails/id_site_logout/new#call'
21
25
  }.freeze
@@ -69,6 +73,23 @@ module Stormpath
69
73
  post Stormpath::Rails.config.web.verify_email.uri => actions['verify_email#create'], as: :verify_email
70
74
  end
71
75
 
76
+ # SOCIAL LOGINS
77
+ if Stormpath::Rails.config.web.facebook_app_id
78
+ get Stormpath::Rails.config.web.social.facebook.uri => actions['facebook#create'], as: :facebook_callback
79
+ end
80
+
81
+ if Stormpath::Rails.config.web.github_app_id
82
+ get Stormpath::Rails.config.web.social.github.uri => actions['github#create'], as: :github_callback
83
+ end
84
+
85
+ if Stormpath::Rails.config.web.google_app_id
86
+ get Stormpath::Rails.config.web.social.google.uri => actions['google#create'], as: :google_callback
87
+ end
88
+
89
+ if Stormpath::Rails.config.web.linkedin_app_id
90
+ get Stormpath::Rails.config.web.social.linkedin.uri => actions['linkedin#create'], as: :linkedin_callback
91
+ end
92
+
72
93
  # ID SITE LOGIN
73
94
  if Stormpath::Rails.config.web.id_site.enabled
74
95
  get '/id_site_result' => actions['id_site_login#new'], as: :id_site_result
@@ -4,30 +4,13 @@ module Stormpath
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- helper_method :facebook_login_enabled?, :facebook_app_id,
8
- :google_login_enabled?, :google_client_id, :social_auth?
7
+ helper_method :social_providers_present?
9
8
  end
10
9
 
11
10
  private
12
11
 
13
- def facebook_login_enabled?
14
- false # facebook_app_id.present?
15
- end
16
-
17
- def google_login_enabled?
18
- false # google_client_id.present?
19
- end
20
-
21
- def facebook_app_id
22
- ENV['STORMPATH_FACEBOOK_APP_ID']
23
- end
24
-
25
- def google_client_id
26
- ENV['STORMPATH_GOOGLE_CLIENT_ID']
27
- end
28
-
29
- def social_auth?
30
- facebook_login_enabled? || google_login_enabled?
12
+ def social_providers_present?
13
+ Stormpath::Rails.config.web.has_social_providers
31
14
  end
32
15
  end
33
16
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Stormpath
3
3
  module Rails
4
- VERSION = '2.1.0'.freeze
4
+ VERSION = '2.2.0'.freeze
5
5
  end
6
6
  end
@@ -4,6 +4,7 @@ require 'stormpath/rails/config/read_file'
4
4
  require 'stormpath/rails/config/application_resolution'
5
5
  require 'stormpath/rails/config/account_store_verification'
6
6
  require 'stormpath/rails/config/dynamic_configuration'
7
+ require 'stormpath/rails/config/social_login_verification'
7
8
  require 'stormpath/rails/configuration'
8
9
  require 'stormpath/rails/router'
9
10
  require 'virtus'
@@ -18,5 +19,9 @@ module Stormpath
18
19
  autoload :RoutingConstraint, 'stormpath/rails/routing_constraint'
19
20
  autoload :InvalidSptokenError, 'stormpath/rails/errors/invalid_sptoken_error'
20
21
  autoload :NoSptokenError, 'stormpath/rails/errors/no_sptoken_error'
22
+ autoload :NoFacebookAuthorizationError, 'stormpath/rails/errors/no_facebook_authorization_error'
23
+ autoload :NoGithubAuthorizationError, 'stormpath/rails/errors/no_github_authorization_error'
24
+ autoload :FacebookAuthCodeExchange, 'stormpath/rails/facebook_auth_code_exchange'
25
+ autoload :GithubAuthCodeExchange, 'stormpath/rails/github_auth_code_exchange'
21
26
  end
22
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stormpath-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nenad Nikolic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-02 00:00:00.000000000 Z
11
+ date: 2016-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: stormpath-sdk
@@ -113,10 +113,14 @@ files:
113
113
  - app/controllers/stormpath/rails/base_controller.rb
114
114
  - app/controllers/stormpath/rails/change_password/create_controller.rb
115
115
  - app/controllers/stormpath/rails/change_password/new_controller.rb
116
+ - app/controllers/stormpath/rails/facebook/create_controller.rb
116
117
  - app/controllers/stormpath/rails/forgot_password/create_controller.rb
117
118
  - app/controllers/stormpath/rails/forgot_password/new_controller.rb
119
+ - app/controllers/stormpath/rails/github/create_controller.rb
120
+ - app/controllers/stormpath/rails/google/create_controller.rb
118
121
  - app/controllers/stormpath/rails/id_site_login/new_controller.rb
119
122
  - app/controllers/stormpath/rails/id_site_logout/new_controller.rb
123
+ - app/controllers/stormpath/rails/linkedin/create_controller.rb
120
124
  - app/controllers/stormpath/rails/login/create_controller.rb
121
125
  - app/controllers/stormpath/rails/login/new_controller.rb
122
126
  - app/controllers/stormpath/rails/logout/create_controller.rb
@@ -125,11 +129,13 @@ files:
125
129
  - app/controllers/stormpath/rails/profile/show_controller.rb
126
130
  - app/controllers/stormpath/rails/register/create_controller.rb
127
131
  - app/controllers/stormpath/rails/register/new_controller.rb
132
+ - app/controllers/stormpath/rails/social_controller.rb
128
133
  - app/controllers/stormpath/rails/verify_email/create_controller.rb
129
134
  - app/controllers/stormpath/rails/verify_email/show_controller.rb
130
135
  - app/forms/stormpath/rails/login_form.rb
131
136
  - app/forms/stormpath/rails/registration_form.rb
132
137
  - app/forms/stormpath/rails/registration_form_fields.rb
138
+ - app/forms/stormpath/rails/social_login_form.rb
133
139
  - app/helpers/social_helper.rb
134
140
  - app/serializers/stormpath/rails/account_serializer.rb
135
141
  - app/serializers/stormpath/rails/form_serializer.rb
@@ -164,6 +170,7 @@ files:
164
170
  - app/views/stormpath/rails/register/_form.html.erb
165
171
  - app/views/stormpath/rails/register/new.html.erb
166
172
  - app/views/stormpath/rails/shared/_input.html.erb
173
+ - app/views/stormpath/rails/shared/_social_login.html.erb
167
174
  - app/views/stormpath/rails/verify_email/new.html.erb
168
175
  - bin/console
169
176
  - bin/rails
@@ -185,12 +192,17 @@ files:
185
192
  - lib/stormpath/rails/config/application_resolution.rb
186
193
  - lib/stormpath/rails/config/dynamic_configuration.rb
187
194
  - lib/stormpath/rails/config/read_file.rb
195
+ - lib/stormpath/rails/config/social_login_verification.rb
188
196
  - lib/stormpath/rails/configuration.rb
189
197
  - lib/stormpath/rails/content_type_negotiator.rb
190
198
  - lib/stormpath/rails/controller.rb
191
199
  - lib/stormpath/rails/engine.rb
192
200
  - lib/stormpath/rails/errors/invalid_sptoken_error.rb
201
+ - lib/stormpath/rails/errors/no_facebook_authorization_error.rb
202
+ - lib/stormpath/rails/errors/no_github_authorization_error.rb
193
203
  - lib/stormpath/rails/errors/no_sptoken_error.rb
204
+ - lib/stormpath/rails/facebook_auth_code_exchange.rb
205
+ - lib/stormpath/rails/github_auth_code_exchange.rb
194
206
  - lib/stormpath/rails/router.rb
195
207
  - lib/stormpath/rails/routing_constraint.rb
196
208
  - lib/stormpath/rails/social.rb