DEV: Add integration specs for Discord, Facebook and Twitter logins (#18941)

Internal topic: t/82084.
This commit is contained in:
Osama Sayegh 2022-11-11 13:50:17 +03:00 committed by GitHub
parent 729c8cf068
commit 4cd07627d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 340 additions and 0 deletions

View File

@ -0,0 +1,123 @@
# frozen_string_literal: true
describe 'Discord OAuth2' do
let(:access_token) { "discord_access_token_448" }
let(:client_id) { "abcdef11223344" }
let(:client_secret) { "adddcccdddd99922" }
let(:temp_code) { "discord_temp_code_544254" }
fab!(:user1) { Fabricate(:user) }
def setup_discord_email_stub(email, verified:)
stub_request(:get, "https://discord.com/api/users/@me")
.with(
headers: {
"Authorization" => "Bearer #{access_token}"
}
)
.to_return(
status: 200,
body: JSON.dump(
id: "80351110224678912",
username: "Nelly",
discriminator: "1337",
avatar: "8342729096ea3675442027381ff50dfe",
verified: verified,
email: email,
flags: 64,
banner: "06c16474723fe537c283b8efa61a30c8",
accent_color: 16711680,
premium_type: 1,
public_flags: 64
),
headers: {
"Content-Type" => "application/json"
}
)
end
before do
SiteSetting.enable_discord_logins = true
SiteSetting.discord_client_id = client_id
SiteSetting.discord_secret = client_secret
stub_request(:post, "https://discord.com/api/oauth2/token")
.with(
body: hash_including(
"client_id" => client_id,
"client_secret" => client_secret,
"code" => temp_code,
"grant_type" => "authorization_code",
"redirect_uri" => "http://test.localhost/auth/discord/callback"
)
)
.to_return(
status: 200,
body: Rack::Utils.build_query(
access_token: access_token,
scope: "identify emails guilds",
token_type: "Bearer",
expires_in: 604800,
refresh_token: "D43f5y0ahjqew82jZ4NViEr2YafMKhue",
),
headers: {
"Content-Type" => "application/x-www-form-urlencoded"
}
)
stub_request(:get, "https://discord.com/api/users/@me/guilds")
.with(
headers: {
"Authorization" => "Bearer #{access_token}"
}
)
.to_return(
status: 200,
body: JSON.dump(
id: "80351110224678912",
name: "1337 Krew",
icon: "8342729096ea3675442027381ff50dfe",
owner: true,
permissions: "36953089",
features: ["COMMUNITY", "NEWS"]
),
headers: {
"Content-Type" => "application/json"
}
)
end
it "doesn't sign in anyone if the email from discord is not verified" do
post "/auth/discord"
expect(response.status).to eq(302)
expect(response.location).to start_with("https://discord.com/api/oauth2/authorize")
setup_discord_email_stub(user1.email, verified: false)
post "/auth/discord/callback", params: {
state: session["omniauth.state"],
code: temp_code
}
expect(response.status).to eq(302)
expect(response.location).to eq("http://test.localhost/")
expect(session[:current_user_id]).to be_blank
end
it "signs in the user if the email from discord is verified and matches the user's email" do
post "/auth/discord"
expect(response.status).to eq(302)
expect(response.location).to start_with("https://discord.com/api/oauth2/authorize")
setup_discord_email_stub(user1.email, verified: true)
post "/auth/discord/callback", params: {
state: session["omniauth.state"],
code: temp_code
}
expect(response.status).to eq(302)
expect(response.location).to eq("http://test.localhost/")
expect(session[:current_user_id]).to eq(user1.id)
end
end

View File

@ -0,0 +1,97 @@
# frozen_string_literal: true
describe 'Facebook OAuth2' do
let(:access_token) { "facebook_access_token_448" }
let(:app_id) { "432489234823984" }
let(:app_secret) { "adddcccdddd99922" }
let(:temp_code) { "facebook_temp_code_544254" }
let(:appsecret_proof) { OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, app_secret, access_token) }
fab!(:user1) { Fabricate(:user) }
def setup_facebook_email_stub(email:)
body = {
id: "4923489839597234",
name: "Robot Lizard",
first_name: "Robot",
last_name: "Lizard",
}
body[:email] = email if email
stub_request(:get, "https://graph.facebook.com/v5.0/me?appsecret_proof=#{appsecret_proof}&fields=name,first_name,last_name,email")
.with(
headers: {
"Authorization" => "OAuth #{access_token}"
}
)
.to_return(
status: 200,
body: JSON.dump(body),
headers: {
"Content-Type" => "application/json"
}
)
end
before do
SiteSetting.enable_facebook_logins = true
SiteSetting.facebook_app_id = app_id
SiteSetting.facebook_app_secret = app_secret
stub_request(:post, "https://graph.facebook.com/v5.0/oauth/access_token")
.with(
body: hash_including(
"client_id" => app_id,
"client_secret" => app_secret,
"code" => temp_code,
"grant_type" => "authorization_code",
"redirect_uri" => "http://test.localhost/auth/facebook/callback"
)
)
.to_return(
status: 200,
body: Rack::Utils.build_query(
access_token: access_token,
scope: "email",
token_type: "Bearer",
),
headers: {
"Content-Type" => "application/x-www-form-urlencoded"
}
)
end
it "signs in the user if the API response from facebook includes an email (implies it's verified) and the email matches an existing user's" do
post "/auth/facebook"
expect(response.status).to eq(302)
expect(response.location).to start_with("https://www.facebook.com/v5.0/dialog/oauth")
setup_facebook_email_stub(email: user1.email)
post "/auth/facebook/callback", params: {
state: session["omniauth.state"],
code: temp_code
}
expect(response.status).to eq(302)
expect(response.location).to eq("http://test.localhost/")
expect(session[:current_user_id]).to eq(user1.id)
end
it "doesn't sign in anyone if the API response from facebook doesn't include an email (implying the user's email on facebook isn't verified)" do
post "/auth/facebook"
expect(response.status).to eq(302)
expect(response.location).to start_with("https://www.facebook.com/v5.0/dialog/oauth")
setup_facebook_email_stub(email: nil)
post "/auth/facebook/callback", params: {
state: session["omniauth.state"],
code: temp_code
}
expect(response.status).to eq(302)
expect(response.location).to eq("http://test.localhost/")
expect(session[:current_user_id]).to be_blank
end
end

