X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/3422bb541db16f6b6e7374689e82e982bd78664b..3adb697385824cb7b7208825d9ba3535d8f4d67f:/test/integration/oauth2_test.rb diff --git a/test/integration/oauth2_test.rb b/test/integration/oauth2_test.rb index 81f12f7cb..3fe59cbdd 100644 --- a/test/integration/oauth2_test.rb +++ b/test/integration/oauth2_test.rb @@ -1,4 +1,5 @@ require "test_helper" +require "jwt" class OAuth2Test < ActionDispatch::IntegrationTest def test_oauth2 @@ -12,7 +13,8 @@ class OAuth2Test < ActionDispatch::IntegrationTest token = request_token(client, code) - test_token(token, user, client) + assert_equal "read_prefs", token["scope"] + test_token(token["access_token"], user, client) end def test_oauth2_oob @@ -30,7 +32,8 @@ class OAuth2Test < ActionDispatch::IntegrationTest token = request_token(client, code) - test_token(token, user, client) + assert_equal "read_prefs", token["scope"] + test_token(token["access_token"], user, client) end def test_oauth2_pkce_plain @@ -46,7 +49,8 @@ class OAuth2Test < ActionDispatch::IntegrationTest token = request_token(client, code, verifier) - test_token(token, user, client) + assert_equal "read_prefs", token["scope"] + test_token(token["access_token"], user, client) end def test_oauth2_pkce_s256 @@ -62,19 +66,97 @@ class OAuth2Test < ActionDispatch::IntegrationTest token = request_token(client, code, verifier) - test_token(token, user, client) + assert_equal "read_prefs", token["scope"] + test_token(token["access_token"], user, client) + end + + def test_openid_connect + user = create(:user) + client = create(:oauth_application, :redirect_uri => "https://some.web.app.example.org/callback", :scopes => "openid read_prefs") + state = SecureRandom.urlsafe_base64(16) + verifier = SecureRandom.urlsafe_base64(48) + challenge = Base64.urlsafe_encode64(Digest::SHA256.digest(verifier), :padding => false) + + authorize_client(user, client, :state => state, :code_challenge => challenge, :code_challenge_method => "S256", :scope => "openid read_prefs") + assert_response :redirect + code = validate_redirect(client, state) + + token = request_token(client, code, verifier) + + assert_equal "openid read_prefs", token["scope"] + + access_token = token["access_token"] + assert_not_nil access_token + + id_token = token["id_token"] + assert_not_nil id_token + + data, _headers = JWT.decode id_token, nil, true, { + :algorithm => [Doorkeeper::OpenidConnect.signing_algorithm.to_s], + :verify_iss => true, + :iss => "#{Settings.server_protocol}://#{Settings.server_url}", + :verify_sub => true, + :sub => user.id, + :verify_aud => true, + :aud => client.uid + } do |headers, _payload| + kid = headers["kid"] + get oauth_discovery_keys_path + keys = response.parsed_body["keys"] + jwk = keys&.detect { |e| e["kid"] == kid } + jwk && JWT::JWK::RSA.import(jwk).public_key + end + + assert_equal user.id.to_s, data["sub"] + assert_not data.key?("preferred_username") + + get oauth_userinfo_path + assert_response :unauthorized + + auth_header = bearer_authorization_header(access_token) + get oauth_userinfo_path, :headers => auth_header + assert_response :success + + userinfo = response.parsed_body + + assert_not_nil userinfo + assert_equal user.id.to_s, userinfo["sub"] + assert_equal user.display_name, userinfo["preferred_username"] + end + + def test_openid_discovery + get oauth_discovery_provider_path + assert_response :success + openid_config = response.parsed_body + + assert_equal "#{Settings.server_protocol}://#{Settings.server_url}", openid_config["issuer"] + + assert_equal oauth_authorization_path, URI(openid_config["authorization_endpoint"]).path + assert_equal oauth_token_path, URI(openid_config["token_endpoint"]).path + assert_equal oauth_userinfo_path, URI(openid_config["userinfo_endpoint"]).path + assert_equal oauth_discovery_keys_path, URI(openid_config["jwks_uri"]).path + end + + def test_openid_key + get oauth_discovery_keys_path + assert_response :success + key_info = response.parsed_body + assert key_info.key?("keys") + assert_equal 1, key_info["keys"].size + assert_equal Doorkeeper::OpenidConnect.signing_key.kid, key_info["keys"][0]["kid"] end private def authorize_client(user, client, options = {}) - options = options.merge(:client_id => client.uid, - :redirect_uri => client.redirect_uri, - :response_type => "code", - :scope => "read_prefs") + options = { + :client_id => client.uid, + :redirect_uri => client.redirect_uri, + :response_type => "code", + :scope => "read_prefs" + }.merge(options) get oauth_authorization_path(options) - assert_response :redirect assert_redirected_to login_path(:referer => request.fullpath) post login_path(:username => user.email, :password => "test") @@ -135,9 +217,8 @@ class OAuth2Test < ActionDispatch::IntegrationTest assert_response :success token = response.parsed_body assert_equal "Bearer", token["token_type"] - assert_equal "read_prefs", token["scope"] - token["access_token"] + token end def test_token(token, user, client)