GitHub OAuth helpers
at main 76 lines 2.7 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Thomas Gazagnaire. All rights reserved. 3 SPDX-License-Identifier: MIT 4 ---------------------------------------------------------------------------*) 5 6open Crowbar 7 8let () = Crypto_rng_unix.use_default () 9 10(* Test that authorization_url always produces valid URLs *) 11let test_authorization_url_valid client_id callback_url state scope = 12 let url = 13 Github_oauth.authorization_url ~client_id ~callback_url ~state ~scope 14 in 15 (* Should always start with https://github.com *) 16 check (String.length url > 0); 17 check (String.sub url 0 8 = "https://") 18 19(* Test that exchange_request_body produces valid JSON *) 20let test_exchange_body_valid client_id client_secret code redirect_uri = 21 let body = 22 Github_oauth.exchange_request_body ~client_id ~client_secret ~code 23 ~redirect_uri 24 in 25 (* Should be valid JSON - contains opening brace *) 26 check (String.length body > 2); 27 check (body.[0] = '{') 28 29(* Test that refresh_request_body produces valid JSON *) 30let test_refresh_body_valid client_id client_secret refresh_token = 31 let body = 32 Github_oauth.refresh_request_body ~client_id ~client_secret ~refresh_token 33 in 34 check (String.length body > 2); 35 check (body.[0] = '{') 36 37(* Test that parse_token_response handles arbitrary input without crashing *) 38let test_parse_no_crash input = 39 let _ = Github_oauth.parse_token_response input in 40 check true 41 42(* Test roundtrip: encode a valid token response, then parse it *) 43let test_token_roundtrip access_token expires_in refresh_token = 44 let json = 45 let parts = 46 [ Fmt.str {|"access_token":"%s"|} access_token ] 47 @ (match expires_in with 48 | None -> [] 49 | Some n -> [ Fmt.str {|"expires_in":%d|} (abs n mod 100000) ]) 50 @ 51 match refresh_token with 52 | None -> [] 53 | Some rt -> [ Fmt.str {|"refresh_token":"%s"|} rt ] 54 in 55 "{" ^ String.concat "," parts ^ "}" 56 in 57 match Github_oauth.parse_token_response json with 58 | Ok t -> check (t.access_token = access_token) 59 | Error _ -> check true (* some inputs may be invalid JSON *) 60 61let suite = 62 ( "github_oauth", 63 [ 64 test_case "authorization_url valid" 65 [ bytes; bytes; bytes; list bytes ] 66 test_authorization_url_valid; 67 test_case "exchange_body valid" 68 [ bytes; bytes; bytes; bytes ] 69 test_exchange_body_valid; 70 test_case "refresh_body valid" [ bytes; bytes; bytes ] 71 test_refresh_body_valid; 72 test_case "parse_no_crash" [ bytes ] test_parse_no_crash; 73 test_case "token roundtrip" 74 [ bytes; option int; option bytes ] 75 test_token_roundtrip; 76 ] )