175 lines
5.5 KiB
Ruby
175 lines
5.5 KiB
Ruby
|
require 'spec_helper_integration'
|
||
|
|
||
|
describe 'Refresh Token Flow' do
|
||
|
before do
|
||
|
Doorkeeper.configure do
|
||
|
orm DOORKEEPER_ORM
|
||
|
use_refresh_token
|
||
|
end
|
||
|
client_exists
|
||
|
end
|
||
|
|
||
|
context 'issuing a refresh token' do
|
||
|
before do
|
||
|
authorization_code_exists application: @client
|
||
|
end
|
||
|
|
||
|
it 'client gets the refresh token and refreshses it' do
|
||
|
post token_endpoint_url(code: @authorization.token, client: @client)
|
||
|
|
||
|
token = Doorkeeper::AccessToken.first
|
||
|
|
||
|
should_have_json 'access_token', token.token
|
||
|
should_have_json 'refresh_token', token.refresh_token
|
||
|
|
||
|
expect(@authorization.reload).to be_revoked
|
||
|
|
||
|
post refresh_token_endpoint_url(client: @client, refresh_token: token.refresh_token)
|
||
|
|
||
|
new_token = Doorkeeper::AccessToken.last
|
||
|
should_have_json 'access_token', new_token.token
|
||
|
should_have_json 'refresh_token', new_token.refresh_token
|
||
|
|
||
|
expect(token.token).not_to eq(new_token.token)
|
||
|
expect(token.refresh_token).not_to eq(new_token.refresh_token)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'refreshing the token' do
|
||
|
before do
|
||
|
@token = FactoryBot.create(
|
||
|
:access_token,
|
||
|
application: @client,
|
||
|
resource_owner_id: 1,
|
||
|
use_refresh_token: true
|
||
|
)
|
||
|
end
|
||
|
|
||
|
context "refresh_token revoked on use" do
|
||
|
it 'client request a token with refresh token' do
|
||
|
post refresh_token_endpoint_url(
|
||
|
client: @client, refresh_token: @token.refresh_token
|
||
|
)
|
||
|
should_have_json(
|
||
|
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
||
|
)
|
||
|
expect(@token.reload).not_to be_revoked
|
||
|
end
|
||
|
|
||
|
it 'client request a token with expired access token' do
|
||
|
@token.update_attribute :expires_in, -100
|
||
|
post refresh_token_endpoint_url(
|
||
|
client: @client, refresh_token: @token.refresh_token
|
||
|
)
|
||
|
should_have_json(
|
||
|
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
||
|
)
|
||
|
expect(@token.reload).not_to be_revoked
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "refresh_token revoked on refresh_token request" do
|
||
|
before do
|
||
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
||
|
end
|
||
|
|
||
|
it 'client request a token with refresh token' do
|
||
|
post refresh_token_endpoint_url(
|
||
|
client: @client, refresh_token: @token.refresh_token
|
||
|
)
|
||
|
should_have_json(
|
||
|
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
||
|
)
|
||
|
expect(@token.reload).to be_revoked
|
||
|
end
|
||
|
|
||
|
it 'client request a token with expired access token' do
|
||
|
@token.update_attribute :expires_in, -100
|
||
|
post refresh_token_endpoint_url(
|
||
|
client: @client, refresh_token: @token.refresh_token
|
||
|
)
|
||
|
should_have_json(
|
||
|
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
||
|
)
|
||
|
expect(@token.reload).to be_revoked
|
||
|
end
|
||
|
end
|
||
|
|
||
|
it 'client gets an error for invalid refresh token' do
|
||
|
post refresh_token_endpoint_url(client: @client, refresh_token: 'invalid')
|
||
|
should_not_have_json 'refresh_token'
|
||
|
should_have_json 'error', 'invalid_grant'
|
||
|
end
|
||
|
|
||
|
it 'client gets an error for revoked access token' do
|
||
|
@token.revoke
|
||
|
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
|
||
|
should_not_have_json 'refresh_token'
|
||
|
should_have_json 'error', 'invalid_grant'
|
||
|
end
|
||
|
|
||
|
it 'second of simultaneous client requests get an error for revoked access token' do
|
||
|
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:revoked?).and_return(false, true)
|
||
|
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
|
||
|
|
||
|
should_not_have_json 'refresh_token'
|
||
|
should_have_json 'error', 'invalid_request'
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context 'refreshing the token with multiple sessions (devices)' do
|
||
|
before do
|
||
|
# enable password auth to simulate other devices
|
||
|
config_is_set(:grant_flows, ["password"])
|
||
|
config_is_set(:resource_owner_from_credentials) do
|
||
|
User.authenticate! params[:username], params[:password]
|
||
|
end
|
||
|
create_resource_owner
|
||
|
_another_token = post password_token_endpoint_url(
|
||
|
client: @client, resource_owner: @resource_owner
|
||
|
)
|
||
|
last_token.update_attribute :created_at, 5.seconds.ago
|
||
|
|
||
|
@token = FactoryBot.create(
|
||
|
:access_token,
|
||
|
application: @client,
|
||
|
resource_owner_id: @resource_owner.id,
|
||
|
use_refresh_token: true
|
||
|
)
|
||
|
@token.update_attribute :expires_in, -100
|
||
|
end
|
||
|
|
||
|
context "refresh_token revoked on use" do
|
||
|
it 'client request a token after creating another token with the same user' do
|
||
|
post refresh_token_endpoint_url(
|
||
|
client: @client, refresh_token: @token.refresh_token
|
||
|
)
|
||
|
|
||
|
should_have_json 'refresh_token', last_token.refresh_token
|
||
|
expect(@token.reload).not_to be_revoked
|
||
|
end
|
||
|
end
|
||
|
|
||
|
context "refresh_token revoked on refresh_token request" do
|
||
|
before do
|
||
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
||
|
end
|
||
|
|
||
|
it 'client request a token after creating another token with the same user' do
|
||
|
post refresh_token_endpoint_url(
|
||
|
client: @client, refresh_token: @token.refresh_token
|
||
|
)
|
||
|
|
||
|
should_have_json 'refresh_token', last_token.refresh_token
|
||
|
expect(@token.reload).to be_revoked
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def last_token
|
||
|
Doorkeeper::AccessToken.last_authorized_token_for(
|
||
|
@client.id, @resource_owner.id
|
||
|
)
|
||
|
end
|
||
|
end
|
||
|
end
|