A rhythm game net ranking service built on ATproto.

ok it's now at least *half* working

LemmaEOF 33c18f2f 43d2e896

+30 -6
+30 -6
game-example/OAuth.cs
··· 18 18 public TcpServer RedirectServer = new(); 19 19 public string RedirectUri = $"http://{Binding}:{Port}"; 20 20 21 - public string ClientId = "client_XTcqz8gXODW6yDv-lf9KJg"; 21 + public const string ClientId = "client_lvRAJmPuwePq5oEqoFR_Ww"; 22 + //I have completely given up on using DPoP for this demo. 23 + // THIS IS FOR DEMONSTRATION PURPOSES ONLY! DO NOT USE A CLIENT SECRET IN AN APP PLAYERS WILL DOWNLOAD! 24 + //(this is bound to my localhost docker container so you can't use this secret in prod anyway) 25 + private const string clientSecret = "8f03wNGkVL8oOqd1IUAZaYFUrZBQTIXoC2o8Wo6wXl8"; 26 + 27 + public bool Authorized = false; 22 28 23 29 public string Token; 24 30 private string refreshToken; ··· 34 40 // Called when the node enters the scene tree for the first time. 35 41 public override void _Ready() { 36 42 SetProcess(false); 43 + //InitialAuth(); 37 44 } 38 45 39 46 // Called every frame. 'delta' is the elapsed time since the previous frame. ··· 44 51 if (!String.IsNullOrEmpty(request)) { 45 52 SetProcess(false); 46 53 //TODO: this seems sus, will need to check for quickslice 47 - string authCode = request.Split("&scope")[0].Split("=")[1]; 54 + GD.Print($"Request result: `{request}`"); 55 + string authCode = request.Split(" HTTP/1.1")[0].Split("=")[1]; 56 + GD.Print($"Parsed auth code: `{authCode}`"); 48 57 GetTokenFromAuth(authCode); 49 58 50 59 connection.PutData("HTTP/1.1 200\r\n".ToAsciiBuffer()); 51 60 //TODO: response page here 52 - connection.PutData("".ToAsciiBuffer()); 61 + connection.PutData("Authentication complete!".ToAsciiBuffer()); 53 62 RedirectServer.Stop(); 54 63 } 55 64 } 56 65 } 57 66 67 + public async void InitialAuth() { 68 + LoadTokens(); 69 + 70 + if (!await IsTokenValid()) { 71 + if (!await RefreshTokens()) { 72 + Authorized = false; 73 + return; 74 + } 75 + } 76 + Authorized = true; 77 + } 78 + 58 79 public async Task Authorize(string handle) { 59 80 LoadTokens(); 60 81 ··· 67 88 68 89 private void GetAuthCode(string handle) { 69 90 SetProcess(true); 70 - RedirectServer.Listen(Port, Binding); 71 91 Error err = RedirectServer.Listen(Port, Binding); 72 92 73 93 string[] bodyParts = [ 74 94 $"client_id={ClientId}", 95 + $"client_secret={clientSecret}", 75 96 $"redirect_uri={RedirectUri}", 76 97 $"response_type=code", 77 98 //TODO: code challenge? 78 99 $"login_hint={handle}", 79 - $"scope=atproto transition:generic" 100 + "scope=atproto transition:generic" 80 101 ]; 81 102 string url = $"{AuthUrl}?{bodyParts.Join("&")}"; 82 103 ··· 92 113 string[] bodyParts = [ 93 114 $"code={authCode}", 94 115 $"client_id={ClientId}", 116 + $"client_secret={clientSecret}", 95 117 $"redirect_uri={RedirectUri}", 96 118 "grant_type=authorization_code" 97 119 ]; ··· 121 143 ]; 122 144 string[] bodyParts = [ 123 145 $"client_id={ClientId}", 146 + $"client_secret={clientSecret}", 124 147 $"refresh_token={refreshToken}", 125 148 "grant_type=refresh_token" 126 149 ]; ··· 145 168 return false; 146 169 } 147 170 171 + //TODO: Quickslice doesn't have a way to get token info! Need to refactor to check expiry + stored issue time directly 148 172 private async Task<bool> IsTokenValid() { 149 173 GD.Print("Checking if tokens are valid"); 150 174 if (string.IsNullOrEmpty(Token)) { ··· 160 184 161 185 string body = $"access_token={Token}"; 162 186 163 - Error err = Request.Request(TokenUrl+"info", headers, HttpClient.Method.Post, body); 187 + Error err = Request.Request(TokenUrl, headers, HttpClient.Method.Post, body); 164 188 165 189 if (err != Error.Ok) { 166 190 GD.PushError($"HTTP error {err} occured while trying to check auth token validity");