-
-
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
Allow public clients to authenticate without client_secret #1031
Allow public clients to authenticate without client_secret #1031
Conversation
spec/requests/flows/password_spec.rb
Outdated
token = Doorkeeper::AccessToken.first | ||
context "when client_secret absent" do | ||
it "should not issue new token" do | ||
expect 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.
Parenthesize the param change { Doorkeeper::AccessToken.count } to make sure that the block will be associated with the change method call.
|
||
context "when client_secret incorrect" do | ||
it "should not issue new token" do | ||
expect 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.
Parenthesize the param change { Doorkeeper::AccessToken.count } to make sure that the block will be associated with the change method call.
expect do | ||
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner) | ||
end.to change { Doorkeeper::AccessToken.count }.by(1) | ||
context "with non-confidential/public client" 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]
app = FactoryBot.create :application | ||
authenticated = Application.by_uid_and_secret(app.uid, app.secret) | ||
expect(authenticated).to eq(app) | ||
describe :by_uid_and_secret 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. [30/25]
@@ -0,0 +1,11 @@ | |||
class AddConfidentialToApplication < ActiveRecord::Migration[5.1] |
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.
Missing magic comment # frozen_string_literal: true.
@@ -1,4 +1,4 @@ | |||
class AddOwnerToApplication < ActiveRecord::Migration | |||
class AddOwnerToApplication < ActiveRecord::Migration[4.2] |
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.
Missing magic comment # frozen_string_literal: true.
@@ -1,4 +1,4 @@ | |||
class CreateDoorkeeperTables < ActiveRecord::Migration | |||
class CreateDoorkeeperTables < ActiveRecord::Migration[4.2] |
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.
Missing magic comment # frozen_string_literal: true.
@@ -1,4 +1,4 @@ | |||
class AddPasswordToUsers < ActiveRecord::Migration | |||
class AddPasswordToUsers < ActiveRecord::Migration[4.2] |
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.
Missing magic comment # frozen_string_literal: true.
@@ -1,4 +1,4 @@ | |||
class CreateUsers < ActiveRecord::Migration | |||
class CreateUsers < ActiveRecord::Migration[4.2] |
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.
Missing magic comment # frozen_string_literal: true.
@@ -48,7 +48,7 @@ def set_application | |||
end | |||
|
|||
def application_params | |||
params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes) | |||
params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes, :confidential) |
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. [98/80]
@@ -48,7 +48,8 @@ def set_application | |||
end | |||
|
|||
def application_params | |||
params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes) | |||
params.require(:doorkeeper_application) | |||
.permit(:name, :redirect_uri, :scopes, :confidential) |
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.
Place the . on the previous line, together with the method call receiver.
@@ -48,7 +48,8 @@ def set_application | |||
end | |||
|
|||
def application_params | |||
params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes) | |||
params.require(:doorkeeper_application) | |||
.permit(:name, :redirect_uri, :scopes, :confidential) |
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.
Place the . on the previous line, together with the method call receiver.
9cfaee6
to
6cadbc8
Compare
Ignoring the coverage decrease because the existing lines that became uncovered are guarded for Rails 5 only and the test envs that never reach it are 4.x |
@nbulaj any comments on this work? |
@f3ndot I will take a look at it a little bit later - currently I do not have much time |
@nbulaj Take all the time you need, no rush. |
14903a4
to
54e8345
Compare
Hi @f3ndot . Could you please sync this branch with the master and squash the commits to a single one? I will take a look at this this week. |
👋 @nbulaj I'll take care of this Friday or on the weekend |
Thanks for your work @f3ndot. I'm looking forward to this becoming available soon. I tried testing this on my application but had an issue with database migration (the new column was not recognised for some reason). I will give it another try. |
Add Application#confidential Add dummy migration for Application#confidential Because Dummy app is now Rails 5.1, the old migrations' ancestor class needed to be explicitly the 4.2 variety. Expose app confidentiality in views & controllers Allow public applications to be found if secret is blank Don't use #client_via_uid fallback on Password strategy Since credentials will only contain UID when a public application is calling, the fallback method of finding by UID alone is dead code. Private apps are not allowed to be identified by UID alone.
6cadbc8
to
de4618c
Compare
@nbulaj all set! |
if credentials | ||
server.client | ||
elsif parameters[:client_id] | ||
server.client_via_uid |
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.
Is it OK that we removed client_via_uid
and introduced only client
?
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.
I think so, because this method was originally returning a client if:
- Valid credentials aka good
client_id
andclient_secret
- Only good
client_id
set
Because credentials
now returns true if good client_id
and client_secret
or only good client_id
set this private method is redundant. We can trust the server.client
to be set when either (1) or (2) is satisfied.
Hi @f3ndot . I've added upgrade notes to the Migration from old versions doc and introduced generator for generating migration for projects with old Doorkeeper version. |
Summary
This PR aims to solve #999 and comply with Section 8.5 of draft-ietf-oauth-native-apps-12:
Public vs Private Clients
The original OAuth 2 RFC makes a definition between public & private clients (Section 2.1). To this end, along with modeling industry best practice,
Doorkeeper::Application
now has a#confidential?
attribute. The developer must decide when creating an application, whether it is to be a confidential or non-confidential client.This allows Doorkeeper to behave differently when receiving an authentication request, depending on the identified client and its confidentiality.
This decision maintains security by forcing the presence of a
client_secret
when the developer intends their app only to be used in secure environments.For backwards compatibility, an
UPGRADING.md
document should be written asking developers to generate a migration that adds theconfidential
column. To be safe by default, the default value/backfill should be a confidential app.What's Next
I omitted some important work to keep this PR simple:
Doorkeeper::AccessToken
for whether or not it was created under authenticated means (confidential app) or just identified (public app). A future PR should do this so it is clear to the developer that that Access Token's application relationship is guaranteed or just claimed.