github.com/snowflakedb/gosnowflake@v1.9.0/authexternalbrowser_test.go (about)

     1  // Copyright (c) 2022 Snowflake Computing Inc. All rights reserved.
     2  
     3  package gosnowflake
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"net/url"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  func TestGetTokenFromResponseFail(t *testing.T) {
    15  	response := "GET /?fakeToken=fakeEncodedSamlToken HTTP/1.1\r\n" +
    16  		"Host: localhost:54001\r\n" +
    17  		"Connection: keep-alive\r\n" +
    18  		"Upgrade-Insecure-Requests: 1\r\n" +
    19  		"User-Agent: userAgentStr\r\n" +
    20  		"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n" +
    21  		"Referer: https://myaccount.snowflakecomputing.com/fed/login\r\n" +
    22  		"Accept-Encoding: gzip, deflate, br\r\n" +
    23  		"Accept-Language: en-US,en;q=0.9\r\n\r\n"
    24  
    25  	_, err := getTokenFromResponse(response)
    26  	if err == nil {
    27  		t.Errorf("Should have failed parsing the malformed response.")
    28  	}
    29  }
    30  
    31  func TestGetTokenFromResponse(t *testing.T) {
    32  	response := "GET /?token=GETtokenFromResponse HTTP/1.1\r\n" +
    33  		"Host: localhost:54001\r\n" +
    34  		"Connection: keep-alive\r\n" +
    35  		"Upgrade-Insecure-Requests: 1\r\n" +
    36  		"User-Agent: userAgentStr\r\n" +
    37  		"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n" +
    38  		"Referer: https://myaccount.snowflakecomputing.com/fed/login\r\n" +
    39  		"Accept-Encoding: gzip, deflate, br\r\n" +
    40  		"Accept-Language: en-US,en;q=0.9\r\n\r\n"
    41  
    42  	expected := "GETtokenFromResponse"
    43  
    44  	token, err := getTokenFromResponse(response)
    45  	if err != nil {
    46  		t.Errorf("Failed to get the token. Err: %#v", err)
    47  	}
    48  	if token != expected {
    49  		t.Errorf("Expected: %s, found: %s", expected, token)
    50  	}
    51  }
    52  
    53  func TestBuildResponse(t *testing.T) {
    54  	resp := buildResponse("Go")
    55  	bytes := resp.Bytes()
    56  	respStr := string(bytes[:])
    57  	if !strings.Contains(respStr, "Your identity was confirmed and propagated to Snowflake Go.\nYou can close this window now and go back where you started from.") {
    58  		t.Fatalf("failed to build response")
    59  	}
    60  }
    61  
    62  func postAuthExternalBrowserError(_ context.Context, _ *snowflakeRestful, _ map[string]string, _ []byte, _ time.Duration) (*authResponse, error) {
    63  	return &authResponse{}, errors.New("failed to get SAML response")
    64  }
    65  
    66  func postAuthExternalBrowserFail(_ context.Context, _ *snowflakeRestful, _ map[string]string, _ []byte, _ time.Duration) (*authResponse, error) {
    67  	return &authResponse{
    68  		Success: false,
    69  		Message: "external browser auth failed",
    70  	}, nil
    71  }
    72  
    73  func postAuthExternalBrowserFailWithCode(_ context.Context, _ *snowflakeRestful, _ map[string]string, _ []byte, _ time.Duration) (*authResponse, error) {
    74  	return &authResponse{
    75  		Success: false,
    76  		Message: "failed to connect to db",
    77  		Code:    "260008",
    78  	}, nil
    79  }
    80  
    81  func TestUnitAuthenticateByExternalBrowser(t *testing.T) {
    82  	authenticator := "externalbrowser"
    83  	application := "testapp"
    84  	account := "testaccount"
    85  	user := "u"
    86  	password := "p"
    87  	timeout := defaultExternalBrowserTimeout
    88  	sr := &snowflakeRestful{
    89  		Protocol:         "https",
    90  		Host:             "abc.com",
    91  		Port:             443,
    92  		FuncPostAuthSAML: postAuthExternalBrowserError,
    93  		TokenAccessor:    getSimpleTokenAccessor(),
    94  	}
    95  	_, _, err := authenticateByExternalBrowser(context.Background(), sr, authenticator, application, account, user, password, timeout, ConfigBoolTrue)
    96  	if err == nil {
    97  		t.Fatal("should have failed.")
    98  	}
    99  	sr.FuncPostAuthSAML = postAuthExternalBrowserFail
   100  	_, _, err = authenticateByExternalBrowser(context.Background(), sr, authenticator, application, account, user, password, timeout, ConfigBoolTrue)
   101  	if err == nil {
   102  		t.Fatal("should have failed.")
   103  	}
   104  	sr.FuncPostAuthSAML = postAuthExternalBrowserFailWithCode
   105  	_, _, err = authenticateByExternalBrowser(context.Background(), sr, authenticator, application, account, user, password, timeout, ConfigBoolTrue)
   106  	if err == nil {
   107  		t.Fatal("should have failed.")
   108  	}
   109  	driverErr, ok := err.(*SnowflakeError)
   110  	if !ok {
   111  		t.Fatalf("should be snowflake error. err: %v", err)
   112  	}
   113  	if driverErr.Number != ErrCodeFailedToConnect {
   114  		t.Fatalf("unexpected error code. expected: %v, got: %v", ErrCodeFailedToConnect, driverErr.Number)
   115  	}
   116  }
   117  
   118  func TestAuthenticationTimeout(t *testing.T) {
   119  	authenticator := "externalbrowser"
   120  	application := "testapp"
   121  	account := "testaccount"
   122  	user := "u"
   123  	password := "p"
   124  	timeout := 0 * time.Second
   125  	sr := &snowflakeRestful{
   126  		Protocol:         "https",
   127  		Host:             "abc.com",
   128  		Port:             443,
   129  		FuncPostAuthSAML: postAuthExternalBrowserError,
   130  		TokenAccessor:    getSimpleTokenAccessor(),
   131  	}
   132  	_, _, err := authenticateByExternalBrowser(context.Background(), sr, authenticator, application, account, user, password, timeout, ConfigBoolTrue)
   133  	if err.Error() != "authentication timed out" {
   134  		t.Fatal("should have timed out")
   135  	}
   136  }
   137  
   138  func Test_createLocalTCPListener(t *testing.T) {
   139  	listener, err := createLocalTCPListener()
   140  	if err != nil {
   141  		t.Fatalf("createLocalTCPListener() failed: %v", err)
   142  	}
   143  	if listener == nil {
   144  		t.Fatal("createLocalTCPListener() returned nil listener")
   145  	}
   146  
   147  	// Close the listener after the test.
   148  	defer listener.Close()
   149  }
   150  
   151  func TestUnitGetLoginURL(t *testing.T) {
   152  	expectedScheme := "https"
   153  	expectedHost := "abc.com:443"
   154  	user := "u"
   155  	callbackPort := 123
   156  	sr := &snowflakeRestful{
   157  		Protocol:      "https",
   158  		Host:          "abc.com",
   159  		Port:          443,
   160  		TokenAccessor: getSimpleTokenAccessor(),
   161  	}
   162  
   163  	loginURL, proofKey, err := getLoginURL(sr, user, callbackPort)
   164  	assertNilF(t, err, "failed to get login URL")
   165  	assertNotNilF(t, len(proofKey), "proofKey should be non-empty string")
   166  
   167  	urlPtr, err := url.Parse(loginURL)
   168  	assertNilF(t, err, "failed to parse the login URL")
   169  	assertEqualF(t, urlPtr.Scheme, expectedScheme)
   170  	assertEqualF(t, urlPtr.Host, expectedHost)
   171  	assertEqualF(t, urlPtr.Path, consoleLoginRequestPath)
   172  	assertStringContainsF(t, urlPtr.RawQuery, "login_name")
   173  	assertStringContainsF(t, urlPtr.RawQuery, "browser_mode_redirect_port")
   174  	assertStringContainsF(t, urlPtr.RawQuery, "proof_key")
   175  }