omniauth-yahoo-oauth2 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 784ac84ce174a7e01cc6ff2093f87258edaffa52
4
- data.tar.gz: 6383b98740bbac0c5b93787bb869306c828710de
2
+ SHA256:
3
+ metadata.gz: d5a2c23bd49d42781032387a982ba92dcf388a5946b3a75ab70e33b711959e36
4
+ data.tar.gz: 20b3e2e88fb855dd62a562b840a5259534da733e3a8728d683f85554db6b2cb9
5
5
  SHA512:
6
- metadata.gz: 499b6375e10ac27c860f80ae59e77b21aefb0a0958e6936355207f8d85fa79637b4ab6abe3145d5020f57b80be08213ffece4369f24e3f0647500508877d0204
7
- data.tar.gz: 1d635f2e19db108e51d11f0303da8f0852212064aa1e3cd31a4eb1ff0f6ed589313beac37c5f69c253bafcd3b226aaf5388bab1b02ea0fe147442b1886c1c1db
6
+ metadata.gz: 0f00d924baf2b6bda0c11c3d2bbd331d7afab7f82cc3fb953102adabbf5186f4ee3fab3c1f7a0cfcb87cde1a9300eea27a1f5f77b8f3e4ec7860b6ffb35941a6
7
+ data.tar.gz: e640145bfa89799591d54ec4d78414cbc066e3161c2c1ab662e6ab861ff5f1f3b737a469d2b5b646bd21376b3e06ccf8fa15c7adbbdac05c80a0792514c77f4f
data/README.md CHANGED
@@ -1,56 +1,67 @@
1
1
  ## omniauth-yahoo-oauth2 ##
2
2
 
3
- An unofficial, hastily-written Oauth2 OmniAuth strategy for Yahoo. Uses the authorization flow described at https://developer.yahoo.com/oauth2/guide/flows_authcode/.
3
+ An unofficial, hastily-written Oauth2 OmniAuth strategy for Yahoo. Uses the
4
+ authorization flow described at
5
+ https://developer.yahoo.com/oauth2/guide/flows_authcode/.
4
6
 
5
7
  Built using https://github.com/intridea/omniauth-oauth2.
6
8
 
7
9
  ## Setup ##
8
10
  `gem install omniauth-yahoo-oauth2`
9
11
 
10
- Create an app at https://developer.yahoo.com/apps to get a Yahoo client ID and secret.
12
+ Create an app at https://developer.yahoo.com/apps to get a Yahoo client ID and
13
+ secret.
11
14
 
12
15
  ## Usage ##
13
16
  ```ruby
14
17
  # In an initializer
15
18
  Rails.application.config.middleware.use OmniAuth::Builder do
16
- provider :yahoo_oauth2, yahoo_client_id, yahoo_secret,
17
- name: 'yahoo'
19
+ provider :yahoo_oauth2, yahoo_client_id, yahoo_secret, name: 'yahoo'
18
20
  end
19
21
  ```
20
22
 
21
23
  See https://github.com/intridea/omniauth for Omniauth instructions.
22
24
 
23
25
  ## Notes ##
24
- OmniAuth doesn't currently have built-in support for Basic Authentication for retrieving OAuth tokens, so `YahooOauth2#build_access_token` handles this inline.
25
26
 
26
- Yahoo returns an access_token, a refresh_token, and an expiration time for the access_token. They are available in the authentication hash in the callback:
27
+ OmniAuth doesn't currently have built-in support for Basic Authentication for
28
+ retrieving OAuth2 tokens, so `YahooOauth2::Client` overrides
29
+ `OAuth2::Client#get_token`. Yahoo also requires `redirect_uri` to be set when
30
+ refreshing the `access_token`, so `YahooOauth2::AccessToken` overrides
31
+ `OAuth2::AccessToken#refresh!` to handle that.
32
+
33
+ As with other OAuth2 providers, Yahoo returns an `access_token`, a
34
+ `refresh_token`, and an expiration time for the `access_token`. They are
35
+ available in the credentials hash in the callback:
36
+
37
+ ```ruby
38
+ credentials = request.env.fetch('omniauth.auth').fetch(:credentials)
39
+ tokens_hash = {
40
+ access_token: credentials[:token],
41
+ refresh_token: credentials[:refresh_token],
42
+ expires_at: credentials[:expires_at]
43
+ }
44
+ ```
45
+
46
+ They should be saved to your application's database. You can use the
47
+ `access_token` directly or use `YahooOauth2::AccessToken` for requests:
27
48
 
