| 1 | # frozen_string_literal: true |
| 2 | |
| 3 | require "rails_helper" |
| 4 | |
| 5 | RSpec.describe "Api::V1::Oauth::Google", type: :request do |
| 6 | let(:authorize_url) { "https://api.smbcloud.xyz/v1/client/oauth/google/authorize?client_id=app" } |
| 7 | |
| 8 | # Keep the spec off the smbcloud-auth native extension: stub the URL builder |
| 9 | # and assert we forward the (validated) redirect_uri through to it. The |
| 10 | # allowlist relies on the controller's built-in defaults (code.sigit.si + |
| 11 | # localhost:5180), so no ENV juggling is needed. |
| 12 | before do |
| 13 | allow(SmbcloudAuthService).to receive(:google_authorize_url).and_return(authorize_url) |
| 14 | end |
| 15 | |
| 16 | describe "GET /api/v1/auth/google" do |
| 17 | it "redirects to the smbCloud authorize URL for an allowlisted redirect_uri" do |
| 18 | redirect_uri = "https://code.sigit.si/auth/google/callback" |
| 19 | |
| 20 | get "/api/v1/auth/google", params: { redirect_uri: redirect_uri } |
| 21 | |
| 22 | expect(SmbcloudAuthService).to have_received(:google_authorize_url).with(redirect_uri: redirect_uri) |
| 23 | expect(response).to redirect_to(authorize_url) |
| 24 | end |
| 25 | |
| 26 | it "allows the local dev origin (default port omitted)" do |
| 27 | get "/api/v1/auth/google", params: { redirect_uri: "http://localhost:5180/auth/google/callback" } |
| 28 | |
| 29 | expect(response).to have_http_status(:found) |
| 30 | end |
| 31 | |
| 32 | it "rejects a redirect_uri whose origin is not allowlisted" do |
| 33 | get "/api/v1/auth/google", params: { redirect_uri: "https://evil.example.com/auth/google/callback" } |
| 34 | |
| 35 | expect(SmbcloudAuthService).not_to have_received(:google_authorize_url) |
| 36 | expect(response).to have_http_status(:unprocessable_entity) |
| 37 | expect(response.parsed_body["message"]).to eq("Unsupported redirect_uri.") |
| 38 | end |
| 39 | |
| 40 | it "rejects a redirect_uri with the wrong callback path" do |
| 41 | get "/api/v1/auth/google", params: { redirect_uri: "https://code.sigit.si/somewhere-else" } |
| 42 | |
| 43 | expect(response).to have_http_status(:unprocessable_entity) |
| 44 | end |
| 45 | |
| 46 | it "rejects a GitHub callback path on the Google endpoint" do |
| 47 | get "/api/v1/auth/google", params: { redirect_uri: "https://code.sigit.si/auth/github/callback" } |
| 48 | |
| 49 | expect(response).to have_http_status(:unprocessable_entity) |
| 50 | end |
| 51 | |
| 52 | it "rejects a missing redirect_uri" do |
| 53 | get "/api/v1/auth/google" |
| 54 | |
| 55 | expect(response).to have_http_status(:unprocessable_entity) |
| 56 | end |
| 57 | end |
| 58 | end |