defmodule WhoNeedHelp.SocialOAuthTest do use ExUnit.Case, async: true alias WhoNeedHelp.SocialOAuth.GithubStrategy test "GitHub authorization uses state and PKCE without requesting extra scopes" do assert {:ok, %{url: url, session_params: session_params}} = GithubStrategy.authorize_url( client_id: "client", client_secret: "secret", redirect_uri: "https://example.test/auth/social/github/callback" ) uri = URI.parse(url) params = URI.decode_query(uri.query) assert uri.host == "github.com" assert params["client_id"] == "client" assert params["redirect_uri"] == "https://example.test/auth/social/github/callback" assert params["state"] == session_params.state assert params["code_challenge_method"] == "S256" assert is_binary(session_params.code_verifier) assert is_binary(session_params.code_challenge) refute Map.has_key?(params, "scope") end test "normalizes only the public GitHub identity fields" do assert {:ok, normalized} = GithubStrategy.normalize([], %{ "id" => 123, "login" => "alice", "name" => "Alice", "html_url" => "https://github.com/alice", "avatar_url" => "https://avatars.githubusercontent.com/u/123", "access_token" => "must-not-leak" }) assert normalized["sub"] == 123 assert normalized["preferred_username"] == "alice" refute Map.has_key?(normalized, "access_token") refute Map.has_key?(normalized, "email") end end