/// <see cref="IAuthenticator"/> async Task IAuthenticator.AuthenticateAsync(CancellationToken cancellationToken) { logger.Info("Okta Authentication"); // Clear cookies before authenticating because when a cookie is present in the request, // Okta will assume it is coming from a browser and perform a CSRF check. // This will ensure that we are NOT including the ‘sid’ cookie with the request. HttpUtil.ClearCookies(oktaUrl); logger.Debug("step 1: get sso and token url"); var authenticatorRestRequest = BuildAuthenticatorRestRequest(); var authenticatorResponse = await session.restRequester.PostAsync <AuthenticatorResponse>(authenticatorRestRequest, cancellationToken).ConfigureAwait(false); authenticatorResponse.FilterFailedResponse(); Uri ssoUrl = new Uri(authenticatorResponse.data.ssoUrl); Uri tokenUrl = new Uri(authenticatorResponse.data.tokenUrl); logger.Debug("step 2: verify urls fetched from step 1"); logger.Debug("Checking sso url"); VerifyUrls(ssoUrl, oktaUrl); logger.Debug("Checking token url"); VerifyUrls(tokenUrl, oktaUrl); logger.Debug("step 3: get idp onetime token"); IdpTokenRestRequest idpTokenRestRequest = BuildIdpTokenRestRequest(tokenUrl); var idpResponse = await session.restRequester.PostAsync <IdpTokenResponse>(idpTokenRestRequest, cancellationToken).ConfigureAwait(false); string onetimeToken = idpResponse.CookieToken; logger.Debug("step 4: get SAML reponse from sso"); var samlRestRequest = BuildSAMLRestRequest(ssoUrl, onetimeToken); var samlRawResponse = await session.restRequester.GetAsync(samlRestRequest, cancellationToken).ConfigureAwait(false); samlRawHtmlString = await samlRawResponse.Content.ReadAsStringAsync().ConfigureAwait(false); logger.Debug("step 5: verify postback url in SAML reponse"); VerifyPostbackUrl(); logger.Debug("step 6: send SAML reponse to snowflake to login"); await base.LoginAsync(cancellationToken); }