28
49
  ```ruby
29
- auth_info = request.env['omniauth.auth']
30
- access_token = auth_info[:credentials][:token]
31
- refresh_token = auth_info[:credentials][:refresh_token]
32
- expires_at = auth_info[:credentials][:expires_at]
50
+ client = YahooOauth2::Client.new(YAHOO_CLIENT_ID, YAHOO_SECRET)
51
+ token = YahooOauth2::AccessToken.from_hash(client, tokens_hash)
52
+ token.get(
53
+ "https://social.yahooapis.com/v1/user/#{uid}/profile?format=json"
54
+ ).parsed
33
55
  ```
34
56
 
35
- You can use the refresh_token to generate new access tokens:
57
+ And to refresh the access token once it has expired:
36
58
 
37
59
  ```ruby
38
- require 'oauth2'
39
- require 'base64'
40
-
41
- oauth_client = OAuth2::Client.new(YAHOO_CLIENT_ID, YAHOO_SECRET, {
42
- site: 'https://api.login.yahoo.com',
43
- authorize_url: '/oauth2/request_auth',
44
- token_url: '/oauth2/get_token',
45
- })
46
-
47
- auth = "Basic #{Base64.strict_encode64("#{YAHOO_CLIENT_ID}:#{YAHOO_SECRET}")}"
48
-
49
- new_token = oauth_client.get_token({
50
- redirect_uri: YOUR_CALLBACK_URL,
51
- refresh_token: YOUR_REFRESH_TOKEN,
52
- grant_type: 'refresh_token',
53
- headers: { 'Authorization' => auth } })
60
+ old_token = YahooOauth2::AccessToken.from_hash(client, tokens_hash)
61
+ if old_token.expired?
62
+ new_token = old_token.refresh!
63
+ new_token.to_hash # => update your database with this
64
+ end
54
65
  ```
55
66
 
56
67
  ## TODO ##
@@ -1 +1 @@
1
- require File.join('omniauth', 'yahoo_oauth2')
1
+ require 'omniauth/yahoo_oauth2'
@@ -1,49 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jwt"
1
4
  require 'omniauth/strategies/oauth2'
2
- require 'base64'
3
5
 
4
6
  module OmniAuth
5
7
  module Strategies
6
8
  class YahooOauth2 < OmniAuth::Strategies::OAuth2
7
- option :name, 'yahoo_oauth2'
8
-
9
+
10
+ OPEN_ID_CONNECT_SCOPES = "openid,profile,email"
11
+
12
+ ALLOWED_ISSUERS = %w[
13
+ https://api.login.yahoo.com
14
+ api.login.yahoo.com
15
+ login.yahoo.com
16
+ ].freeze
17
+
18
+ option :name, 'yahoo'
19
+
20
+ option :userinfo_url, "/openid/v1/userinfo"
21
+
9
22
  option :client_options, {
10
- site: 'https://api.login.yahoo.com',
11
- authorize_url: '/oauth2/request_auth',
12
- token_url: '/oauth2/get_token',
23
+ site: "https://api.login.yahoo.com",
24
+ authorize_url: "/oauth2/request_auth",
25
+ token_url: "/oauth2/get_token",
13
26
  }
14
27
 
15
- uid { access_token.params['xoauth_yahoo_guid'] }
28
+ option :skip_jwt, false
29
+ option :jwt_leeway, 300
30
+
31
+ option :authorize_params, {
32
+ response_type: 'code',
33
+ }
34
+
35
+ option :authorize_options, %i[
36
+ language
37
+ login_hint
38
+ max_age
39
+ prompt
40
+ redirect_uri
41
+ scope
42
+ state
43
+ ]
44
+
45
+ uid { raw_info['sub'] }
16
46
 
17
47
  info do
18
- {
19
- name: raw_info['profile']['nickname'],
20
- nickname: raw_info['profile']['nickname'],
21
- gender: raw_info['profile']['gender'],
22
- language: raw_info['profile']['lang'],
23
- location: raw_info['profile']['location'],
48
+ prune!({
49
+ name: raw_info["name"],
50
+ email: verified_email,
51
+ unverified_email: raw_info['email'],
52
+ email_verified: raw_info["email_verified"],
53
+ first_name: raw_info["given_name"],
54
+ last_name: raw_info["family_name"],
55
+ nickname: raw_info["nickname"],
56
+ gender: raw_info["gender"],
57
+ locale: raw_info['locale'],
58
+ image: raw_info['picture'],
59
+ phone: raw_info["phone_number"],
60
+ phone_verified: raw_info["phone_number_verified"],
24
61
  urls: {
25
- image: raw_info['profile']['image']['imageUrl'],
26
- profile: raw_info['profile']['profileUrl']
27
- }
28
- }
29
- end
30
-
31
- def build_access_token
32
- verifier = request.params['code']
33
-
34
- auth = "Basic #{Base64.strict_encode64("#{options.client_id}:#{options.client_secret}")}"
35
-
36
- token = client.get_token(
37
- { redirect_uri: callback_url, code: verifier, grant_type: 'authorization_code', headers: { 'Authorization' => auth } }.
38
- merge(token_params.to_hash(symbolize_keys: true)), deep_symbolize(options.auth_token_params))
39
-
40
- token
41
- end
42
-
62
+ profile: raw_info['profile'],
63
+ website: raw_info['website'],
64
+ },
65
+ })
66
+ end
67
+
68
+ # n.b. renamed raw_info to userinfo. Userinfo is part of the OIDc standard.
69
+ extra do
70
+ hash = {}
71
+ hash[:userinfo] = raw_info unless skip_info?
72
+ hash[:id_token] = access_token["id_token"]
73
+ hash[:id_info] = decode_info_token
74
+ prune! hash
75
+ end
76
+
43
77
  def raw_info
