From 7b80a7408da614fd78f67da46a7e822271aab3cc Mon Sep 17 00:00:00 2001 From: theworldbright <kent@kentshikama.com> Date: Thu, 16 Jul 2015 17:12:53 +0900 Subject: [PATCH] Add integration tests for implicit flow Squashed commits: [d5001fe] Refactor [8d8a23f] Add test for when authorization is denied [659fc56] Adjust password flow integration test --- app/models/openid_connect/authorization.rb | 1 + app/models/user.rb | 4 -- ...150613202109_create_o_auth_applications.rb | 4 -- ...50614134031_create_o_auth_access_tokens.rb | 2 +- features/desktop/oauth_password_flow.feature | 6 +-- features/desktop/oidc_implicit_flow.feature | 26 ++++++++++++ .../step_definitions/implicit_flow_steps.rb | 41 +++++++++++++++++++ ...openid_steps.rb => password_flow_steps.rb} | 6 +-- lib/openid_connect/token_endpoint.rb | 10 ++--- public/docs/v0/index.html | 17 -------- public/docs/v0/style.css | 5 --- .../authorizations_controller_spec.rb | 2 + 12 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 features/desktop/oidc_implicit_flow.feature create mode 100644 features/step_definitions/implicit_flow_steps.rb rename features/step_definitions/{openid_steps.rb => password_flow_steps.rb} (88%) delete mode 100644 public/docs/v0/index.html delete mode 100644 public/docs/v0/style.css diff --git a/app/models/openid_connect/authorization.rb b/app/models/openid_connect/authorization.rb index c91aa2cc66..abbe8c090e 100644 --- a/app/models/openid_connect/authorization.rb +++ b/app/models/openid_connect/authorization.rb @@ -4,6 +4,7 @@ class OpenidConnect::Authorization < ActiveRecord::Base validates :user, presence: true validates :o_auth_application, presence: true + validates :user, uniqueness: {scope: :o_auth_application} has_many :scopes, through: :authorization_scopes has_many :o_auth_access_tokens, dependent: :destroy diff --git a/app/models/user.rb b/app/models/user.rb index 28fa845a2d..3766456bca 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -602,10 +602,6 @@ class User < ActiveRecord::Base end end - def find_authorization_by_client_id(client_id) - OpenidConnect::Authorization.find_by_client_id_and_user client_id, self - end - private def clearable_fields diff --git a/db/migrate/20150613202109_create_o_auth_applications.rb b/db/migrate/20150613202109_create_o_auth_applications.rb index c5f44bfef1..0e36a70062 100644 --- a/db/migrate/20150613202109_create_o_auth_applications.rb +++ b/db/migrate/20150613202109_create_o_auth_applications.rb @@ -10,8 +10,4 @@ class CreateOAuthApplications < ActiveRecord::Migration t.timestamps null: false end end - - def self.down - drop_table :o_auth_applications - end end diff --git a/db/migrate/20150614134031_create_o_auth_access_tokens.rb b/db/migrate/20150614134031_create_o_auth_access_tokens.rb index 5084d61e5a..8bd619142b 100644 --- a/db/migrate/20150614134031_create_o_auth_access_tokens.rb +++ b/db/migrate/20150614134031_create_o_auth_access_tokens.rb @@ -1,5 +1,5 @@ class CreateOAuthAccessTokens < ActiveRecord::Migration - def self.up + def change create_table :o_auth_access_tokens do |t| t.belongs_to :authorization, index: true t.string :token diff --git a/features/desktop/oauth_password_flow.feature b/features/desktop/oauth_password_flow.feature index 2829ac296a..7fa59c4fd7 100644 --- a/features/desktop/oauth_password_flow.feature +++ b/features/desktop/oauth_password_flow.feature @@ -4,17 +4,17 @@ Feature: Access protected resources using password flow Scenario: Invalid credentials to token endpoint When I register a new client - And I send a post request from that client to the token endpoint using invalid credentials + 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 token endpoint using "kent"'s credentials + 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 token endpoint using "kent"'s credentials + 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 diff --git a/features/desktop/oidc_implicit_flow.feature b/features/desktop/oidc_implicit_flow.feature new file mode 100644 index 0000000000..92bf59d5a9 --- /dev/null +++ b/features/desktop/oidc_implicit_flow.feature @@ -0,0 +1,26 @@ +@javascript +Feature: Access protected resources using implicit flow + Background: + Given a user with username "kent" + And the OpenID scope exists + + Scenario: Invalid client id to auth endpoint + When I register a new client + And I send a post request from that client to the implicit flow authorization endpoint using a invalid client id + And I sign in as "kent@kent.kent" + Then I should see an "bad_request" error + + Scenario: Application is denied authorization + When I register a new client + And I send a post request from that client to the implicit flow authorization endpoint + And I sign in as "kent@kent.kent" + And I deny authorization to the client + Then I should not see any tokens in the redirect url + + Scenario: Application is authorized + When I register a new client + And I send a post request from that client to the implicit flow authorization endpoint + And I sign in as "kent@kent.kent" + And I give my consent and authorize the client + And I parse the bearer tokens and use it to access user info + Then I should receive "kent"'s id, username, and email diff --git a/features/step_definitions/implicit_flow_steps.rb b/features/step_definitions/implicit_flow_steps.rb new file mode 100644 index 0000000000..2ea9fdfa0b --- /dev/null +++ b/features/step_definitions/implicit_flow_steps.rb @@ -0,0 +1,41 @@ +Given(/^the OpenID scope exists$/) do + OpenidConnect::Scope.create(name: "openid") +end + +Given /^I send a post request from that client to the implicit flow authorization endpoint$/ do + client_json = JSON.parse(last_response.body) + auth_endpoint_url = "/openid_connect/authorizations/new" + visit auth_endpoint_url + "?client_id=" + client_json["o_auth_application"]["client_id"] + "&redirect_uri=" + "http://localhost:3000" + + "&response_type=id_token token" + "&scope=openid" + "&nonce=hello" + "&state=hi" +end + +Given /^I send a post request from that client to the implicit flow authorization endpoint using a invalid client id/ do + auth_endpoint_url = "/openid_connect/authorizations/new" + visit auth_endpoint_url + "?client_id=randomid" + "&redirect_uri=" + "http://localhost:3000" + + "&response_type=id_token token" + "&scope=openid" + "&nonce=hello" + "&state=hi" +end + +When /^I give my consent and authorize the client$/ do + click_button "Approve" +end + +When /^I deny authorization to the client$/ do + click_button "Deny" +end + +Then /^I should not see any tokens in the redirect url$/ do + access_token = current_url[/(?<=access_token=)[^&]+/] + id_token = current_url[/(?<=access_token=)[^&]+/] + expect(access_token).to eq(nil) + expect(id_token).to eq(nil) +end + +When /^I parse the bearer tokens and use it to access user info$/ do + access_token = current_url[/(?<=access_token=)[^&]+/] + user_info_endpoint_url = "/api/v0/user/" + get user_info_endpoint_url, access_token: access_token +end + +Then /^I should see an "([^\"]*)" error$/ do |error_message| + expect(page).to have_content(error_message) +end diff --git a/features/step_definitions/openid_steps.rb b/features/step_definitions/password_flow_steps.rb similarity index 88% rename from features/step_definitions/openid_steps.rb rename to features/step_definitions/password_flow_steps.rb index 3aa5bdf36b..2dcbf7b3f1 100644 --- a/features/step_definitions/openid_steps.rb +++ b/features/step_definitions/password_flow_steps.rb @@ -1,9 +1,9 @@ When /^I register a new client$/ do client_registration_url = "/openid_connect/clients" - post client_registration_url, redirect_uris: ["http://localhost:3000"] # Not actually used + post client_registration_url, redirect_uris: ["http://localhost:3000"] end -Given /^I send a post request from that client to the token endpoint using "([^\"]*)"'s credentials$/ do |username| +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) token_endpoint_url = "/openid_connect/access_tokens" @@ -13,7 +13,7 @@ Given /^I send a post request from that client to the token endpoint using "([^\ client_secret: client_json["o_auth_application"]["client_secret"] end -Given /^I send a post request from that client to the token endpoint using invalid credentials$/ do +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) token_endpoint_url = "/openid_connect/access_tokens" post token_endpoint_url, grant_type: "password", username: "bob", password: "wrongpassword", diff --git a/lib/openid_connect/token_endpoint.rb b/lib/openid_connect/token_endpoint.rb index a19d7766c1..116a5c67b4 100644 --- a/lib/openid_connect/token_endpoint.rb +++ b/lib/openid_connect/token_endpoint.rb @@ -7,17 +7,17 @@ module OpenidConnect @app = Rack::OAuth2::Server::Token.new do |req, res| o_auth_app = retrieve_client(req) if app_valid?(o_auth_app, req) - handle_flows(req, res) + handle_flows(o_auth_app, req, res) else req.invalid_client! end end end - def handle_flows(req, res) + def handle_flows(o_auth_app, req, res) case req.grant_type when :password - handle_password_flow(req, res) + handle_password_flow(o_auth_app, req, res) when :refresh_token handle_refresh_flow(req, res) else @@ -25,11 +25,11 @@ module OpenidConnect end end - def handle_password_flow(req, res) + 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(req.client_id, user) + auth = OpenidConnect::Authorization.find_or_create_by(o_auth_application: o_auth_app, user: user) res.access_token = auth.create_access_token else req.invalid_grant! diff --git a/public/docs/v0/index.html b/public/docs/v0/index.html deleted file mode 100644 index 08b6b913fe..0000000000 --- a/public/docs/v0/index.html +++ /dev/null @@ -1,17 +0,0 @@ -<!DOCTYPE html> -<html lang="en-US"> - <head> - <title>Documentation for v0</title> - <link href="v2/style.css" media="screen" rel="stylesheet" type="text/css"> - </head> - <body> - <div id="container"> - <div id="operations"> - <h3>API Operations</h3> - </div> - <div id="content"> - <h1>Documentation for v0</h1> - </div> - </div> - </body> -</html> diff --git a/public/docs/v0/style.css b/public/docs/v0/style.css deleted file mode 100644 index ea6e1ce9cb..0000000000 --- a/public/docs/v0/style.css +++ /dev/null @@ -1,5 +0,0 @@ -body {margin: 0; background-color: #fff; color: #000; font-family: Arial,sans-serif;} -content {margin-left: 200px;} -content h1 {text-align: center;} -operations {float: left; width: 200px; border-right: 1px solid #ccc;} -operations h3 {text-align: center;} diff --git a/spec/controllers/openid_connect/authorizations_controller_spec.rb b/spec/controllers/openid_connect/authorizations_controller_spec.rb index bb597254db..1c8e3655b8 100644 --- a/spec/controllers/openid_connect/authorizations_controller_spec.rb +++ b/spec/controllers/openid_connect/authorizations_controller_spec.rb @@ -7,6 +7,8 @@ describe OpenidConnect::AuthorizationsController, type: :controller do name: "Diaspora Test Client", redirect_uris: ["http://localhost:3000/", "http://localhost/"]) end + # TODO: jhass - "Might want to setup some factories in spec/factories.rb, see factory_girl's docs." + before do sign_in :user, alice allow(@controller).to receive(:current_user).and_return(alice) -- GitLab