Project

General

Profile

Feature #1237 » 0004-Integration-test-for-2fa-auth-1237.patch

Go MAEDA, 2020-08-26 18:22

View differences:

test/integration/twofa_test.rb
1
# frozen_string_literal: true
2

  
3
# Redmine - project management software
4
# Copyright (C) 2006-2020  Jean-Philippe Lang
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19

  
20
require File.expand_path('../../test_helper', __FILE__)
21

  
22
class TwofaTest < Redmine::IntegrationTest
23
  fixtures :projects, :users, :email_addresses
24

  
25
  test "should require twofa setup when configured" do
26
    with_settings twofa: "2" do
27
      log_user('jsmith', 'jsmith')
28
      follow_redirect!
29
      assert_redirected_to "/my/twofa/totp/activate/confirm"
30
    end
31
  end
32

  
33
  test "should generate and accept backup codes" do
34
    log_user('jsmith', 'jsmith')
35
    get "/my/account"
36
    assert_response :success
37
    post "/my/twofa/totp/activate/init"
38
    assert_redirected_to "/my/twofa/totp/activate/confirm"
39
    follow_redirect!
40
    assert_response :success
41

  
42
    totp = ROTP::TOTP.new User.find_by_login('jsmith').twofa_totp_key
43
    post "/my/twofa/totp/activate", params: { twofa_code: totp.now }
44
    assert_redirected_to "/my/account"
45
    follow_redirect!
46
    assert_response :success
47
    assert_select '.flash', /Two-factor authentication successfully enabled/i
48

  
49
    post "/my/twofa/backup_codes/init"
50
    assert_redirected_to "/my/twofa/backup_codes/confirm"
51
    follow_redirect!
52
    assert_response :success
53
    assert_select 'form', /Please enter your two-factor authentication code/i
54

  
55
    post "/my/twofa/backup_codes/create", params: { twofa_code: "wrong" }
56
    assert_redirected_to "/my/twofa/backup_codes/confirm"
57
    follow_redirect!
58
    assert_response :success
59
    assert_select 'form', /Please enter your two-factor authentication code/i
60

  
61
    # prevent replay attack prevention from kicking in
62
    User.find_by_login('jsmith').update_column :twofa_totp_last_used_at, 2.minutes.ago.to_i
63

  
64
    post "/my/twofa/backup_codes/create", params: { twofa_code: totp.now }
65
    assert_redirected_to "/my/twofa/backup_codes"
66
    follow_redirect!
67
    assert_response :success
68
    assert_select ".flash", /your backup codes have been generated/i
69

  
70
    assert code = response.body.scan(/<code>([a-z0-9]{4} [a-z0-9]{4} [a-z0-9]{4})<\/code>/).flatten.first
71

  
72
    post "/logout"
73
    follow_redirect!
74
    # prevent replay attack prevention from kicking in
75
    User.find_by_login('jsmith').update_column :twofa_totp_last_used_at, 2.minutes.ago.to_i
76

  
77
    # sign in with backup code
78
    get "/login"
79
    assert_nil session[:user_id]
80
    assert_response :success
81
    post "/login", params: {
82
      username: 'jsmith',
83
      password: 'jsmith'
84
    }
85
    assert_redirected_to "/account/twofa/confirm"
86
    follow_redirect!
87

  
88
    assert_select "#login-form h3", /two-factor authentication/i
89
    post "/account/twofa", params: { twofa_code: code }
90
    assert_redirected_to "/my/page"
91
    follow_redirect!
92
    assert_response :success
93
  end
94

  
95
  test "should configure totp and require code on login" do
96
    with_settings twofa: "2" do
97
      log_user('jsmith', 'jsmith')
98
      follow_redirect!
99
      assert_redirected_to "/my/twofa/totp/activate/confirm"
100
      follow_redirect!
101

  
102
      assert key = User.find_by_login('jsmith').twofa_totp_key
103
      assert key.present?
104
      totp = ROTP::TOTP.new key
105

  
106
      post "/my/twofa/totp/activate", params: { twofa_code: '123456789' }
107
      assert_redirected_to "/my/twofa/totp/activate/confirm"
108
      follow_redirect!
109

  
110
      post "/my/twofa/totp/activate", params: { twofa_code: totp.now }
111
      assert_redirected_to "/my/account"
112

  
113
      post "/logout"
114
      follow_redirect!
115

  
116
      # prevent replay attack prevention from kicking in
117
      User.find_by_login('jsmith').update_column :twofa_totp_last_used_at, 2.minutes.ago.to_i
118

  
119
      # sign in with totp
120
      get "/login"
121
      assert_nil session[:user_id]
122
      assert_response :success
123
      post "/login", params: {
124
        username: 'jsmith',
125
        password: 'jsmith'
126
      }
127

  
128
      assert_redirected_to "/account/twofa/confirm"
129
      follow_redirect!
130

  
131
      assert_select "#login-form h3", /two-factor authentication/i
132
      post "/account/twofa", params: { twofa_code: 'wrong code' }
133
      assert_redirected_to "/account/twofa/confirm"
134
      follow_redirect!
135
      assert_select "#login-form h3", /two-factor authentication/i
136
      assert_select ".flash", /code is invalid/i
137

  
138
      post "/account/twofa", params: { twofa_code: totp.now }
139
      assert_redirected_to "/my/page"
140
      follow_redirect!
141
      assert_response :success
142
    end
143
  end
144
end
(22-22/22)