3 class OAuth2Test < ActionDispatch::IntegrationTest
5 client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "read_prefs write_api read_gpx")
6 state = SecureRandom.urlsafe_base64(16)
8 authorize_client(client, :state => state)
9 assert_response :redirect
10 code = validate_redirect(client, state)
12 token = request_token(client, code)
14 test_token(token, client)
18 client = create(:oauth_application, :redirect_uri => "urn:ietf:wg:oauth:2.0:oob", :scopes => "read_prefs write_api read_gpx")
20 authorize_client(client)
21 assert_response :redirect
23 assert_response :success
24 assert_template "oauth2_authorizations/show"
25 m = response.body.match(%r{<code id="authorization_code">([A-Za-z0-9_-]+)</code>})
29 token = request_token(client, code)
31 test_token(token, client)
34 def test_oauth2_pkce_plain
35 client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "read_prefs write_api read_gpx")
36 state = SecureRandom.urlsafe_base64(16)
37 verifier = SecureRandom.urlsafe_base64(48)
40 authorize_client(client, :state => state, :code_challenge => challenge, :code_challenge_method => "plain")
41 assert_response :redirect
42 code = validate_redirect(client, state)
44 token = request_token(client, code, verifier)
46 test_token(token, client)
49 def test_oauth2_pkce_s256
50 client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "read_prefs write_api read_gpx")
51 state = SecureRandom.urlsafe_base64(16)
52 verifier = SecureRandom.urlsafe_base64(48)
53 challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(verifier), :padding => false)
55 authorize_client(client, :state => state, :code_challenge => challenge, :code_challenge_method => "S256")
56 assert_response :redirect
57 code = validate_redirect(client, state)
59 token = request_token(client, code, verifier)
61 test_token(token, client)
66 def authorize_client(client, options = {})
67 options = options.merge(:client_id => client.uid,
68 :redirect_uri => client.redirect_uri,
69 :response_type => "code",
70 :scope => "read_prefs")
72 get oauth_authorization_path(options)
73 assert_response :redirect
74 assert_redirected_to login_path(:referer => request.fullpath)
78 post login_path(:username => user.email, :password => "test")
80 assert_response :success
82 get oauth_authorization_path(options)
83 assert_response :success
84 assert_template "oauth2_authorizations/new"
86 delete oauth_authorization_path(options)
88 validate_deny(client, options)
90 post oauth_authorization_path(options)
93 def validate_deny(client, options)
94 if client.redirect_uri == "urn:ietf:wg:oauth:2.0:oob"
95 assert_response :bad_request
97 assert_response :redirect
98 location = URI.parse(response.location)
99 assert_match(/^#{Regexp.escape(client.redirect_uri)}/, location.to_s)
100 query = Rack::Utils.parse_query(location.query)
101 assert_equal "access_denied", query["error"]
102 assert_equal "The resource owner or authorization server denied the request.", query["error_description"]
103 assert_equal options[:state], query["state"]
107 def validate_redirect(client, state)
108 location = URI.parse(response.location)
109 assert_match(/^#{Regexp.escape(client.redirect_uri)}/, location.to_s)
110 query = Rack::Utils.parse_query(location.query)
111 assert_equal state, query["state"]
116 def request_token(client, code, verifier = nil)
118 :client_id => client.uid,
119 :client_secret => client.plaintext_secret,
121 :grant_type => "authorization_code",
122 :redirect_uri => client.redirect_uri
126 post oauth_token_path(options)
127 assert_response :bad_request
129 options = options.merge(:code_verifier => verifier)
132 post oauth_token_path(options)
133 assert_response :success
134 token = response.parsed_body
135 assert_equal "Bearer", token["token_type"]
136 assert_equal "read_prefs", token["scope"]
138 token["access_token"]
141 def test_token(token, client)
142 get user_preferences_path
143 assert_response :unauthorized
145 auth_header = bearer_authorization_header(token)
147 get user_preferences_path, :headers => auth_header
148 assert_response :success
150 get user_preferences_path(:access_token => token)
151 assert_response :unauthorized
153 get user_preferences_path(:bearer_token => token)
154 assert_response :unauthorized
156 get api_trace_path(:id => 2), :headers => auth_header
157 assert_response :forbidden
159 post oauth_revoke_path(:token => token)
160 assert_response :forbidden
162 post oauth_revoke_path(:token => token,
163 :client_id => client.uid,
164 :client_secret => client.plaintext_secret)
165 assert_response :success
167 get user_preferences_path, :headers => auth_header
168 assert_response :unauthorized