44
- raw_info_url = "https://social.yahooapis.com/v1/user/#{uid}/profile?format=json"
45
- @raw_info ||= access_token.get(raw_info_url).parsed
78
+ @raw_info ||= access_token.get(userinfo_url).parsed
79
+ end
80
+
81
+ private
82
+
83
+ # This follows the example in omniauth-google-oauth2.
84
+ #
85
+ # Probably better to set the redirect_uri as a client option when creating
86
+ # the client, because OAuth2::Client knows how to handle it, but that
87
+ # requires updating OmniAuth::Strategies::OAuth2.
88
+ def callback_url
89
+ options[:redirect_uri] || (full_host + script_name + callback_path)
90
+ end
91
+
92
+ def userinfo_url
93
+ options.client_options.site + options.userinfo_url
94
+ end
95
+
96
+ # This is copied from the omniauth-google-oauth2 gem
97
+ def verified_email
98
+ raw_info['email_verified'] ? raw_info['email'] : nil
99
+ end
100
+
101
+ # This is copied from the omniauth-google-oauth2 gem
102
+ def prune!(hash)
103
+ hash.delete_if do |_, v|
104
+ prune!(v) if v.is_a?(Hash)
105
+ v.nil? || (v.respond_to?(:empty?) && v.empty?)
106
+ end
46
107
  end
108
+
109
+ # super saves SecureRandom state to session and merges authorize_options
110
+ #
111
+ # This follows the example in omniauth-google-oauth2 and
112
+ # merges any request param with the same name as an authorize_option.
113
+ # It then saves state to the session (in case it was overwritten).
114
+ #
115
+ # Probably the better way to handle this is to build it into "options_for"
116
+ # and have another option (e.g. authorize_request_params).
117
+ def authorize_params
118
+ super.tap do |params|
119
+ options[:authorize_options].each do |k|
120
+ unless [nil, ''].include?(request.params[k.to_s])
121
+ params[k] = request.params[k.to_s]
122
+ end
123
+ session['omniauth.state'] = params[:state] if params[:state]
124
+ end
125
+ end
126
+ end
127
+
128
+ # This is copied from the omniauth-google-oauth2 gem
129
+ def decode_info_token
130
+ unless options[:skip_jwt] || access_token['id_token'].nil?
131
+ decoded = ::JWT.decode(access_token['id_token'], nil, false).first
132
+
133
+ # We have to manually verify the claims because the third parameter to
134
+ # JWT.decode is false since no verification key is provided.
135
+ ::JWT::Verify.verify_claims(decoded,
136
+ verify_iss: true,
137
+ iss: ALLOWED_ISSUERS,
138
+ verify_aud: true,
139
+ aud: options.client_id,
140
+ verify_sub: false,
141
+ verify_expiration: true,
142
+ verify_not_before: true,
143
+ verify_iat: true,
144
+ verify_jti: false,
145
+ leeway: options[:jwt_leeway])
146
+
147
+ decoded
148
+ end
149
+ end
150
+
47
151
  end
48
152
  end
49
153
  end
@@ -1 +1 @@
1
- require File.join('omniauth', 'strategies', 'yahoo_oauth2')
1
+ require 'omniauth/strategies/yahoo_oauth2'
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module YahooOauth2
3
- VERSION = '1.1.0'
3
+ VERSION = '1.2.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-yahoo-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amir Manji
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-06 00:00:00.000000000 Z
11
+ date: 2020-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: omniauth
@@ -86,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.2.2
89
+ rubygems_version: 3.0.3
91
90
  signing_key:
92
91
  specification_version: 4
93
92
  summary: A Yahoo OAuth2 strategy for OmniAuth.