Delete password flow
This commit is contained in:
parent
e5932968fd
commit
2be932ceff
5 changed files with 30 additions and 158 deletions
|
|
@ -1,21 +0,0 @@
|
|||
Feature: Access protected resources using password flow
|
||||
Background:
|
||||
Given a user with username "kent"
|
||||
And all scopes exist
|
||||
|
||||
Scenario: Invalid credentials to token endpoint
|
||||
When I register a new client
|
||||
And I send a post request from that client to the password flow token endpoint using invalid credentials
|
||||
Then I should receive an "invalid_grant" error
|
||||
|
||||
Scenario: Invalid bearer tokens sent
|
||||
When I register a new client
|
||||
And I send a post request from that client to the password flow token endpoint using "kent"'s credentials
|
||||
And I use invalid bearer tokens to access user info
|
||||
Then I should receive an "invalid_token" error
|
||||
|
||||
Scenario: Valid password flow
|
||||
When I register a new client
|
||||
And I send a post request from that client to the password flow token endpoint using "kent"'s credentials
|
||||
And I use received valid bearer tokens to access user info
|
||||
Then I should receive "kent"'s id, username, and email
|
||||
30
features/step_definitions/oidc_common_steps.rb
Normal file
30
features/step_definitions/oidc_common_steps.rb
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
Given(/^all scopes exist$/) do
|
||||
Api::OpenidConnect::Scope.find_or_create_by(name: "openid")
|
||||
Api::OpenidConnect::Scope.find_or_create_by(name: "read")
|
||||
end
|
||||
|
||||
When /^I register a new client$/ do
|
||||
post api_openid_connect_clients_path, redirect_uris: ["http://localhost:3000"], client_name: "diaspora client"
|
||||
end
|
||||
|
||||
When /^I use received valid bearer tokens to access user info$/ do
|
||||
access_token_json = JSON.parse(last_response.body)
|
||||
get api_v0_user_path, access_token: access_token_json["access_token"]
|
||||
end
|
||||
|
||||
When /^I use invalid bearer tokens to access user info$/ do
|
||||
get api_v0_user_path, access_token: SecureRandom.hex(32)
|
||||
end
|
||||
|
||||
Then /^I should receive "([^\"]*)"'s id, username, and email$/ do |username|
|
||||
user_info_json = JSON.parse(last_response.body)
|
||||
user = User.find_by_username(username)
|
||||
expect(user_info_json["username"]).to have_content(user.username)
|
||||
expect(user_info_json["language"]).to have_content(user.language)
|
||||
expect(user_info_json["email"]).to have_content(user.email)
|
||||
end
|
||||
|
||||
Then /^I should receive an "([^\"]*)" error$/ do |error_message|
|
||||
user_info_json = JSON.parse(last_response.body)
|
||||
expect(user_info_json["error"]).to have_content(error_message)
|
||||
end
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
Given(/^all scopes exist$/) do
|
||||
Api::OpenidConnect::Scope.find_or_create_by(name: "openid")
|
||||
Api::OpenidConnect::Scope.find_or_create_by(name: "read")
|
||||
end
|
||||
|
||||
When /^I register a new client$/ do
|
||||
post api_openid_connect_clients_path, redirect_uris: ["http://localhost:3000"], client_name: "diaspora client"
|
||||
end
|
||||
|
||||
Given /^I send a post request from that client to the password flow token endpoint using "([^\"]*)"'s credentials$/ do |username|
|
||||
client_json = JSON.parse(last_response.body)
|
||||
user = User.find_by(username: username)
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: user.username,
|
||||
password: "password", # Password has been hard coded as all test accounts seem to have a password of "password"
|
||||
client_id: client_json["o_auth_application"]["client_id"],
|
||||
client_secret: client_json["o_auth_application"]["client_secret"],
|
||||
scope: "read"
|
||||
end
|
||||
|
||||
Given /^I send a post request from that client to the password flow token endpoint using invalid credentials$/ do
|
||||
client_json = JSON.parse(last_response.body)
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob", password: "wrongpassword",
|
||||
client_id: client_json["o_auth_application"]["client_id"],
|
||||
client_secret: client_json["o_auth_application"]["client_secret"],
|
||||
scope: "read"
|
||||
end
|
||||
|
||||
When /^I use received valid bearer tokens to access user info$/ do
|
||||
access_token_json = JSON.parse(last_response.body)
|
||||
get api_v0_user_path, access_token: access_token_json["access_token"]
|
||||
end
|
||||
|
||||
When /^I use invalid bearer tokens to access user info$/ do
|
||||
get api_v0_user_path, access_token: SecureRandom.hex(32)
|
||||
end
|
||||
|
||||
Then /^I should receive "([^\"]*)"'s id, username, and email$/ do |username|
|
||||
user_info_json = JSON.parse(last_response.body)
|
||||
user = User.find_by_username(username)
|
||||
expect(user_info_json["username"]).to have_content(user.username)
|
||||
expect(user_info_json["language"]).to have_content(user.language)
|
||||
expect(user_info_json["email"]).to have_content(user.email)
|
||||
end
|
||||
|
||||
Then /^I should receive an "([^\"]*)" error$/ do |error_message|
|
||||
user_info_json = JSON.parse(last_response.body)
|
||||
expect(user_info_json["error"]).to have_content(error_message)
|
||||
end
|
||||
|
|
@ -17,8 +17,6 @@ module Api
|
|||
|
||||
def handle_flows(o_auth_app, req, res)
|
||||
case req.grant_type
|
||||
when :password
|
||||
handle_password_flow(o_auth_app, req, res)
|
||||
when :refresh_token
|
||||
handle_refresh_flow(req, res)
|
||||
when :authorization_code
|
||||
|
|
@ -34,20 +32,6 @@ module Api
|
|||
end
|
||||
end
|
||||
|
||||
def handle_password_flow(o_auth_app, req, res)
|
||||
user = User.find_for_database_authentication(username: req.username)
|
||||
if user
|
||||
if user.valid_password?(req.password)
|
||||
auth = OpenidConnect::Authorization.find_or_create_by(o_auth_application: o_auth_app, user: user)
|
||||
build_auth_and_access_token(auth, req, res)
|
||||
else
|
||||
req.invalid_grant!
|
||||
end
|
||||
else
|
||||
req.invalid_grant! # TODO: Change to user login: Perhaps redirect_to login_path?
|
||||
end
|
||||
end
|
||||
|
||||
def build_auth_and_access_token(auth, req, res)
|
||||
scope_list = req.scope.map { |scope_name|
|
||||
OpenidConnect::Scope.find_by(name: scope_name).tap do |scope|
|
||||
|
|
|
|||
|
|
@ -75,79 +75,6 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
|
|||
end
|
||||
end
|
||||
|
||||
describe "the password grant type" do
|
||||
context "when the username field is missing" do
|
||||
it "should return an invalid request error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", password: "bluepin7",
|
||||
client_id: client.client_id, client_secret: client.client_secret, scope: "read"
|
||||
expect(response.body).to include "'username' required"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the password field is missing" do
|
||||
it "should return an invalid request error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob",
|
||||
client_id: client.client_id, client_secret: client.client_secret, scope: "read"
|
||||
expect(response.body).to include "'password' required"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the username does not match an existing user" do
|
||||
it "should return an invalid request error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "randomnoexist",
|
||||
password: "bluepin7", client_id: client.client_id, client_secret: client.client_secret, scope: "read"
|
||||
expect(response.body).to include "invalid_grant"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the password is invalid" do
|
||||
it "should return an invalid request error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob",
|
||||
password: "wrongpassword", client_id: client.client_id, client_secret: client.client_secret, scope: "read"
|
||||
expect(response.body).to include "invalid_grant"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the client_secret doesn't match" do
|
||||
it "should return an invalid client error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob",
|
||||
password: "bluepin7", client_id: client.client_id, client_secret: "client.client_secret", scope: "read"
|
||||
expect(response.body).to include "invalid_client"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the request is valid" do
|
||||
it "should return an access token" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob",
|
||||
password: "bluepin7", client_id: client.client_id, client_secret: client.client_secret, scope: "read"
|
||||
json = JSON.parse(response.body)
|
||||
expect(json.keys).to include "expires_in"
|
||||
expect(json["access_token"].length).to eq(64)
|
||||
expect(json["token_type"]).to eq("bearer")
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are duplicate fields" do
|
||||
it "should return an invalid request error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob", password: "bluepin7",
|
||||
username: "bob", password: "bluepin6", client_id: client.client_id, client_secret: client.client_secret,
|
||||
scope: "read"
|
||||
expect(response.body).to include "invalid_grant"
|
||||
end
|
||||
end
|
||||
|
||||
context "when the client is unregistered" do
|
||||
it "should return an error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "password", username: "bob",
|
||||
password: "bluepin7", client_id: SecureRandom.hex(16).to_s, client_secret: client.client_secret,
|
||||
scope: "read"
|
||||
expect(response.body).to include "invalid_client"
|
||||
end
|
||||
end
|
||||
# TODO: Support a way to prevent brute force attacks using rate-limitation
|
||||
# as specified by RFC 6749 4.3.2 Access Token Request
|
||||
end
|
||||
|
||||
describe "an unsupported grant type" do
|
||||
it "should return an unsupported grant type error" do
|
||||
post api_openid_connect_access_tokens_path, grant_type: "noexistgrant", username: "bob",
|
||||
|
|
|
|||
Loading…
Reference in a new issue