mirror of
https://github.com/sstent/go-garth.git
synced 2026-01-25 16:42:28 +00:00
sync authfix
This commit is contained in:
294
auth.go
294
auth.go
@@ -2,10 +2,7 @@ package garth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -16,7 +13,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -164,28 +161,10 @@ func (a *GarthAuthenticator) Login(ctx context.Context, username, password, mfaT
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Get OAuth1 request token
|
||||
oauth1RequestToken, err := a.fetchOAuth1RequestToken(ctx)
|
||||
// Step 3: Exchange service ticket for access token
|
||||
token, err := a.exchangeServiceTicketForToken(ctx, serviceTicket)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get OAuth1 request token: %w", err)
|
||||
}
|
||||
|
||||
// Step 4: Authorize OAuth1 request token (using the session from authentication)
|
||||
err = a.authorizeOAuth1Token(ctx, oauth1RequestToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to authorize OAuth1 token: %w", err)
|
||||
}
|
||||
|
||||
// Step 5: Exchange service ticket for OAuth1 access token
|
||||
oauth1AccessToken, err := a.exchangeTicketForOAuth1Token(ctx, serviceTicket)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to exchange ticket for OAuth1 access token: %w", err)
|
||||
}
|
||||
|
||||
// Step 6: Exchange OAuth1 access token for OAuth2 token
|
||||
token, err := a.exchangeOAuth1ForOAuth2Token(ctx, oauth1AccessToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to exchange OAuth1 for OAuth2 token: %w", err)
|
||||
return nil, fmt.Errorf("failed to exchange service ticket for token: %w", err)
|
||||
}
|
||||
|
||||
if err := a.storage.StoreToken(token); err != nil {
|
||||
@@ -195,203 +174,61 @@ func (a *GarthAuthenticator) Login(ctx context.Context, username, password, mfaT
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) fetchOAuth1RequestToken(ctx context.Context) (*OAuth1Token, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://connectapi.%s/oauth-service/oauth/request_token", a.domain), nil)
|
||||
// exchangeServiceTicketForToken exchanges service ticket for access token
|
||||
func (a *GarthAuthenticator) exchangeServiceTicketForToken(ctx context.Context, ticket string) (*Token, error) {
|
||||
callbackURL := fmt.Sprintf("https://connect.%s/oauthConfirm?ticket=%s", a.domain, ticket)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", callbackURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
// Sign request with OAuth1 consumer credentials
|
||||
req.Header.Set("Authorization", a.buildOAuth1Header(req, nil, ""))
|
||||
|
||||
resp, err := a.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("request failed with status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
values, err := url.ParseQuery(string(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse response: %w", err)
|
||||
}
|
||||
|
||||
return &OAuth1Token{
|
||||
Token: values.Get("oauth_token"),
|
||||
Secret: values.Get("oauth_token_secret"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) authorizeOAuth1Token(ctx context.Context, token *OAuth1Token) error {
|
||||
params := url.Values{}
|
||||
params.Set("oauth_token", token.Token)
|
||||
authURL := fmt.Sprintf("https://connect.%s/oauthConfirm?%s", a.domain, params.Encode())
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", authURL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create authorization request: %w", err)
|
||||
return nil, fmt.Errorf("failed to create callback request: %w", err)
|
||||
}
|
||||
|
||||
// Use realistic browser headers
|
||||
req.Header = a.getRealisticBrowserHeaders("https://connect.garmin.com")
|
||||
req.Header = a.getRealisticBrowserHeaders("https://sso.garmin.com")
|
||||
|
||||
resp, err := a.client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("authorization request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// We don't need the CSRF token anymore, so just check for success
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return fmt.Errorf("authorization failed with status: %d, response: %s", resp.StatusCode, body)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) exchangeTicketForOAuth1Token(ctx context.Context, ticket string) (*OAuth1Token, error) {
|
||||
data := url.Values{}
|
||||
data.Set("oauth_verifier", ticket)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("https://connectapi.%s/oauth-service/oauth/access_token", a.domain), strings.NewReader(data.Encode()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create access token request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Authorization", a.buildOAuth1Header(req, nil, ""))
|
||||
|
||||
resp, err := a.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("access token request failed: %w", err)
|
||||
return nil, fmt.Errorf("callback request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("access token request failed with status: %d", resp.StatusCode)
|
||||
return nil, fmt.Errorf("callback failed with status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read access token response: %w", err)
|
||||
return nil, fmt.Errorf("failed to read callback response: %w", err)
|
||||
}
|
||||
|
||||
values, err := url.ParseQuery(string(body))
|
||||
// Extract tokens from embedded JavaScript
|
||||
accessToken, err := extractParam(`"accessToken":"([^"]+)"`, string(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse access token response: %w", err)
|
||||
return nil, fmt.Errorf("failed to extract access token: %w", err)
|
||||
}
|
||||
|
||||
return &OAuth1Token{
|
||||
Token: values.Get("oauth_token"),
|
||||
Secret: values.Get("oauth_token_secret"),
|
||||
refreshToken, err := extractParam(`"refreshToken":"([^"]+)"`, string(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract refresh token: %w", err)
|
||||
}
|
||||
|
||||
expiresAt, err := extractParam(`"expiresAt":(\d+)`, string(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract expiresAt: %w", err)
|
||||
}
|
||||
|
||||
expiresAtInt, err := strconv.ParseInt(expiresAt, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse expiresAt: %w", err)
|
||||
}
|
||||
|
||||
return &Token{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
ExpiresAt: expiresAtInt,
|
||||
Domain: a.domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) exchangeOAuth1ForOAuth2Token(ctx context.Context, oauth1Token *OAuth1Token) (*Token, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("https://connectapi.%s/oauth-service/oauth/exchange_token", a.domain), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create token exchange request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", a.buildOAuth1Header(req, oauth1Token, ""))
|
||||
|
||||
resp, err := a.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("token exchange request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("token exchange failed with status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var token Token
|
||||
if err := json.NewDecoder(resp.Body).Decode(&token); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse token response: %w", err)
|
||||
}
|
||||
|
||||
if token.OAuth2Token != nil {
|
||||
token.OAuth2Token.ExpiresAt = time.Now().Add(time.Duration(token.OAuth2Token.ExpiresIn) * time.Second).Unix()
|
||||
}
|
||||
token.OAuth1Token = oauth1Token
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) buildOAuth1Header(req *http.Request, token *OAuth1Token, callback string) string {
|
||||
oauthParams := url.Values{}
|
||||
oauthParams.Set("oauth_consumer_key", "fc020df2-e33d-4ec5-987a-7fb6de2e3850")
|
||||
oauthParams.Set("oauth_signature_method", "HMAC-SHA1")
|
||||
oauthParams.Set("oauth_timestamp", fmt.Sprintf("%d", time.Now().Unix()))
|
||||
oauthParams.Set("oauth_nonce", fmt.Sprintf("%d", rand.Int63()))
|
||||
oauthParams.Set("oauth_version", "1.0")
|
||||
|
||||
if token != nil {
|
||||
oauthParams.Set("oauth_token", token.Token)
|
||||
}
|
||||
if callback != "" {
|
||||
oauthParams.Set("oauth_callback", callback)
|
||||
}
|
||||
|
||||
// Generate signature
|
||||
baseString := a.buildSignatureBaseString(req, oauthParams)
|
||||
signingKey := url.QueryEscape("secret_key_from_mobile_app") + "&"
|
||||
if token != nil {
|
||||
signingKey += url.QueryEscape(token.Secret)
|
||||
}
|
||||
|
||||
mac := hmac.New(sha1.New, []byte(signingKey))
|
||||
mac.Write([]byte(baseString))
|
||||
signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
||||
oauthParams.Set("oauth_signature", signature)
|
||||
|
||||
// Build header
|
||||
params := make([]string, 0, len(oauthParams))
|
||||
for k, v := range oauthParams {
|
||||
params = append(params, fmt.Sprintf(`%s="%s"`, k, url.QueryEscape(v[0])))
|
||||
}
|
||||
sort.Strings(params)
|
||||
|
||||
return "OAuth " + strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) buildSignatureBaseString(req *http.Request, oauthParams url.Values) string {
|
||||
method := strings.ToUpper(req.Method)
|
||||
baseURL := req.URL.Scheme + "://" + req.URL.Host + req.URL.Path
|
||||
|
||||
// Collect all parameters
|
||||
params := url.Values{}
|
||||
for k, v := range req.URL.Query() {
|
||||
params[k] = v
|
||||
}
|
||||
for k, v := range oauthParams {
|
||||
params[k] = v
|
||||
}
|
||||
|
||||
// Sort parameters
|
||||
paramKeys := make([]string, 0, len(params))
|
||||
for k := range params {
|
||||
paramKeys = append(paramKeys, k)
|
||||
}
|
||||
sort.Strings(paramKeys)
|
||||
|
||||
paramPairs := make([]string, 0, len(paramKeys))
|
||||
for _, k := range paramKeys {
|
||||
paramPairs = append(paramPairs, fmt.Sprintf("%s=%s", k, url.QueryEscape(params[k][0])))
|
||||
}
|
||||
|
||||
queryString := strings.Join(paramPairs, "&")
|
||||
return fmt.Sprintf("%s&%s&%s", method, url.QueryEscape(baseURL), url.QueryEscape(queryString))
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) getLoginTicket(ctx context.Context) (string, string, error) {
|
||||
params := url.Values{}
|
||||
params.Set("id", "gauth-widget")
|
||||
@@ -527,10 +364,6 @@ func (a *GarthAuthenticator) authenticate(ctx context.Context, username, passwor
|
||||
return authResponse.Ticket, nil
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) ExchangeToken(ctx context.Context, token *OAuth1Token) (*Token, error) {
|
||||
return a.exchangeOAuth1ForOAuth2Token(ctx, token)
|
||||
}
|
||||
|
||||
func (a *GarthAuthenticator) getEnhancedBrowserHeaders(referrer string) http.Header {
|
||||
u, _ := url.Parse(referrer)
|
||||
origin := fmt.Sprintf("%s://%s", u.Scheme, u.Host)
|
||||
@@ -553,25 +386,27 @@ func (a *GarthAuthenticator) getEnhancedBrowserHeaders(referrer string) http.Hea
|
||||
}
|
||||
|
||||
func getCSRFToken(html string) (string, string, error) {
|
||||
// Extract login ticket (lt) from hidden input field
|
||||
re := regexp.MustCompile(`<input\s+type="hidden"\s+name="lt"\s+value="([^"]+)"\s*/>`)
|
||||
matches := re.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1], "lt", nil
|
||||
// More robust regex patterns to handle variations in HTML structure
|
||||
patterns := []struct {
|
||||
regex string
|
||||
tokenType string
|
||||
}{
|
||||
// Pattern for login ticket (lt)
|
||||
{`<input[^>]*name="lt"[^>]*value="([^"]+)"`, "lt"},
|
||||
// Pattern for CSRF token in hidden input
|
||||
{`<input[^>]*name="_csrf"[^>]*value="([^"]+)"`, "_csrf"},
|
||||
// Pattern for CSRF token in meta tag
|
||||
{`<meta[^>]*name="_csrf"[^>]*content="([^"]+)"`, "_csrf"},
|
||||
// Pattern for CSRF token in JSON payload
|
||||
{`"csrfToken"\s*:\s*"([^"]+)"`, "_csrf"},
|
||||
}
|
||||
|
||||
// Extract CSRF token as fallback
|
||||
re = regexp.MustCompile(`<input\s+type="hidden"\s+name="_csrf"\s+value="([^"]+)"\s*/>`)
|
||||
matches = re.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1], "_csrf", nil
|
||||
}
|
||||
|
||||
// Try alternative CSRF token pattern
|
||||
re = regexp.MustCompile(`"csrfToken":"([^"]+)"`)
|
||||
matches = re.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1], "_csrf", nil
|
||||
for _, p := range patterns {
|
||||
re := regexp.MustCompile(p.regex)
|
||||
matches := re.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1], p.tokenType, nil
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we didn't find a token
|
||||
@@ -609,15 +444,22 @@ func (a *GarthAuthenticator) RefreshToken(ctx context.Context, refreshToken stri
|
||||
return nil, fmt.Errorf("refresh failed: %d %s", resp.StatusCode, body)
|
||||
}
|
||||
|
||||
var token Token
|
||||
if err := json.NewDecoder(resp.Body).Decode(&token); err != nil {
|
||||
var response struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse refresh response: %w", err)
|
||||
}
|
||||
|
||||
if token.OAuth2Token != nil {
|
||||
token.OAuth2Token.ExpiresAt = time.Now().Add(time.Duration(token.OAuth2Token.ExpiresIn) * time.Second).Unix()
|
||||
}
|
||||
return &token, nil
|
||||
expiresAt := time.Now().Add(time.Duration(response.ExpiresIn) * time.Second).Unix()
|
||||
return &Token{
|
||||
AccessToken: response.AccessToken,
|
||||
RefreshToken: response.RefreshToken,
|
||||
ExpiresAt: expiresAt,
|
||||
Domain: a.domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetClient returns the HTTP client used for authentication
|
||||
|
||||
12
auth_test.go
12
auth_test.go
@@ -59,27 +59,27 @@ func TestRealAuthentication(t *testing.T) {
|
||||
}
|
||||
|
||||
log.Printf("Authentication successful! Token details:")
|
||||
log.Printf("Access Token: %s", token.OAuth2Token.AccessToken)
|
||||
log.Printf("Expires At: %d", token.OAuth2Token.ExpiresAt)
|
||||
log.Printf("Refresh Token: %s", token.OAuth2Token.RefreshToken)
|
||||
log.Printf("Access Token: %s", token.AccessToken)
|
||||
log.Printf("Expires At: %d", token.ExpiresAt)
|
||||
log.Printf("Refresh Token: %s", token.RefreshToken)
|
||||
|
||||
// Verify token storage
|
||||
storedToken, err := storage.GetToken()
|
||||
if err != nil {
|
||||
t.Fatalf("Token storage verification failed: %v", err)
|
||||
}
|
||||
if storedToken.OAuth2Token.AccessToken != token.OAuth2Token.AccessToken {
|
||||
if storedToken.AccessToken != token.AccessToken {
|
||||
t.Fatal("Stored token doesn't match authenticated token")
|
||||
}
|
||||
|
||||
log.Println("Token storage verification successful")
|
||||
|
||||
// Test token refresh
|
||||
newToken, err := auth.RefreshToken(ctx, token.OAuth2Token.RefreshToken)
|
||||
newToken, err := auth.RefreshToken(ctx, token.RefreshToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Token refresh failed: %v", err)
|
||||
}
|
||||
if newToken.OAuth2Token.AccessToken == token.OAuth2Token.AccessToken {
|
||||
if newToken.AccessToken == token.AccessToken {
|
||||
t.Fatal("Refreshed token should be different from original")
|
||||
}
|
||||
log.Println("Token refresh successful")
|
||||
|
||||
@@ -59,7 +59,7 @@ func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
}
|
||||
|
||||
// Add Authorization header
|
||||
req.Header.Set("Authorization", "Bearer "+token.OAuth2Token.AccessToken)
|
||||
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
||||
req.Header.Set("User-Agent", t.userAgent)
|
||||
req.Header.Set("Referer", "https://sso.garmin.com/sso/signin")
|
||||
|
||||
@@ -85,7 +85,7 @@ func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+token.OAuth2Token.AccessToken)
|
||||
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ func (t *AuthTransport) refreshToken(ctx context.Context, token *Token) (*Token,
|
||||
}
|
||||
|
||||
// Perform refresh
|
||||
newToken, err := t.auth.RefreshToken(ctx, token.OAuth2Token.RefreshToken)
|
||||
newToken, err := t.auth.RefreshToken(ctx, token.RefreshToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -40,16 +40,16 @@ func main() {
|
||||
}
|
||||
|
||||
fmt.Println("\nAuthentication successful! Token details:")
|
||||
fmt.Printf("Access Token: %s\n", token.OAuth2Token.AccessToken)
|
||||
fmt.Printf("Expires At: %d\n", token.OAuth2Token.ExpiresAt)
|
||||
fmt.Printf("Refresh Token: %s\n", token.OAuth2Token.RefreshToken)
|
||||
fmt.Printf("Access Token: %s\n", token.AccessToken)
|
||||
fmt.Printf("Expires At: %d\n", token.ExpiresAt)
|
||||
fmt.Printf("Refresh Token: %s\n", token.RefreshToken)
|
||||
|
||||
// Verify token storage
|
||||
storedToken, err := storage.GetToken()
|
||||
if err != nil {
|
||||
log.Fatalf("Token storage verification failed: %v", err)
|
||||
}
|
||||
if storedToken.OAuth2Token.AccessToken != token.OAuth2Token.AccessToken {
|
||||
if storedToken.AccessToken != token.AccessToken {
|
||||
log.Fatal("Stored token doesn't match authenticated token")
|
||||
}
|
||||
|
||||
|
||||
BIN
debug/oauth1_response_1757098946234920274.html
Normal file
BIN
debug/oauth1_response_1757098946234920274.html
Normal file
Binary file not shown.
BIN
debug/oauth1_response_1757098948026901630.html
Normal file
BIN
debug/oauth1_response_1757098948026901630.html
Normal file
Binary file not shown.
BIN
debug/oauth1_response_1757129132587570285.html
Normal file
BIN
debug/oauth1_response_1757129132587570285.html
Normal file
Binary file not shown.
BIN
debug/oauth1_response_1757129134048278764.html
Normal file
BIN
debug/oauth1_response_1757129134048278764.html
Normal file
Binary file not shown.
BIN
debug/oauth1_response_1757129231414677442.html
Normal file
BIN
debug/oauth1_response_1757129231414677442.html
Normal file
Binary file not shown.
BIN
debug/oauth1_response_1757129232952257721.html
Normal file
BIN
debug/oauth1_response_1757129232952257721.html
Normal file
Binary file not shown.
93
debug_auth_response_1757103692.html
Normal file
93
debug_auth_response_1757103692.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a86f0198f008fa</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a86f0198f008fa',t:'MTc1NzEwMzY5My4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757103857.html
Normal file
93
debug_auth_response_1757103857.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a87306fc145337</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a87306fc145337',t:'MTc1NzEwMzg1Ny4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757104480.html
Normal file
93
debug_auth_response_1757104480.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a8823fcfbc0904</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a8823fcfbc0904',t:'MTc1NzEwNDQ4MS4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757116993.html
Normal file
93
debug_auth_response_1757116993.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a9b3b9dbc89dea</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a9b3b9dbc89dea',t:'MTc1NzExNjk5My4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757117105.html
Normal file
93
debug_auth_response_1757117105.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a9b677e98ff8d5</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">138.199.43.80</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a9b677e98ff8d5',t:'MTc1NzExNzEwNS4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757117228.html
Normal file
93
debug_auth_response_1757117228.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a9b977caffdbc2</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a9b977caffdbc2',t:'MTc1NzExNzIyOC4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757117813.html
Normal file
93
debug_auth_response_1757117813.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a9c7bc4ed7ff84</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a9c7bc4ed7ff84',t:'MTc1NzExNzgxMy4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
93
debug_auth_response_1757119493.html
Normal file
93
debug_auth_response_1757119493.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en-US"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en-US"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Attention Required! | Cloudflare</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" />
|
||||
<!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" /><![endif]-->
|
||||
<style>body{margin:0;padding:0}</style>
|
||||
|
||||
|
||||
<!--[if gte IE 10]><!-->
|
||||
<script>
|
||||
if (!navigator.cookieEnabled) {
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
var cookieEl = document.getElementById('cookie-alert');
|
||||
cookieEl.style.display = 'block';
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<!--<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="cf-wrapper">
|
||||
<div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
|
||||
<div id="cf-error-details" class="cf-error-details-wrapper">
|
||||
<div class="cf-wrapper cf-header cf-error-overview">
|
||||
<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
|
||||
<h2 class="cf-subheadline"><span data-translate="unable_to_access">You are unable to access</span> sso.garmin.com</h2>
|
||||
</div><!-- /.header -->
|
||||
|
||||
<div class="cf-section cf-highlight">
|
||||
<div class="cf-wrapper">
|
||||
<div class="cf-screenshot-container cf-screenshot-full">
|
||||
|
||||
<span class="cf-no-screenshot error"></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.captcha-container -->
|
||||
|
||||
<div class="cf-section cf-wrapper">
|
||||
<div class="cf-columns two">
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_why_headline">Why have I been blocked?</h2>
|
||||
|
||||
<p data-translate="blocked_why_detail">This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.</p>
|
||||
</div>
|
||||
|
||||
<div class="cf-column">
|
||||
<h2 data-translate="blocked_resolve_headline">What can I do to resolve this?</h2>
|
||||
|
||||
<p data-translate="blocked_resolve_detail">You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.section -->
|
||||
|
||||
<div class="cf-error-footer cf-wrapper w-240 lg:w-full py-10 sm:py-4 sm:px-8 mx-auto text-center sm:text-left border-solid border-0 border-t border-gray-300">
|
||||
<p class="text-13">
|
||||
<span class="cf-footer-item sm:block sm:mb-1">Cloudflare Ray ID: <strong class="font-semibold">97a9f0c2588a72e0</strong></span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
<span id="cf-footer-item-ip" class="cf-footer-item hidden sm:block sm:mb-1">
|
||||
Your IP:
|
||||
<button type="button" id="cf-footer-ip-reveal" class="cf-footer-ip-reveal-btn">Click to reveal</button>
|
||||
<span class="hidden" id="cf-footer-ip">47.150.230.21</span>
|
||||
<span class="cf-footer-separator sm:hidden">•</span>
|
||||
</span>
|
||||
<span class="cf-footer-item sm:block sm:mb-1"><span>Performance & security by</span> <a rel="noopener noreferrer" href="https://www.cloudflare.com/5xx-error-landing" id="brand_link" target="_blank">Cloudflare</a></span>
|
||||
|
||||
</p>
|
||||
<script>(function(){function d(){var b=a.getElementById("cf-footer-item-ip"),c=a.getElementById("cf-footer-ip-reveal");b&&"classList"in b&&(b.classList.remove("hidden"),c.addEventListener("click",function(){c.classList.add("hidden");a.getElementById("cf-footer-ip").classList.remove("hidden")}))}var a=document;document.addEventListener&&a.addEventListener("DOMContentLoaded",d)})();</script>
|
||||
</div><!-- /.error-footer -->
|
||||
|
||||
|
||||
</div><!-- /#cf-error-details -->
|
||||
</div><!-- /#cf-wrapper -->
|
||||
|
||||
<script>
|
||||
window._cf_translation = {};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a9f0c2588a72e0',t:'MTc1NzExOTQ5My4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
BIN
debug_response_1757099867.html
Normal file
BIN
debug_response_1757099867.html
Normal file
Binary file not shown.
206
debug_response_fixed_1757099969.html
Normal file
206
debug_response_fixed_1757099969.html
Normal file
@@ -0,0 +1,206 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge;" />
|
||||
<title>GARMIN Authentication Application</title>
|
||||
<link href="/sso/css/GAuth.css?20210406" rel="stylesheet" type="text/css" media="all" />
|
||||
|
||||
<link rel="stylesheet" href=""/>
|
||||
|
||||
<script type="text/javascript" src="/sso/js/jquery/3.7.1/jquery.min.js?20210319"></script>
|
||||
<script type="text/javascript">jQuery.noConflict();</script>
|
||||
<script type="text/javascript" src="/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319"></script>
|
||||
<script type="text/javascript" src="/sso/js/jsUtils.js?20210406"></script>
|
||||
<script type="text/javascript" src="/sso/js/json2.js"></script>
|
||||
<script type="text/javascript" src="/sso/js/consoleUtils.js?20210319"></script>
|
||||
<script type="text/javascript" src="/sso/js/postmessage.js?20210319"></script>
|
||||
<script type="text/javascript" src="/sso/js/popupWindow.js"></script>
|
||||
<script type="text/javascript" src="/sso/js/base.js?20231020"></script>
|
||||
<script type="text/javascript" src="/sso/js/gigyaUtils.js?20210319"></script>
|
||||
<script type="text/javascript" src="/sso/js/login.js?20211102"></script>
|
||||
<script type="text/javascript" src="/sso/js/reCaptchaUtil.js?20230706"></script>
|
||||
|
||||
<script>
|
||||
var recaptchaSiteKey = null;
|
||||
var reCaptchaURL = "\\\/sso\\\/reCaptcha?clientId=GarminConnect\u0026consumeServiceTicket=false\u0026embedWidget=true\u0026gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso\u0026generateExtraServiceTicket=true\u0026id=gauth-widget\u0026locale=en_US\u0026redirectAfterAccountCreationUrl=https%3A%2F%2Fconnect.garmin.com%2FoauthConfirm\u0026redirectAfterAccountLoginUrl=https%3A%2F%2Fconnect.garmin.com%2FoauthConfirm\u0026service=https%3A%2F%2Fconnect.garmin.com%2FoauthConfirm\u0026source=https%3A%2F%2Fsso.garmin.com%2Fsso";
|
||||
var isRecaptchaEnabled = null;
|
||||
var recaptchaToken = null;
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var parent_url = "https:\/\/sso.garmin.com\/sso";
|
||||
var status = "";
|
||||
var result = "";
|
||||
var clientId = 'GarminConnect';
|
||||
var embedWidget = true;
|
||||
var isUsernameDefined = (false == true) || (false == true);
|
||||
|
||||
// Gigya callback to SocialSignInController for brand new social network users redirects to this page
|
||||
// to popup Create or Link Social Account page, but has a possibly mangled source parameter
|
||||
// where "?" is set as "<QM>", so translate it back to "?" here.
|
||||
parent_url = parent_url.replace('<QM>', '?');
|
||||
var parent_scheme = parent_url.substring(0, parent_url.indexOf("://"));
|
||||
var parent_hostname = parent_url.substring(parent_scheme.length + 3, parent_url.length);
|
||||
if (parent_hostname.indexOf("/") != -1) {
|
||||
parent_hostname = parent_hostname.substring(0, parent_hostname.indexOf("/"));
|
||||
}
|
||||
var parentHost = parent_scheme + "://" + parent_hostname;
|
||||
var createAccountConfigURL = '\/sso\/createNewAccount?clientId%3DGarminConnect%26consumeServiceTicket%3Dfalse%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%26generateExtraServiceTicket%3Dtrue%26id%3Dgauth-widget%26locale%3Den_US%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fconnect.garmin.com%252FoauthConfirm%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fconnect.garmin.com%252FoauthConfirm%26service%3Dhttps%253A%252F%252Fconnect.garmin.com%252FoauthConfirm%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso';
|
||||
var socialConfigURL = 'https://sso.garmin.com/sso/socialSignIn?clientId%3DGarminConnect%26consumeServiceTicket%3Dfalse%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%26generateExtraServiceTicket%3Dtrue%26id%3Dgauth-widget%26locale%3Den_US%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fconnect.garmin.com%2FoauthConfirm%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fconnect.garmin.com%2FoauthConfirm%26service%3Dhttps%3A%2F%2Fconnect.garmin.com%2FoauthConfirm%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso';
|
||||
var gigyaURL = "https://cdns.gigya.com/js/gigya.js?apiKey=2_R3ZGY8Bqlwwk3_63knoD9wA_m-Y19mAgW61bF_s5k9gymYnMEAtMrJiF5MjF-U7B";
|
||||
|
||||
if (createAccountConfigURL.indexOf('%253A%252F%252F') != -1) {
|
||||
createAccountConfigURL = decodeURIComponent(createAccountConfigURL);
|
||||
}
|
||||
consoleInfo('signin.html embedWidget: true, createAccountConfigURL: \/sso\/createNewAccount?clientId%3DGarminConnect%26consumeServiceTicket%3Dfalse%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%26generateExtraServiceTicket%3Dtrue%26id%3Dgauth-widget%26locale%3Den_US%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fconnect.garmin.com%252FoauthConfirm%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fconnect.garmin.com%252FoauthConfirm%26service%3Dhttps%253A%252F%252Fconnect.garmin.com%252FoauthConfirm%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso, socialEnabled: true, gigyaSupported: true, socialConfigURL(): https://sso.garmin.com/sso/socialSignIn?clientId%3DGarminConnect%26consumeServiceTicket%3Dfalse%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%26generateExtraServiceTicket%3Dtrue%26id%3Dgauth-widget%26locale%3Den_US%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fconnect.garmin.com%2FoauthConfirm%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fconnect.garmin.com%2FoauthConfirm%26service%3Dhttps%3A%2F%2Fconnect.garmin.com%2FoauthConfirm%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso');
|
||||
|
||||
if (socialConfigURL.indexOf('%3A%2F%2F') != -1) {
|
||||
socialConfigURL = decodeURIComponent(socialConfigURL);
|
||||
}
|
||||
|
||||
if( status != null && status != ''){
|
||||
send({'status':status});
|
||||
}
|
||||
|
||||
jQuery(document).ready( function(){
|
||||
|
||||
|
||||
consoleInfo("signin.html: setting field validation rules...");
|
||||
|
||||
jQuery("#username").rules("add",{
|
||||
required: true,
|
||||
messages: {
|
||||
required: "Email is required."
|
||||
}});
|
||||
|
||||
jQuery("#password").rules("add", {
|
||||
required: true,
|
||||
messages: {
|
||||
required: "Password is required."
|
||||
}
|
||||
});
|
||||
|
||||
consoleInfo("signin.html: done setting field validation rules...");
|
||||
|
||||
});
|
||||
|
||||
XD.receiveMessage(function(m){
|
||||
consoleInfo("signin.html: " + m.data + " received on " + window.location.host);
|
||||
if (m && m.data) {
|
||||
var md = m.data;
|
||||
if (typeof(md) === 'string') {
|
||||
md = JSON.parse(m.data);
|
||||
}
|
||||
if (md.setUsername) {
|
||||
consoleInfo("signin.html: Setting username \"" + md.username + "\"...");
|
||||
jQuery("#signInWithDiffLink").click(); // Ensure the normal login form is shown.
|
||||
jQuery("#username").val(md.username);
|
||||
jQuery("#password").focus();
|
||||
}
|
||||
}
|
||||
}, parentHost);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- begin GAuth component -->
|
||||
<div id="GAuth-component">
|
||||
<!-- begin login component-->
|
||||
<div id="login-component" class="blueForm-basic">
|
||||
<input type="hidden" id="queryString" value="clientId=GarminConnect&consumeServiceTicket=false&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso&generateExtraServiceTicket=true&id=gauth-widget&locale=en_US&redirectAfterAccountCreationUrl=https%3A%2F%2Fconnect.garmin.com%2FoauthConfirm&redirectAfterAccountLoginUrl=https%3A%2F%2Fconnect.garmin.com%2FoauthConfirm&service=https%3A%2F%2Fconnect.garmin.com%2FoauthConfirm&source=https%3A%2F%2Fsso.garmin.com%2Fsso" />
|
||||
<input type="hidden" id="contextPath" value="/sso" />
|
||||
<!-- begin login form -->
|
||||
<div id="login-state-default">
|
||||
<h2>Sign In</h2>
|
||||
|
||||
<form method="post" id="login-form">
|
||||
|
||||
<div class="form-alert">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="username-error" style="display:none;"></div>
|
||||
<div id="password-error" style="display:none;"></div>
|
||||
</div>
|
||||
<div class="textfield">
|
||||
<label for="username">Email</label>
|
||||
<!-- If the lockToEmailAddress parameter is specified then we want to mark the field as readonly,
|
||||
preload the email address, and disable the other input so that null isn't sent to the server. We'll
|
||||
also style the field to have a darker grey background and disable the mouse pointer
|
||||
-->
|
||||
|
||||
<!-- If the lockToEmailAddress parameter is NOT specified then keep the existing functionality and disable the readonly input field
|
||||
-->
|
||||
<input class="login_email" name="username" id="username" value="" type="email" spellcheck="false" autocorrect="off" autocapitalize="off"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="textfield">
|
||||
<label for="password">Password</label>
|
||||
<a id="loginforgotpassword" class="login-forgot-password" style="cursor:pointer">(Forgot?)</a>
|
||||
<input type="password" name="password" id="password" spellcheck="false" autocorrect="off" autocapitalize="off" />
|
||||
<strong id="capslock-warning" class="information" title="Caps lock is on." style="display: none;">Caps lock is on.</strong>
|
||||
</div>
|
||||
<input type="hidden" name="embed" value="true"/>
|
||||
<input type="hidden" name="_csrf" value="E40E9FF5C027499972C9CF65024778906C9844597CEA466BA7F12FD111B57968050F45514DAA93282D2DF3FB562B20866BD6" />
|
||||
<button type="submit" id="login-btn-signin" class="btn1" accesskey="l">Sign In</button>
|
||||
|
||||
|
||||
|
||||
<!-- The existence of the "rememberme" parameter at all will remember the user! -->
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<!-- end login form -->
|
||||
|
||||
<!-- begin Create Account message -->
|
||||
<div id="login-create-account">
|
||||
|
||||
</div>
|
||||
<!-- end Create Account message -->
|
||||
|
||||
<!-- begin Social Sign In component -->
|
||||
<div id="SSI-component">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<!-- end Social Sign In component -->
|
||||
<div class="clearfix"></div> <!-- Ensure that GAuth-component div's height is computed correctly. -->
|
||||
</div>
|
||||
<!-- end login component-->
|
||||
|
||||
</div>
|
||||
<!-- end GAuth component -->
|
||||
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function(){
|
||||
resizePageOnLoad(jQuery("#GAuth-component").height());
|
||||
|
||||
if(isUsernameDefined == true){
|
||||
// If the user's login just failed, redisplay the email/username specified, and focus them in the password field.
|
||||
jQuery("#password").focus();
|
||||
} else if(false == true && result != "PASSWORD_RESET_RESULT"){
|
||||
// Otherwise focus them in the username field of the login dialog.
|
||||
jQuery("#username").focus();
|
||||
}
|
||||
|
||||
// Scroll to top of iframe to fix problem where Firefox 3.0-3.6 browsers initially show top of iframe cutoff.
|
||||
location.href="#";
|
||||
|
||||
if(!embedWidget){
|
||||
jQuery('.createAccountLink').click(function(){
|
||||
send({'openLiteBox':'createAccountLink', 'popupUrl': createAccountConfigURL, 'popupTitle':'Create An Account', 'clientId':clientId});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'97a8141f193919db',t:'MTc1NzA5OTk3MC4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
|
||||
</html>
|
||||
19
garth.go
19
garth.go
@@ -32,7 +32,6 @@ package garth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -41,15 +40,12 @@ import (
|
||||
|
||||
// Authenticator defines the authentication interface
|
||||
type Authenticator interface {
|
||||
// Login authenticates with Garmin services using OAuth1/OAuth2 hybrid flow
|
||||
// Login authenticates with Garmin services using OAuth2 flow
|
||||
Login(ctx context.Context, username, password, mfaToken string) (*Token, error)
|
||||
|
||||
// RefreshToken refreshes an expired OAuth2 access token
|
||||
RefreshToken(ctx context.Context, refreshToken string) (*Token, error)
|
||||
|
||||
// ExchangeToken exchanges OAuth1 token for OAuth2 token
|
||||
ExchangeToken(ctx context.Context, oauth1Token *OAuth1Token) (*Token, error)
|
||||
|
||||
// GetClient returns an authenticated HTTP client
|
||||
GetClient() *http.Client
|
||||
}
|
||||
@@ -89,16 +85,3 @@ func NewClientOptionsFromEnv() ClientOptions {
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
// getRequestToken retrieves OAuth1 request token
|
||||
// getRequestToken retrieves OAuth1 request token
|
||||
func getRequestToken(a Authenticator, ctx context.Context) (*OAuth1Token, error) {
|
||||
// Implementation will be added in next step
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// authorizeRequestToken authorizes OAuth1 token through SSO
|
||||
func authorizeRequestToken(a Authenticator, ctx context.Context, token *OAuth1Token) error {
|
||||
// Implementation will be added in next step
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
44
types.go
44
types.go
@@ -8,49 +8,23 @@ import (
|
||||
|
||||
// Unified Token Definitions
|
||||
|
||||
// OAuth1Token represents OAuth1 credentials
|
||||
type OAuth1Token struct {
|
||||
Token string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// OAuth2Token represents OAuth2 credentials
|
||||
type OAuth2Token struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
ExpiresAt int64 `json:"expires_at"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
// IsExpired checks if the token has expired
|
||||
func (t *OAuth2Token) IsExpired() bool {
|
||||
return time.Now().After(time.Unix(t.ExpiresAt, 0))
|
||||
}
|
||||
|
||||
// Token represents unified authentication credentials
|
||||
// Token represents authentication credentials
|
||||
type Token struct {
|
||||
Domain string `json:"domain"`
|
||||
OAuth1Token *OAuth1Token `json:"oauth1_token"`
|
||||
OAuth2Token *OAuth2Token `json:"oauth2_token"`
|
||||
UserProfile *UserProfile `json:"user_profile"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresAt int64 `json:"expires_at"`
|
||||
Domain string `json:"domain"`
|
||||
UserProfile *UserProfile `json:"user_profile"`
|
||||
}
|
||||
|
||||
// IsExpired checks if the OAuth2 token has expired
|
||||
// IsExpired checks if the token has expired (with 60 second buffer)
|
||||
func (t *Token) IsExpired() bool {
|
||||
if t.OAuth2Token == nil {
|
||||
return true
|
||||
}
|
||||
return t.OAuth2Token.IsExpired()
|
||||
return time.Now().Unix() >= (t.ExpiresAt - 60)
|
||||
}
|
||||
|
||||
// NeedsRefresh checks if token needs refresh (within 5 min expiry window)
|
||||
func (t *Token) NeedsRefresh() bool {
|
||||
if t.OAuth2Token == nil {
|
||||
return true
|
||||
}
|
||||
return time.Now().Add(5 * time.Minute).After(time.Unix(t.OAuth2Token.ExpiresAt, 0))
|
||||
return time.Now().Unix() >= (t.ExpiresAt - 300)
|
||||
}
|
||||
|
||||
// UserProfile represents Garmin user profile information
|
||||
|
||||
Reference in New Issue
Block a user