Skip to content

Commit 62eb09c

Browse files
author
Brad Horrocks
committed
As a OAuth consumer I want to get a refresh token during OAuth2 Registration
refresh token is now returned in oath registration Fixes PLAT-1218 Test Plan: Create a dev_key that has an invalid redirect_ur, this makes it easier to subvert the oauth process later. attempt to authorize your new key with a user. I used something like blackmesa.canvas.dev/login/oauth2/auth?client_id=30000000000001&response_type=code&redirect_uri=http://blackmesa.dev/redirect&state=YYY Sign in and authorize. You should be redirected to something similar to http://blackmesa.dev/redirect?code=1c8d2ff5498eb879db9737d494a4bbd64810c84cf7e1776d1f4cebdb9699244c6209add4838d02f0d67b969a599cee589fecbeef5f84ababb1ef6e4cb9099b68&state=YYY Take the code out of the url. open up [postman](<https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en) create a new post request with the following params code: #{code} client_id: #{your dev key's client id} client_secret: #{your dev key's client secret} make sure the response includes a refresh_token property. A postman request that can be imported [can be found here](https://gist.github.com/defektive/f1cced73b08e5f6a2925) ________ < Thanks > -------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || Change-Id: I8a8a8450825309232c903251231dec8c5d4e7463 Reviewed-on: https://gerrit.instructure.com/63256 Tested-by: Jenkins Reviewed-by: Nathan Mills <nathanm@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Brad Horrocks <bhorrocks@instructure.com>
1 parent 995f829 commit 62eb09c

5 files changed

Lines changed: 39 additions & 2 deletions

File tree

app/models/access_token.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
class AccessToken < ActiveRecord::Base
22
attr_reader :full_token
3+
attr_reader :plaintext_refresh_token
34
belongs_to :developer_key
45
belongs_to :user
56
has_one :account, through: :developer_key
@@ -24,6 +25,7 @@ class AccessToken < ActiveRecord::Base
2425
ALLOWED_SCOPES = ["#{OAUTH2_SCOPE_NAMESPACE}userinfo"]
2526

2627
before_create :generate_token
28+
before_create :generate_refresh_token
2729

2830
def self.authenticate(token_string)
2931
# hash the user supplied token with all of our known keys
@@ -95,6 +97,27 @@ def generate_token(overwrite=false)
9597
end
9698
end
9799

100+
def refresh_token=(new_token)
101+
self.crypted_refresh_token = AccessToken.hashed_token(new_token)
102+
@plaintext_refresh_token = new_token
103+
end
104+
105+
def generate_refresh_token(overwrite=false)
106+
if overwrite || !self.crypted_refresh_token
107+
self.refresh_token = CanvasSlug.generate(nil, TOKEN_SIZE)
108+
end
109+
end
110+
111+
def regenerate_refresh_token=(val)
112+
if val == '1' && !protected_token?
113+
generate_refresh_token(true)
114+
end
115+
end
116+
117+
def clear_plaintext_refresh_token!
118+
@plaintext_refresh_token = nil
119+
end
120+
98121
def protected_token?
99122
developer_key != DeveloperKey.default
100123
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class AddRefreshTokenToAccessTokens < ActiveRecord::Migration
2+
tag :predeploy
3+
4+
def self.up
5+
add_column :access_tokens, :crypted_refresh_token, :string
6+
add_index :access_tokens, [:crypted_refresh_token], :unique => true
7+
end
8+
9+
def self.down
10+
remove_column :access_tokens, :crypted_refresh_token
11+
end
12+
end

lib/canvas/oauth/token.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def create_access_token_if_needed(replace_tokens = false)
5757
@access_token = user.access_tokens.create!({:developer_key => key, :remember_access => remember_access?, :scopes => scopes, :purpose => purpose, expires_at: expiration_date})
5858

5959
@access_token.clear_full_token! if @access_token.scoped_to?(['userinfo'])
60+
@access_token.clear_plaintext_refresh_token! if @access_token.scoped_to?(['userinfo'])
6061
end
6162
end
6263

@@ -76,6 +77,7 @@ def self.find_reusable_access_token(user, key, scopes, purpose)
7677
def as_json(_options={})
7778
json = {
7879
'access_token' => access_token.full_token,
80+
'refresh_token' => access_token.plaintext_refresh_token,
7981
'user' => user.as_json(:only => [:id, :name], :include_root => false)
8082
}
8183
json['expires_in'] = access_token.expires_at.utc.to_time.to_i - Time.now.utc.to_i if access_token.expires_at

spec/controllers/oauth2_provider_controller_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
Canvas.stubs(:redis => redis)
134134
get :token, :client_id => key.id, :client_secret => key.api_key, :code => valid_code
135135
expect(response).to be_success
136-
expect(JSON.parse(response.body).keys.sort).to match_array(['access_token', 'user', 'expires_in'])
136+
expect(JSON.parse(response.body).keys.sort).to eq ['access_token', 'expires_in', 'refresh_token', 'user']
137137
end
138138

139139
it 'deletes existing tokens for the same key when replace_tokens=1' do

spec/lib/canvas/oauth/token_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def stub_out_cache(client_id = nil, scopes = nil)
157157
end
158158

159159
it 'does not put anything else into the json' do
160-
expect(json.keys.sort).to match_array(['access_token', 'user', 'expires_in'])
160+
expect(json.keys.sort).to eq ['access_token', 'expires_in', 'refresh_token', 'user']
161161
end
162162

163163
end

0 commit comments

Comments
 (0)