DEV: Add integration specs for Discord, Facebook and Twitter logins (#18941)
Internal topic: t/82084.
This commit is contained in:
parent
729c8cf068
commit
4cd07627d5
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue