Delete password flow

This commit is contained in:
theworldbright 2015-07-31 01:46:14 +09:00
parent e5932968fd
commit 2be932ceff
5 changed files with 30 additions and 158 deletions

View file

@ -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

View 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

View file

@ -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

View file

@ -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|

View file

@ -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",