1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
# frozen_string_literal: true
module Doorkeeper
module OAuth
class RefreshTokenRequest < BaseRequest
include OAuth::Helpers
validate :token_presence, error: Errors::InvalidRequest
validate :token, error: Errors::InvalidGrant
validate :client, error: Errors::InvalidClient
validate :client_match, error: Errors::InvalidGrant
validate :scope, error: Errors::InvalidScope
attr_reader :access_token, :client, :credentials, :refresh_token
attr_reader :missing_param
def initialize(server, refresh_token, credentials, parameters = {})
@server = server
@refresh_token = refresh_token
@credentials = credentials
@original_scopes = parameters[:scope] || parameters[:scopes]
@refresh_token_parameter = parameters[:refresh_token]
@client = load_client(credentials) if credentials
end
private
def load_client(credentials)
Doorkeeper.config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
end
def before_successful_response
refresh_token.transaction do
refresh_token.lock!
raise Errors::InvalidGrantReuse if refresh_token.revoked?
refresh_token.revoke unless refresh_token_revoked_on_use?
create_access_token
end
super
end
def refresh_token_revoked_on_use?
Doorkeeper.config.access_token_model.refresh_token_revoked_on_use?
end
def default_scopes
refresh_token.scopes
end
def create_access_token
attributes = {}.merge(custom_token_attributes_with_data)
resource_owner =
if Doorkeeper.config.polymorphic_resource_owner?
refresh_token.resource_owner
else
refresh_token.resource_owner_id
end
if refresh_token_revoked_on_use?
attributes[:previous_refresh_token] = refresh_token.refresh_token
end
# RFC6749
# 1.5. Refresh Token
#
# Refresh tokens are issued to the client by the authorization server and are
# used to obtain a new access token when the current access token
# becomes invalid or expires, or to obtain additional access tokens
# with identical or narrower scope (access tokens may have a shorter
# lifetime and fewer permissions than authorized by the resource
# owner).
#
# Here we assume that TTL of the token received after refreshing should be
# the same as that of the original token.
#
@access_token = Doorkeeper.config.access_token_model.create_for(
application: refresh_token.application,
resource_owner: resource_owner,
scopes: scopes,
expires_in: refresh_token.expires_in,
use_refresh_token: true,
**attributes,
)
end
def validate_token_presence
@missing_param = :refresh_token if refresh_token.blank? && @refresh_token_parameter.blank?
@missing_param.nil?
end
def validate_token
refresh_token.present? && !refresh_token.revoked?
end
def validate_client
return true if credentials.blank?
client.present?
end
# @see https://datatracker.ietf.org/doc/html/rfc6749#section-1.5
#
def validate_client_match
return true if refresh_token.application_id.blank?
client && refresh_token.application_id == client.id
end
def validate_scope
if @original_scopes.present?
ScopeChecker.valid?(
scope_str: @original_scopes,
server_scopes: refresh_token.scopes,
)
else
true
end
end
def custom_token_attributes_with_data
refresh_token
.attributes
.with_indifferent_access
.slice(*Doorkeeper.config.custom_access_token_attributes)
.symbolize_keys
end
end
end
end
|