When a workflow needs a Google authorization code and no refresh token is stored, GPAL.Credentials opens the auth URL in a browser, then polls /get-access-token on the local listener for up to 60 seconds waiting for the redirect to arrive. The code is cleared immediately on retrieval -- it is single use. If the 60-second window passes with nothing returned, GPAL logs the auth URL and falls back to prompting for a manual paste via the console.
// GPAL
// No manual REST calls needed
//
// 1
// 2
// http://localhost:3000/access-token
// 3
// 60 seconds and collects the code
// 4
// GPAL prints the auth URL and asks the
// user to paste the code manually
//
// The code is single-use -- cleared on retrieval
// GPALRestAPI clears it after 5 minutes
// if it is never retrieved at all
In Google Cloud Console under your OAuth client, add http://localhost:3000/access-token to Authorized Redirect URIs. A web application client matches the redirect exactly, port included, which is why GPAL never moves the listener to a different port. Use a different port by all means, but change it in both places: GoogleRestRedirectUri and the console.
The provider only redirects to the URI registered with it, so the address that catches the token is not a choice GPAL makes: it is the authority of GoogleRestRedirectUri, http://localhost:3000/ by default, read from credentialsConfig.json beside the exe. Before opening the auth URL, GPAL tries to bind that address with its own minimal listener, which serves the same access-token and get-access-token endpoints on a background thread and shuts down once the code is collected. If the bind fails then something already owns the port, and GPAL asks it whether it is GPALRestAPI by calling its status endpoint, waiting one second at most. If it answers, it catches the redirect as normal. If it does not, GPAL reports an error rather than listening somewhere else, because a redirect the provider never agreed to would not arrive anyway. Whichever caught it is readable afterwards as GPAL.OAuthTokenUrl.
// GPAL checks whether something is already
// listening on the redirect base URL
//
// If GPALRestAPI IS running:
// it owns the port -- redirect lands there
//
// If GPALRestAPI is NOT running:
// GPAL binds the same base URL itself via
// LocalAuthCallbackServer
// Same /access-token and /get-access-token
// endpoints, same behavior
// Listener is stopped after the code
// is retrieved
GPALRestAPI scans upward from 3000, so the first one on a machine takes it, which is why the usual case is that the GPALRestAPI your own browser launched is already sitting on the registered address. A second instance pushed to another port does not catch redirects, and cannot: there is one registered address, so two workflows doing OAuth at the same moment on one machine will collide.
Post the code to Google's token endpoint using the same redirect_uri that was registered. Google returns an access token and a refresh token. Store the refresh token -- once you have it, pass it to GPAL.Credentials and the full browser-based authorization flow never needs to run again. GPAL exchanges the refresh token for a fresh access token automatically on every subsequent workflow run.
// Exchange the code for access + refresh tokens:
string tokens = GPAL
code,
client_id = clientId,
client_secret = clientSecret,
redirect_uri = "http://localhost:3000/access-token",
grant_type = "authorization_code"
})
// Parse tokens JSON for access_token,
// refresh_token -- store the refresh token
The interactive browser authorization only runs once per Google account. After you have a refresh token, the workflow is fully automated with no user interaction required.
Showing off some plain text in these paragraphs eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Here you can find different accents and emphasis sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
This is a link and how it could look like bestlinkinthebeautifulworld. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Here's just some classic bold text adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam notBoldSecondbestlinkinthebeautifulworld illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at adipisicing elit libero vel voluptas? Expedita, adipisicing facere dolores voluptatem ad ab rem assumenda soluta!
Other cuple of colors in case we want to emphasize several ways adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at voluptatem libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repudiandae quas consequuntur illo numquam assumenda autem exercitationem distinctio perspiciatis in natus. Eius dicta similique ipsam ipsa minima, nemo quae enim tempore.
GPAL
.CallIfNotFound(GenericCallIfNotFound)
.WithPublishToConsole();
//System.Drawing.Rectangle windowSize = new System.Drawing.Rectangle(10, 10, 1500, 1024);
// NOTE: we have to set browser = before we execute any steps
// this is due to the 'GenericCallIfNotFound' which might throw an exception, and BankScraper will not have the browser set when it calls scraper.Close()
// until the complete fluent line gets executed (meaning every step, meaning browser is not set until everything else succeeds)
browser = GPAL.Browser
.WithBrowserType(Enums.BrowserType.Chrome)
.WithProfileDataDirectory(ChromeProfileLocation)
.WithUseAutomationEngine(AutomationEngine.Selenium)
.WithWindowSize(new System.Drawing.Rectangle(0,0,1920,1080))
.ToGPALObject();