//get refresh token from file private static bool trySetRefreshToken() { string refreshToken; string refreshTokenFilePath = YoutubeAuthentication.getRefreshTokenFilePath(); if (File.Exists(refreshTokenFilePath)) { refreshToken = File.ReadAllText(refreshTokenFilePath); if (string.IsNullOrWhiteSpace(refreshToken)) { return(false); } else { YoutubeAuthentication.refreshToken = refreshToken; return(true); } } else { return(false); } }
//initial authentication, get refresh token from API private static async Task getRefreshToken() { // Generates state and PKCE values. string state = randomDataBase64url(32); string code_verifier = randomDataBase64url(32); string code_challenge = base64urlencodeNoPadding(sha256(code_verifier)); const string code_challenge_method = "S256"; // Creates a redirect URI using an available port on the loopback address. string redirectURI = string.Format("http://{0}:{1}/", IPAddress.Loopback, YoutubeAuthentication.getRandomUnusedPort()); // Creates an HttpListener to listen for requests on that redirect URI. var http = new HttpListener(); http.Prefixes.Add(redirectURI); http.Start(); // Creates the OAuth 2.0 authorization request. string authorizationRequest = string.Format("{0}?response_type=code&scope={6}&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}", YoutubeAuthentication.authorizationEndpoint, Uri.EscapeDataString(redirectURI), Credentials.ClientId, state, code_challenge, code_challenge_method, Uri.EscapeDataString(YoutubeAuthentication.scopes)); var ps = new ProcessStartInfo(authorizationRequest) { UseShellExecute = true, Verb = "open" }; // Opens request in the browser. Process.Start(ps); // Waits for the OAuth authorization response. var context = await http.GetContextAsync(); // Sends an HTTP response to the browser. var response = context.Response; string responseString = string.Format("<html><head><meta http-equiv='refresh' content='10;url=https://google.com'></head><body>Please return to the app.</body></html>"); var buffer = Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; var responseOutput = response.OutputStream; responseOutput.Write(buffer, 0, buffer.Length); responseOutput.Close(); http.Stop(); // Checks for errors. if (context.Request.QueryString.Get("error") != null) { throw new AuthenticationException(string.Format("Authentication error: {0}", context.Request.QueryString.Get("error"))); } if (context.Request.QueryString.Get("code") == null || context.Request.QueryString.Get("state") == null) { throw new AuthenticationException("Authentication error: Code or State is null."); } // extracts the code var code = context.Request.QueryString.Get("code"); var incoming_state = context.Request.QueryString.Get("state"); // Compares the receieved state to the expected value, to ensure that // this app made the request which resulted in authorization. if (incoming_state != state) { throw new AuthenticationException("Authentication error: Code and State differ."); } // Starts the code exchange for refresh token at the token endpoint. // builds the request string tokenRequestBody = string.Format("code={0}&redirect_uri={1}&client_id={2}&code_verifier={3}&client_secret={4}&scope=&grant_type=authorization_code", code, System.Uri.EscapeDataString(redirectURI), Credentials.ClientId, code_verifier, Credentials.ClientSecret ); // sends the request byte[] contentBytes = Encoding.ASCII.GetBytes(tokenRequestBody); using (ByteArrayContent content = new ByteArrayContent(contentBytes)) { content.Headers.ContentLength = contentBytes.Length; content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); using (HttpResponseMessage message = await YoutubeAuthentication.client.PostAsync(YoutubeAuthentication.tokenEndpoint, content)) { message.EnsureSuccessStatusCode(); Dictionary <string, string> tokenEndpointDecoded = JsonConvert.DeserializeObject <Dictionary <string, string> >(await message.Content.ReadAsStringAsync()); YoutubeAuthentication.refreshToken = tokenEndpointDecoded["refresh_token"]; File.WriteAllText(YoutubeAuthentication.getRefreshTokenFilePath(), YoutubeAuthentication.refreshToken); } } }