-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rails API support #992
Rails API support #992
Conversation
expect(json[:response_type]).to eq subject.response_type | ||
expect(json[:scope]).to eq subject.scope | ||
expect(json[:client_name]).to eq client_name | ||
expect(json[:status]).to eq 'preauthorization' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
end | ||
let(:json){ subject.as_json({}) } | ||
it { is_expected.to respond_to :as_json } | ||
it 'returns correct values' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
allow(client).to receive(:uid).and_return client_id | ||
allow(client).to receive(:name).and_return client_name | ||
end | ||
let(:json){ subject.as_json({}) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
|
||
describe "as_json" do | ||
let(:client_id){ 'client_uid_123' } | ||
let(:client_name){ 'Acme Co.' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
@@ -151,5 +151,25 @@ module Doorkeeper::OAuth | |||
subject.redirect_uri = nil | |||
expect(subject).not_to be_authorizable | |||
end | |||
|
|||
describe "as_json" do | |||
let(:client_id){ 'client_uid_123' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
it 'sets redirect_uri to correct value' do | ||
redirect_uri = JSON.parse(response.body)['redirect_uri'] | ||
expect(redirect_uri).to_not be_nil | ||
expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq 'bearer' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
end | ||
|
||
it 'sets redirect_uri to correct value' do | ||
redirect_uri = JSON.parse(response.body)['redirect_uri'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
expect(JSON.parse(response.body)['status']).to eq('redirect') | ||
end | ||
|
||
it 'sets redirect_uri to correct value' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
end | ||
|
||
it 'sets status to redirect' do | ||
expect(JSON.parse(response.body)['status']).to eq('redirect') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
expect(Doorkeeper::AccessToken.count).to be 1 | ||
end | ||
|
||
it 'sets status to redirect' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
@@ -151,5 +151,25 @@ module Doorkeeper::OAuth | |||
subject.redirect_uri = nil | |||
expect(subject).not_to be_authorizable | |||
end | |||
|
|||
describe 'as_json' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
spec/lib/config_spec.rb
Outdated
@@ -331,4 +331,18 @@ | |||
it { expect(Doorkeeper.configuration.base_controller).to eq('ApplicationController') } | |||
end | |||
end | |||
|
|||
describe 'api_mode' do | |||
it 'is false by default' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
spec/lib/config_spec.rb
Outdated
@@ -331,4 +331,18 @@ | |||
it { expect(Doorkeeper.configuration.base_controller).to eq('ApplicationController') } | |||
end | |||
end | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace detected.
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id) | ||
end | ||
|
||
it 'issues the token for the current resource owner' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping.
No movement on this PR? |
Hi @Borzik . I like this approach more than original PR. Does it still WIP , maybe you need some help? I will look at your questions (aka side-effects) ASAP. |
Hi! When I submitted this PR I was working on a feature which was postponed, so I'm not working actively on this at the moment. Since you think this PR is worth attention, I'll look into it again next week, will rebase it on current master, and will try to get it out of WIP status (as I remember, it worked well for me on my app, but it still needs refactoring). |
Great! Let me know it you will need some help. |
Just found another issue with this configuration. I have an app that is api only but also one that is api and web. The api only works fine, however, the hybrid I want to remove protect_from forgery for authorization & token & revoke endpoints but would need to still have the routes defined for applications I think removing the routes should be separately configurable |
c8e3f15
to
df79d14
Compare
@@ -200,6 +272,44 @@ def translated_error_message(key) | |||
end | |||
end | |||
|
|||
describe 'GET #new in API mode with skip_authorization true' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block has too many lines. [29/25]
end | ||
|
||
it 'includes correct redirect URI' do | ||
expect(redirect_uri).to match(%r{^#{client.redirect_uri}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use // around regular expression.
post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri | ||
end | ||
let(:response_json_body){ JSON.parse(response.body) } | ||
let(:redirect_uri){ response_json_body['redirect_uri'] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
default_scopes_exist :public | ||
post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri | ||
end | ||
let(:response_json_body){ JSON.parse(response.body) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
end | ||
|
||
it 'renders correct redirect uri' do | ||
expect(redirect_uri).to match(%r{^#{client.redirect_uri}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use // around regular expression.
@@ -5,7 +5,8 @@ class ErrorResponse < BaseResponse | |||
|
|||
def self.from_request(request, attributes = {}) | |||
state = request.state if request.respond_to?(:state) | |||
new(attributes.merge(name: request.error, state: state)) | |||
redirect_uri = request.redirect_uri if request.respond_to?(:redirect_uri) | |||
new(attributes.merge(name: request.error, state: state, redirect_uri: redirect_uri)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [92/80]
@@ -5,7 +5,8 @@ class ErrorResponse < BaseResponse | |||
|
|||
def self.from_request(request, attributes = {}) | |||
state = request.state if request.respond_to?(:state) | |||
new(attributes.merge(name: request.error, state: state)) | |||
redirect_uri = request.redirect_uri if request.respond_to?(:redirect_uri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [81/80]
redirect_to auth.redirect_uri | ||
else | ||
render json: auth.body, status: auth.status | ||
return render(json: { status: :redirect, redirect_uri: auth.redirect_uri }, status: auth.status) if Doorkeeper.configuration.api_mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [141/80]
end | ||
else | ||
render :error | ||
if Doorkeeper.configuration.api_mode | ||
render json: @pre_auth.error_response.body[:error_description], status: :bad_request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [94/80]
end | ||
else | ||
render :error | ||
if Doorkeeper.configuration.api_mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert if nested inside else to elsif.
@@ -200,6 +272,44 @@ def translated_error_message(key) | |||
end | |||
end | |||
|
|||
describe 'GET #new in API mode with skip_authorization true' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block has too many lines. [29/25]
end | ||
|
||
it 'includes correct redirect URI' do | ||
expect(redirect_uri).to match(%r{^#{client.redirect_uri}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use // around regular expression.
post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri | ||
end | ||
let(:response_json_body){ JSON.parse(response.body) } | ||
let(:redirect_uri){ response_json_body['redirect_uri'] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
default_scopes_exist :public | ||
post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri | ||
end | ||
let(:response_json_body){ JSON.parse(response.body) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space missing to the left of {.
end | ||
|
||
it 'renders correct redirect uri' do | ||
expect(redirect_uri).to match(%r{^#{client.redirect_uri}}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use // around regular expression.
@@ -5,7 +5,8 @@ class ErrorResponse < BaseResponse | |||
|
|||
def self.from_request(request, attributes = {}) | |||
state = request.state if request.respond_to?(:state) | |||
new(attributes.merge(name: request.error, state: state)) | |||
redirect_uri = request.redirect_uri if request.respond_to?(:redirect_uri) | |||
new(attributes.merge(name: request.error, state: state, redirect_uri: redirect_uri)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [92/80]
@@ -5,7 +5,8 @@ class ErrorResponse < BaseResponse | |||
|
|||
def self.from_request(request, attributes = {}) | |||
state = request.state if request.respond_to?(:state) | |||
new(attributes.merge(name: request.error, state: state)) | |||
redirect_uri = request.redirect_uri if request.respond_to?(:redirect_uri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [81/80]
redirect_to auth.redirect_uri | ||
else | ||
render json: auth.body, status: auth.status | ||
return render(json: { status: :redirect, redirect_uri: auth.redirect_uri }, status: auth.status) if Doorkeeper.configuration.api_mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [141/80]
end | ||
else | ||
render :error | ||
if Doorkeeper.configuration.api_mode | ||
render json: @pre_auth.error_response.body[:error_description], status: :bad_request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line is too long. [94/80]
end | ||
else | ||
render :error | ||
if Doorkeeper.configuration.api_mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert if nested inside else to elsif.
df79d14
to
03cdd92
Compare
@@ -200,6 +272,46 @@ def translated_error_message(key) | |||
end | |||
end | |||
|
|||
describe 'GET #new in API mode with skip_authorization true' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block has too many lines. [31/25]
name: request.error, | ||
state: state, | ||
redirect_uri: redirect_uri | ||
})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent the right brace the same as the first position after the preceding left parenthesis.
redirect_uri = request.redirect_uri | ||
end | ||
new(attributes.merge({ | ||
name: request.error, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use 2 spaces for indentation in a hash, relative to the first position after the preceding left parenthesis.
if request.respond_to?(:redirect_uri) | ||
redirect_uri = request.redirect_uri | ||
end | ||
new(attributes.merge({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant curly braces around a hash parameter.
redirect_to auth.redirect_uri | ||
else | ||
render json: auth.body, status: auth.status | ||
return render( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Favor a normal if-statement over a modifier clause in a multiline statement.
else | ||
render :new | ||
end | ||
else | ||
render :error | ||
if Doorkeeper.configuration.api_mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert if nested inside else to elsif.
a49d8aa
to
d5849e7
Compare
redirect_uri = request.redirect_uri | ||
end | ||
new(attributes.merge( | ||
name: request.error, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent the first parameter one step more than attributes.merge(.
ca7debb
to
2a3036e
Compare
@JoeWoodward @nbulaj if success
if api_mode?
else
end
else
if api_mode?
else
end
end And if redirectable? and api_mode?
render ...
elsif redirectable?
redirect
else
render
end If you have any ideas how this can be improved, please let me know. |
Hi @Borzik. Can you please resolve the conflicts? What about some code issues, you can extract successful and error handling to separate private methods, like def new
if pre_auth.authorizable?
render_successful
else
render_error
end
end
private
# ...
# Nothing wrong with if elsif else :)
def render_successful
if skip_authorization? || matching_token?
auth = authorization.authorize
redirect_or_render auth
elsif Doorkeeper.configuration.api_mode
render json: @pre_auth
else
render :new
end
end
def render_error
if Doorkeeper.configuration.api_mode
render json: @pre_auth.error_response.body[:error_description],
status: :bad_request
else
render :error
end
end |
Hi @Borzik . Could you please rebase with the master to resolve the conflicts? I think it is ready to be merged |
Interested in seeing this in the new version. Hope that @Borzik can rebase these files. Is sth that could be done to help? |
2a3036e
to
ca36a93
Compare
@@ -4,7 +4,11 @@ class ErrorResponse < BaseResponse | |||
include OAuth::Helpers | |||
|
|||
def self.from_request(request, attributes = {}) | |||
new(attributes.merge(name: request.error, state: request.try(:state))) | |||
new(attributes.merge( | |||
name: request.error, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent the first parameter one step more than attributes.merge(.
ca36a93
to
26d4543
Compare
def render_error | ||
if Doorkeeper.configuration.api_mode | ||
render json: @pre_auth.error_response.body[:error_description], | ||
status: :bad_request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align the elements of a hash literal if they span more than one line.
26d4543
to
00fc954
Compare
This was influenced by #893, but I took a bit different approach and extended functionality to other areas. It is still WIP, but I just wanted to share what is done already, and I'll be glad to get some advices.
The main premise for this PR is that usually Rails APIs and frontend apps are running on different domains, so we cannot easily identity users by cookies or something like that (e.g. in our project we use devise_token_auth and authenticate users by tokens).
Switching on
api_mode
configuration will:api_mode
onstatus: redirect
andredirect_uri
instead of directly redirecting userAs a side effects, this PR:
Doorkeeper::Oauth::PreAuthorization
serializable by as_json method which will provide all information needed to show preauthorization pageDoorkeeper::Oauth::ErrorResponse
- for some reason, it was not set before. If we render ErrorResponse with api_mode, it will render the samestatus: redirect
andredirect_uri
with error messageAnyone who will use
api_mode
, will also need some oauth page (which can be easily implemented as a small SPA and that will be running on the same domain as main frontend application). They can make main frontend app do this job, but I assume it is not worth loading the whole app just to show a single dialogue message with Allow/Deny buttons. It will have to be responsible for:oauth/authorize
status: redirect
toredirect_uri
provided in responsePlease let me know your thoughts about it.