-
Notifications
You must be signed in to change notification settings - Fork 928
/
Copy pathoauth2_test.rb
170 lines (128 loc) · 5.26 KB
/
oauth2_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
require "test_helper"
class OAuth2Test < ActionDispatch::IntegrationTest
def test_oauth2
client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "read_prefs write_api read_gpx")
state = SecureRandom.urlsafe_base64(16)
authorize_client(client, :state => state)
assert_response :redirect
code = validate_redirect(client, state)
token = request_token(client, code)
test_token(token, client)
end
def test_oauth2_oob
client = create(:oauth_application, :redirect_uri => "urn:ietf:wg:oauth:2.0:oob", :scopes => "read_prefs write_api read_gpx")
authorize_client(client)
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "oauth2_authorizations/show"
m = response.body.match(%r{<code id="authorization_code">([A-Za-z0-9_-]+)</code>})
assert_not_nil m
code = m[1]
token = request_token(client, code)
test_token(token, client)
end
def test_oauth2_pkce_plain
client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "read_prefs write_api read_gpx")
state = SecureRandom.urlsafe_base64(16)
verifier = SecureRandom.urlsafe_base64(48)
challenge = verifier
authorize_client(client, :state => state, :code_challenge => challenge, :code_challenge_method => "plain")
assert_response :redirect
code = validate_redirect(client, state)
token = request_token(client, code, verifier)
test_token(token, client)
end
def test_oauth2_pkce_s256
client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "read_prefs write_api read_gpx")
state = SecureRandom.urlsafe_base64(16)
verifier = SecureRandom.urlsafe_base64(48)
challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(verifier), :padding => false)
authorize_client(client, :state => state, :code_challenge => challenge, :code_challenge_method => "S256")
assert_response :redirect
code = validate_redirect(client, state)
token = request_token(client, code, verifier)
test_token(token, client)
end
private
def authorize_client(client, options = {})
options = options.merge(:client_id => client.uid,
:redirect_uri => client.redirect_uri,
:response_type => "code",
:scope => "read_prefs")
get oauth_authorization_path(options)
assert_response :redirect
assert_redirected_to login_path(:referer => request.fullpath)
user = create(:user)
post login_path(:username => user.email, :password => "test")
follow_redirect!
assert_response :success
get oauth_authorization_path(options)
assert_response :success
assert_template "oauth2_authorizations/new"
delete oauth_authorization_path(options)
validate_deny(client, options)
post oauth_authorization_path(options)
end
def validate_deny(client, options)
if client.redirect_uri == "urn:ietf:wg:oauth:2.0:oob"
assert_response :bad_request
else
assert_response :redirect
location = URI.parse(response.location)
assert_match(/^#{Regexp.escape(client.redirect_uri)}/, location.to_s)
query = Rack::Utils.parse_query(location.query)
assert_equal "access_denied", query["error"]
assert_equal "The resource owner or authorization server denied the request.", query["error_description"]
assert_equal options[:state], query["state"]
end
end
def validate_redirect(client, state)
location = URI.parse(response.location)
assert_match(/^#{Regexp.escape(client.redirect_uri)}/, location.to_s)
query = Rack::Utils.parse_query(location.query)
assert_equal state, query["state"]
query["code"]
end
def request_token(client, code, verifier = nil)
options = {
:client_id => client.uid,
:client_secret => client.plaintext_secret,
:code => code,
:grant_type => "authorization_code",
:redirect_uri => client.redirect_uri
}
if verifier
post oauth_token_path(options)
assert_response :bad_request
options = options.merge(:code_verifier => verifier)
end
post oauth_token_path(options)
assert_response :success
token = JSON.parse(response.body)
assert_equal "Bearer", token["token_type"]
assert_equal "read_prefs", token["scope"]
token["access_token"]
end
def test_token(token, client)
get user_preferences_path
assert_response :unauthorized
auth_header = bearer_authorization_header(token)
get user_preferences_path, :headers => auth_header
assert_response :success
get user_preferences_path(:access_token => token)
assert_response :unauthorized
get user_preferences_path(:bearer_token => token)
assert_response :unauthorized
get api_trace_path(:id => 2), :headers => auth_header
assert_response :forbidden
post oauth_revoke_path(:token => token)
assert_response :forbidden
post oauth_revoke_path(:token => token,
:client_id => client.uid,
:client_secret => client.plaintext_secret)
assert_response :success
get user_preferences_path, :headers => auth_header
assert_response :unauthorized
end
end