lib/rodauth/features/oauth.rb in rodauth-oauth-0.0.1 vs lib/rodauth/features/oauth.rb in rodauth-oauth-0.0.2
- old
+ new
@@ -12,10 +12,27 @@
end
end
using(RegexpExtensions)
end
+ unless String.method_defined?(:delete_suffix!)
+ module SuffixExtensions
+ refine(String) do
+ def delete_suffix!(suffix)
+ suffix = suffix.to_s
+ chomp! if frozen?
+ len = suffix.length
+ return unless len.positive? && index(suffix, -len)
+
+ self[-len..-1] = ""
+ self
+ end
+ end
+ end
+ using(SuffixExtensions)
+ end
+
SCOPES = %w[profile.read].freeze
depends :login
before "authorize"
@@ -49,26 +66,30 @@
auth_value_method :oauth_grant_expires_in, 60 * 5 # 5 minutes
auth_value_method :oauth_token_expires_in, 60 * 60 # 60 minutes
auth_value_method :use_oauth_implicit_grant_type, false
+ auth_value_method :oauth_require_pkce, false
+ auth_value_method :oauth_pkce_challenge_method, "S256"
+
# URL PARAMS
# Authorize / token
%w[
- grant_type code refresh_token client_id scope
+ grant_type code refresh_token client_id client_secret scope
state redirect_uri scopes token_type_hint token
- access_type response_type
+ access_type approval_prompt response_type
+ code_challenge code_challenge_method code_verifier
].each do |param|
auth_value_method :"#{param}_param", param
end
# Application
- APPLICATION_REQUIRED_PARAMS = %w[name description scopes homepage_url redirect_uri].freeze
+ APPLICATION_REQUIRED_PARAMS = %w[name description scopes homepage_url redirect_uri client_secret].freeze
auth_value_method :oauth_application_required_params, APPLICATION_REQUIRED_PARAMS
- (APPLICATION_REQUIRED_PARAMS + %w[client_id client_secret]).each do |param|
+ (APPLICATION_REQUIRED_PARAMS + %w[client_id]).each do |param|
auth_value_method :"oauth_application_#{param}_param", param
end
# OAuth Token
auth_value_method :oauth_tokens_path, "oauth-tokens"
@@ -81,17 +102,22 @@
expires_in revoked_at
].each do |column|
auth_value_method :"oauth_tokens_#{column}_column", column
end
+ # Oauth Token Hash
+ auth_value_method :oauth_tokens_token_hash_column, nil
+ auth_value_method :oauth_tokens_refresh_token_hash_column, nil
+
# OAuth Grants
auth_value_method :oauth_grants_table, :oauth_grants
auth_value_method :oauth_grants_id_column, :id
%i[
account_id oauth_application_id
redirect_uri code scopes access_type
expires_in revoked_at
+ code_challenge code_challenge_method
].each do |column|
auth_value_method :"oauth_grants_#{column}_column", column
end
auth_value_method :authorization_required_error_status, 401
@@ -128,12 +154,20 @@
auth_value_method :unsupported_token_type_message, "Invalid token type hint"
auth_value_method :unique_error_message, "is already in use"
auth_value_method :null_error_message, "is not filled"
+ # PKCE
+ auth_value_method :code_challenge_required_error_code, "invalid_request"
+ auth_value_method :code_challenge_required_message, "code challenge required"
+ auth_value_method :unsupported_transform_algorithm_error_code, "invalid_request"
+ auth_value_method :unsupported_transform_algorithm_message, "transform algorithm not supported"
+
auth_value_methods(
- :oauth_unique_id_generator
+ :oauth_unique_id_generator,
+ :secret_matches?,
+ :secret_hash
)
redirect(:oauth_application) do |id|
"/#{oauth_applications_path}/#{id}"
end
@@ -176,55 +210,35 @@
def initialize(scope)
@scope = scope
end
def state
- state = param(state_param)
-
- return unless state && !state.empty?
-
- state
+ param_or_nil(state_param)
end
def scopes
- scopes = param(scopes_param)
-
- return [oauth_application_default_scope] unless scopes && !scopes.empty?
-
- scopes.split(" ")
+ (param_or_nil(scopes_param) || oauth_application_default_scope).split(" ")
end
def client_id
- client_id = param(client_id_param)
+ param_or_nil(client_id_param)
+ end
- return unless client_id && !client_id.empty?
-
- client_id
+ def client_secret
+ param_or_nil(client_secret_param)
end
def redirect_uri
- redirect_uri = param(redirect_uri_param)
-
- return oauth_application[oauth_applications_redirect_uri_column] unless redirect_uri && !redirect_uri.empty?
-
- redirect_uri
+ param_or_nil(redirect_uri_param) || oauth_application[oauth_applications_redirect_uri_column]
end
def token_type_hint
- token_type_hint = param(token_type_hint_param)
-
- return "access_token" unless token_type_hint && !token_type_hint.empty?
-
- token_type_hint
+ param_or_nil(token_type_hint_param) || "access_token"
end
def token
- token = param(token_param)
-
- return unless token && !token.empty?
-
- token
+ param_or_nil(token_param)
end
def oauth_application
return @oauth_application if defined?(@oauth_application)
@@ -248,14 +262,13 @@
return unless scheme == "Bearer"
# check if there is a token
# check if token has not expired
# check if token has been revoked
- db[oauth_tokens_table].where(oauth_tokens_token_column => token)
- .where(Sequel[oauth_tokens_expires_in_column] >= Sequel::CURRENT_TIMESTAMP)
- .where(oauth_tokens_revoked_at_column => nil)
- .first
+ oauth_token_by_token(token).where(Sequel[oauth_tokens_expires_in_column] >= Sequel::CURRENT_TIMESTAMP)
+ .where(oauth_tokens_revoked_at_column => nil)
+ .first
end
end
def require_oauth_authorization(*scopes)
authorization_required unless authorization_token
@@ -315,14 +328,106 @@
end
end
private
+ def secret_matches?(oauth_application, secret)
+ BCrypt::Password.new(oauth_application[oauth_applications_client_secret_column]) == secret
+ end
+
+ def secret_hash(secret)
+ password_hash(secret)
+ end
+
def oauth_unique_id_generator
- SecureRandom.uuid
+ SecureRandom.hex(32)
end
+ def generate_token_hash(token)
+ Base64.urlsafe_encode64(Digest::SHA256.digest(token))
+ end
+
+ unless method_defined?(:password_hash)
+ # From login_requirements_base feature
+ if ENV["RACK_ENV"] == "test"
+ def password_hash_cost
+ BCrypt::Engine::MIN_COST
+ end
+ else
+ # :nocov:
+ def password_hash_cost
+ BCrypt::Engine::DEFAULT_COST
+ end
+ # :nocov:
+ end
+
+ def password_hash(password)
+ BCrypt::Password.create(password, cost: password_hash_cost)
+ end
+ end
+
+ def generate_oauth_token(params = {}, should_generate_refresh_token = true)
+ create_params = {
+ oauth_grants_expires_in_column => Time.now + oauth_token_expires_in
+ }.merge(params)
+
+ token = oauth_unique_id_generator
+ refresh_token = nil
+
+ if oauth_tokens_token_hash_column
+ create_params[oauth_tokens_token_hash_column] = generate_token_hash(token)
+ else
+ create_params[oauth_tokens_token_column] = token
+ end
+
+ if should_generate_refresh_token
+ refresh_token = oauth_unique_id_generator
+
+ if oauth_tokens_refresh_token_hash_column
+ create_params[oauth_tokens_refresh_token_hash_column] = generate_token_hash(refresh_token)
+ else
+ create_params[oauth_tokens_refresh_token_column] = refresh_token
+ end
+ end
+ oauth_token = _generate_oauth_token(create_params)
+
+ oauth_token[oauth_tokens_token_column] = token
+ oauth_token[oauth_tokens_refresh_token_column] = refresh_token if refresh_token
+ oauth_token
+ end
+
+ def _generate_oauth_token(params = {})
+ ds = db[oauth_tokens_table]
+
+ begin
+ if ds.supports_returning?(:insert)
+ ds.returning.insert(params)
+ else
+ id = ds.insert(params)
+ ds.where(oauth_tokens_id_column => id).first
+ end
+ rescue Sequel::UniqueConstraintViolation
+ retry
+ end
+ end
+
+ def oauth_token_by_token(token)
+ if oauth_tokens_token_hash_column
+ db[oauth_tokens_table].where(oauth_tokens_token_hash_column => generate_token_hash(token))
+ else
+ db[oauth_tokens_table].where(oauth_tokens_token_column => token)
+ end
+ end
+
+ def oauth_token_by_refresh_token(token)
+ if oauth_tokens_refresh_token_hash_column
+ db[oauth_tokens_table].where(oauth_tokens_refresh_token_hash_column => generate_token_hash(token))
+ else
+ db[oauth_tokens_table].where(oauth_tokens_refresh_token_column => token)
+ end
+ end
+
# Oauth Application
def oauth_application_params
@oauth_application_params ||= oauth_application_required_params.each_with_object({}) do |param, params|
value = request.params[__send__(:"oauth_application_#{param}_param")]
@@ -361,13 +466,15 @@
oauth_applications_homepage_url_column => oauth_application_params[oauth_application_homepage_url_param],
oauth_applications_redirect_uri_column => oauth_application_params[oauth_application_redirect_uri_param]
}
# set client ID/secret pairs
+
create_params.merge! \
oauth_applications_client_id_column => oauth_unique_id_generator,
- oauth_applications_client_secret_column => oauth_unique_id_generator
+ oauth_applications_client_secret_column => \
+ secret_hash(oauth_application_params[oauth_application_client_secret_param])
create_params[oauth_applications_scopes_column] = if create_params[oauth_applications_scopes_column]
create_params[oauth_applications_scopes_column].join(",")
else
oauth_application_default_scope
@@ -402,30 +509,61 @@
end
# Authorize
def validate_oauth_grant_params
- unless oauth_application && check_valid_redirect_uri? && check_valid_access_type?
+ unless oauth_application && check_valid_redirect_uri? && check_valid_access_type? &&
+ check_valid_approval_prompt? && check_valid_response_type?
redirect_response_error("invalid_request")
end
redirect_response_error("invalid_scope") unless check_valid_scopes?
+
+ validate_pkce_challenge_params
end
+ def try_approval_prompt
+ approval_prompt = param_or_nil(approval_prompt_param)
+
+ return unless approval_prompt && approval_prompt == "auto"
+
+ return if db[oauth_grants_table].where(
+ oauth_grants_account_id_column => account_id,
+ oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column],
+ oauth_grants_redirect_uri_column => redirect_uri,
+ oauth_grants_scopes_column => scopes.join(","),
+ oauth_grants_access_type_column => "online"
+ ).count.zero?
+
+ # if there's a previous oauth grant for the params combo, it means that this user has approved before.
+
+ request.env["REQUEST_METHOD"] = "POST"
+ end
+
def create_oauth_grant
create_params = {
oauth_grants_account_id_column => account_id,
oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column],
oauth_grants_redirect_uri_column => redirect_uri,
oauth_grants_code_column => oauth_unique_id_generator,
oauth_grants_expires_in_column => Time.now + oauth_grant_expires_in,
oauth_grants_scopes_column => scopes.join(",")
}
- unless (access_type = param("access_type")).empty?
+ if (access_type = param_or_nil(access_type_param))
create_params[oauth_grants_access_type_column] = access_type
end
+ # PKCE flow
+ if (code_challenge = param_or_nil(code_challenge_param))
+ code_challenge_method = param_or_nil(code_challenge_method_param)
+
+ create_params[oauth_grants_code_challenge_column] = code_challenge
+ create_params[oauth_grants_code_challenge_method_column] = code_challenge_method
+ elsif oauth_require_pkce
+ redirect_response_error("code_challenge_required")
+ end
+
ds = db[oauth_grants_table]
begin
if ds.supports_returning?(:insert)
ds.returning(authorize_code_column).insert(create_params)
@@ -439,108 +577,116 @@
end
# Access Tokens
def validate_oauth_token_params
- redirect_response_error("invalid_request") unless param(client_id_param)
+ redirect_response_error("invalid_request") unless param_or_nil(client_id_param)
- unless (grant_type = param(grant_type_param))
+ unless param_or_nil(client_secret_param)
+ redirect_response_error("invalid_request") unless param_or_nil(code_verifier_param)
+ end
+
+ unless (grant_type = param_or_nil(grant_type_param))
redirect_response_error("invalid_request")
end
case grant_type
when "authorization_code"
- redirect_response_error("invalid_request") unless param(code_param)
+ redirect_response_error("invalid_request") unless param_or_nil(code_param)
when "refresh_token"
- redirect_response_error("invalid_request") unless param(refresh_token_param)
+ redirect_response_error("invalid_request") unless param_or_nil(refresh_token_param)
else
redirect_response_error("invalid_request")
end
end
- def generate_oauth_token(params = {})
- create_params = {
- oauth_grants_expires_in_column => Time.now + oauth_token_expires_in,
- oauth_tokens_token_column => oauth_unique_id_generator
- }.merge(params)
+ def create_oauth_token
+ oauth_application = db[oauth_applications_table].where(
+ oauth_applications_client_id_column => param(client_id_param)
+ ).first
- ds = db[oauth_tokens_table]
+ redirect_response_error("invalid_request") unless oauth_application
- begin
- if ds.supports_returning?(:insert)
- ds.returning.insert(create_params)
- else
- id = ds.insert(create_params)
- ds.where(oauth_tokens_id_column => id).first
- end
- rescue Sequel::UniqueConstraintViolation
- retry
+ if (client_secret = param_or_nil(client_secret_param))
+ redirect_response_error("invalid_request") unless secret_matches?(oauth_application, client_secret)
end
- end
- def create_oauth_token
case param(grant_type_param)
when "authorization_code"
+
# fetch oauth grant
oauth_grant = db[oauth_grants_table].where(
oauth_grants_code_column => param(code_param),
oauth_grants_redirect_uri_column => param(redirect_uri_param),
- oauth_grants_oauth_application_id_column => db[oauth_applications_table].where(
- oauth_applications_client_id_column => param(client_id_param),
- oauth_applications_account_id_column => oauth_applications_account_id_column
- ).select(oauth_applications_id_column)
+ oauth_grants_oauth_application_id_column => oauth_application[oauth_applications_id_column],
+ oauth_grants_revoked_at_column => nil
).where(Sequel[oauth_grants_expires_in_column] >= Sequel::CURRENT_TIMESTAMP)
- .where(oauth_grants_revoked_at_column => nil)
.first
redirect_response_error("invalid_grant") unless oauth_grant
+ # PKCE
+ if oauth_grant[oauth_grants_code_challenge_column]
+ code_verifier = param_or_nil(code_verifier_param)
+
+ unless code_verifier && check_valid_grant_challenge?(oauth_grant, code_verifier)
+ redirect_response_error("invalid_request")
+ end
+ elsif oauth_require_pkce
+ redirect_response_error("code_challenge_required")
+ end
+
create_params = {
oauth_tokens_account_id_column => oauth_grant[oauth_grants_account_id_column],
oauth_tokens_oauth_application_id_column => oauth_grant[oauth_grants_oauth_application_id_column],
oauth_tokens_oauth_grant_id_column => oauth_grant[oauth_grants_id_column],
oauth_tokens_scopes_column => oauth_grant[oauth_grants_scopes_column]
}
- if oauth_grant[oauth_grants_access_type_column] == "offline"
- create_params[oauth_tokens_refresh_token_column] = oauth_unique_id_generator
- end
# revoke oauth grant
db[oauth_grants_table].where(oauth_grants_id_column => oauth_grant[oauth_grants_id_column])
.update(oauth_grants_revoked_at_column => Sequel::CURRENT_TIMESTAMP)
- generate_oauth_token(create_params)
+ generate_oauth_token(create_params, oauth_grant[oauth_grants_access_type_column] == "offline")
+
when "refresh_token"
- # fetch oauth grant
- oauth_token = db[oauth_tokens_table].where(
- oauth_tokens_refresh_token_column => param(refresh_token_param),
- oauth_tokens_oauth_application_id_column => db[oauth_applications_table].where(
- oauth_applications_client_id_column => param(client_id_param),
- oauth_applications_account_id_column => account_id
- ).select(oauth_applications_id_column)
+ # fetch oauth token
+ oauth_token = oauth_token_by_refresh_token(param(refresh_token_param)).where(
+ oauth_tokens_oauth_application_id_column => oauth_application[oauth_applications_id_column]
).where(oauth_grants_revoked_at_column => nil).first
redirect_response_error("invalid_grant") unless oauth_token
+ token = oauth_unique_id_generator
+
update_params = {
oauth_tokens_oauth_application_id_column => oauth_token[oauth_grants_oauth_application_id_column],
- oauth_tokens_expires_in_column => Time.now + oauth_token_expires_in,
- oauth_tokens_token_column => oauth_unique_id_generator
+ oauth_tokens_expires_in_column => Time.now + oauth_token_expires_in
}
+ if oauth_tokens_token_hash_column
+ update_params[oauth_tokens_token_hash_column] = generate_token_hash(token)
+ else
+ update_params[oauth_tokens_token_column] = token
+ end
+
ds = db[oauth_tokens_table].where(oauth_tokens_id_column => oauth_token[oauth_tokens_id_column])
- begin
+
+ oauth_token = begin
if ds.supports_returning?(:update)
ds.returning.update(update_params)
else
ds.update(update_params)
ds.first
end
- rescue Sequel::UniqueConstraintViolation
- retry
+ rescue Sequel::UniqueConstraintViolation
+ retry
end
+
+ oauth_token[oauth_tokens_token_column] = token
+ oauth_token
else
redirect_response_error("invalid_grant")
end
end
@@ -554,44 +700,45 @@
redirect_response_error("invalid_request") unless param(token_param)
end
def revoke_oauth_token
- # one can only revoke tokens which haven't been revoked before, and which are
- # either our tokens, or tokens from applications we own.
- ds = db[oauth_tokens_table]
- .where(oauth_tokens_revoked_at_column => nil)
- .where(
- Sequel.or(
- oauth_tokens_account_id_column => account_id,
- oauth_tokens_oauth_application_id_column => db[oauth_applications_table].where(
- oauth_applications_client_id_column => param(client_id_param),
- oauth_applications_account_id_column => account_id
- ).select(oauth_applications_id_column)
- )
- )
ds = case token_type_hint
when "access_token"
- ds.where(oauth_tokens_token_column => token)
+ oauth_token_by_token(token)
when "refresh_token"
- ds.where(oauth_tokens_refresh_token_column => token)
+ oauth_token_by_refresh_token(token)
end
+ # one can only revoke tokens which haven't been revoked before, and which are
+ # either our tokens, or tokens from applications we own.
+ oauth_token = ds.where(oauth_tokens_revoked_at_column => nil)
+ .where(
+ Sequel.or(
+ oauth_tokens_account_id_column => account_id,
+ oauth_tokens_oauth_application_id_column => db[oauth_applications_table].where(
+ oauth_applications_client_id_column => param(client_id_param),
+ oauth_applications_account_id_column => account_id
+ ).select(oauth_applications_id_column)
+ )
+ ).first
- oauth_token = ds.first
redirect_response_error("invalid_request") unless oauth_token
update_params = { oauth_tokens_revoked_at_column => Sequel::CURRENT_TIMESTAMP }
ds = db[oauth_tokens_table].where(oauth_tokens_id_column => oauth_token[oauth_tokens_id_column])
- if ds.supports_returning?(:update)
- ds.returning.update(update_params)
- else
- ds.update(update_params)
- ds.first
- end
+ oauth_token = if ds.supports_returning?(:update)
+ ds.returning.update(update_params)
+ else
+ ds.update(update_params)
+ ds.first
+ end
+ oauth_token[oauth_tokens_token_column] = token
+ oauth_token
+
# If the particular
# token is a refresh token and the authorization server supports the
# revocation of access tokens, then the authorization server SHOULD
# also invalidate all access tokens based on the same authorization
# grant
@@ -604,36 +751,55 @@
def redirect_response_error(error_code, redirect_url = request.referer || default_redirect)
if json_request?
throw_json_response_error(invalid_oauth_response_status, error_code)
else
redirect_url = URI.parse(redirect_url)
- query_params = ["error=#{error_code}"]
+ query_params = []
+
+ query_params << if respond_to?(:"#{error_code}_error_code")
+ "error=#{send(:"#{error_code}_error_code")}"
+ else
+ "error=#{error_code}"
+ end
+
if respond_to?(:"#{error_code}_message")
message = send(:"#{error_code}_message")
query_params << ["error_description=#{CGI.escape(message)}"]
end
+
query_params << redirect_url.query if redirect_url.query
redirect_url.query = query_params.join("&")
redirect(redirect_url.to_s)
end
end
def throw_json_response_error(status, error_code)
set_response_error_status(status)
- payload = { "error" => error_code }
+ code = if respond_to?(:"#{error_code}_error_code")
+ send(:"#{error_code}_error_code")
+ else
+ error_code
+ end
+ payload = { "error" => code }
payload["error_description"] = send(:"#{error_code}_message") if respond_to?(:"#{error_code}_message")
- json_payload = if request.respond_to?(:convert_to_json)
- request.send(:convert_to_json, payload)
- else
- JSON.dump(payload)
- end
+ json_payload = _json_response_body(payload)
response["Content-Type"] ||= json_response_content_type
response["WWW-Authenticate"] = "Bearer" if status == 401
response.write(json_payload)
request.halt
end
+ unless method_defined?(:_json_response_body)
+ def _json_response_body(hash)
+ if request.respond_to?(:convert_to_json)
+ request.send(:convert_to_json, hash)
+ else
+ JSON.dump(hash)
+ end
+ end
+ end
+
def authorization_required
if json_request?
throw_json_response_error(authorization_required_error_status, "invalid_client")
else
set_redirect_error_flash(require_authorization_error_flash)
@@ -652,29 +818,63 @@
end
ACCESS_TYPES = %w[offline online].freeze
def check_valid_access_type?
- access_type = param("access_type")
- access_type.empty? || ACCESS_TYPES.include?(access_type)
+ access_type = param_or_nil(access_type_param)
+ !access_type || ACCESS_TYPES.include?(access_type)
end
+ APPROVAL_PROMPTS = %w[force auto].freeze
+
+ def check_valid_approval_prompt?
+ approval_prompt = param_or_nil(approval_prompt_param)
+ !approval_prompt || APPROVAL_PROMPTS.include?(approval_prompt)
+ end
+
def check_valid_response_type?
- response_type = param("response_type")
+ response_type = param_or_nil(response_type_param)
- return true if response_type.empty? || response_type == "code"
+ return true if response_type.nil? || response_type == "code"
return use_oauth_implicit_grant_type if response_type == "token"
false
end
+ # PKCE
+
+ def validate_pkce_challenge_params
+ if param_or_nil(code_challenge_param)
+
+ challenge_method = param_or_nil(code_challenge_method_param)
+ redirect_response_error("code_challenge_required") unless oauth_pkce_challenge_method == challenge_method
+ else
+ return unless oauth_require_pkce
+
+ redirect_response_error("code_challenge_required")
+ end
+ end
+
+ def check_valid_grant_challenge?(grant, verifier)
+ challenge = grant[oauth_grants_code_challenge_column]
+
+ case grant[oauth_grants_code_challenge_method_column]
+ when "plain"
+ challenge == verifier
+ when "S256"
+ generated_challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(verifier))
+ generated_challenge.delete_suffix!("=") while generated_challenge.end_with?("=")
+
+ challenge == generated_challenge
+ else
+ redirect_response_error("unsupported_transform_algorithm")
+ end
+ end
+
# /oauth-token
route(:oauth_token) do |r|
- throw_json_response_error(authorization_required_error_status, "invalid_client") unless logged_in?
-
- # access-token
r.post do
catch_error do
validate_oauth_token_params
oauth_token = nil
@@ -685,22 +885,18 @@
end
response.status = 200
response["Content-Type"] ||= json_response_content_type
json_response = {
- "token" => oauth_token[:token],
+ "token" => oauth_token[oauth_tokens_token_column],
"token_type" => oauth_token_type,
"expires_in" => oauth_token_expires_in
}
- json_response["refresh_token"] = oauth_token[:refresh_token] if oauth_token[:refresh_token]
+ json_response["refresh_token"] = oauth_token[oauth_tokens_refresh_token_column] if oauth_token[:refresh_token]
- json_payload = if request.respond_to?(:convert_to_json)
- request.send(:convert_to_json, json_response)
- else
- JSON.dump(json_response)
- end
+ json_payload = _json_response_body(json_response)
response.write(json_payload)
request.halt
end
throw_json_response_error(invalid_oauth_response_status, "invalid_request")
@@ -725,19 +921,15 @@
if json_request?
response.status = 200
response["Content-Type"] ||= json_response_content_type
json_response = {
- "token" => oauth_token[:token],
- "refresh_token" => oauth_token[:refresh_token],
- "revoked_at" => oauth_token[:revoked_at]
+ "token" => oauth_token[oauth_tokens_token_column],
+ "refresh_token" => oauth_token[oauth_tokens_refresh_token_column],
+ "revoked_at" => oauth_token[oauth_tokens_revoked_at_column]
}
- json_payload = if request.respond_to?(:convert_to_json)
- request.send(:convert_to_json, json_response)
- else
- JSON.dump(json_response)
- end
+ json_payload = _json_response_body(json_response)
response.write(json_payload)
request.halt
else
set_notice_flash revoke_oauth_token_notice_flash
redirect request.referer || "/"
@@ -749,19 +941,18 @@
end
# /oauth-authorize
route(:oauth_authorize) do |r|
require_account
+ validate_oauth_grant_params
+ try_approval_prompt if request.get?
r.get do
- validate_oauth_grant_params
authorize_view
end
r.post do
- validate_oauth_grant_params
-
code = nil
query_params = []
fragment_params = []
transaction do
@@ -773,12 +964,12 @@
create_params = {
oauth_tokens_account_id_column => account_id,
oauth_tokens_oauth_application_id_column => oauth_application[oauth_applications_id_column],
oauth_tokens_scopes_column => scopes
}
- oauth_token = generate_oauth_token(create_params)
+ oauth_token = generate_oauth_token(create_params, false)
- fragment_params << ["access_token=#{oauth_token[:token]}"]
+ fragment_params << ["access_token=#{oauth_token[oauth_tokens_token_column]}"]
fragment_params << ["token_type=#{oauth_token_type}"]
fragment_params << ["expires_in=#{oauth_token_expires_in}"]
when "code", "", nil
code = create_oauth_grant
query_params << ["code=#{code}"]