View File

@ -0,0 +1,120 @@
# frozen_string_literal: true
describe 'Twitter OAuth 1.0a' do
let(:access_token) { "twitter_access_token_448" }
let(:consumer_key) { "abcdef11223344" }
let(:consumer_secret) { "adddcccdddd99922" }
let(:oauth_token_secret) { "twitter_temp_code_544254" }
fab!(:user1) { Fabricate(:user) }
def setup_twitter_email_stub(email:)
body = {
contributors_enabled: true,
created_at: "Sat May 09 17:58:22 +0000 2009",
default_profile: false,
default_profile_image: false,
description: "I taught your phone that thing you like. The Mobile Partner Engineer @Twitter. ",
favourites_count: 588,
follow_request_sent: nil,
followers_count: 10625,
following: nil,
friends_count: 1181,
geo_enabled: true,
id: 38895958,
id_str: "38895958",
is_translator: false,
lang: "en",
listed_count: 190,
location: "San Francisco",
name: "Sean Cook",
notifications: nil,
profile_background_color: "1A1B1F",
profile_background_image_url: "http://a0.twimg.com/profile_background_images/495742332/purty_wood.png",
profile_background_image_url_https: "https://si0.twimg.com/profile_background_images/495742332/purty_wood.png",
profile_background_tile: true,
profile_image_url: "http://a0.twimg.com/profile_images/1751506047/dead_sexy_normal.JPG",
profile_image_url_https: "https://si0.twimg.com/profile_images/1751506047/dead_sexy_normal.JPG",
profile_link_color: "2FC2EF",
profile_sidebar_border_color: "181A1E",
profile_sidebar_fill_color: "252429",
profile_text_color: "666666",
profile_use_background_image: true,
protected: false,
screen_name: "theSeanCook",
show_all_inline_media: true,
statuses_count: 2609,
time_zone: "Pacific Time (US & Canada)",
url: nil,
utc_offset: -28800,
verified: true,
email: email
}
stub_request(:get, "https://api.twitter.com/1.1/account/verify_credentials.json")
.with(
query: {
include_email: true,
include_entities: false,
skip_status: true
}
)
.to_return(status: 200, body: JSON.dump(body))
end
before do
SiteSetting.enable_twitter_logins = true
SiteSetting.twitter_consumer_key = consumer_key
SiteSetting.twitter_consumer_secret = consumer_secret
stub_request(:post, "https://api.twitter.com/oauth/request_token")
.to_return(
status: 200,
body: Rack::Utils.build_query(
oauth_token: access_token,
oauth_token_secret: oauth_token_secret,
oauth_callback_confirmed: true
),
headers: {
"Content-Type" => "application/x-www-form-urlencoded"
}
)
stub_request(:post, "https://api.twitter.com/oauth/access_token")
.to_return(
status: 200,
body: Rack::Utils.build_query(
oauth_token: access_token,
oauth_token_secret: oauth_token_secret,
user_id: "43423432422",
screen_name: "twitterapi"
)
)
end
it "signs in the user if the API response from twitter includes an email (implies it's verified) and the email matches an existing user's" do
post "/auth/twitter"
expect(response.status).to eq(302)
expect(response.location).to start_with("https://api.twitter.com/oauth/authenticate")
setup_twitter_email_stub(email: user1.email)
post "/auth/twitter/callback", params: { state: session["omniauth.state"] }
expect(response.status).to eq(302)
expect(response.location).to eq("http://test.localhost/")
expect(session[:current_user_id]).to eq(user1.id)
end
it "doesn't sign in anyone if the API response from twitter doesn't include an email (implying the user's email on twitter isn't verified)" do
post "/auth/twitter"
expect(response.status).to eq(302)
expect(response.location).to start_with("https://api.twitter.com/oauth/authenticate")
setup_twitter_email_stub(email: nil)
post "/auth/twitter/callback", params: { state: session["omniauth.state"] }
expect(response.status).to eq(302)
expect(response.location).to eq("http://test.localhost/")
expect(session[:current_user_id]).to be_blank
end
end