loginsrv

Unnamed repository; edit this file 'description' to name the repository.
git clone git@jamesshield.xyz:repos/loginsrv.git
Log | Files | Refs | README | LICENSE

oauth_test.go (6731B)


      1 package oauth2
      2 
      3 import (
      4 	"fmt"
      5 	. "github.com/stretchr/testify/assert"
      6 	"io/ioutil"
      7 	"net/http"
      8 	"net/http/httptest"
      9 	"net/url"
     10 	"strings"
     11 	"testing"
     12 )
     13 
     14 var testConfig = Config{
     15 	ClientID:     "client42",
     16 	ClientSecret: "secret",
     17 	AuthURL:      "http://auth-provider/auth",
     18 	TokenURL:     "http://auth-provider/token",
     19 	RedirectURI:  "http://localhost/callback",
     20 	Scope:        "email other",
     21 }
     22 
     23 func Test_StartFlow(t *testing.T) {
     24 	resp := httptest.NewRecorder()
     25 	StartFlow(testConfig, resp)
     26 
     27 	Equal(t, http.StatusFound, resp.Code)
     28 
     29 	// assert that we received a state cookie
     30 	cHeader := strings.Split(resp.Header().Get("Set-Cookie"), ";")[0]
     31 	Equal(t, stateCookieName, strings.Split(cHeader, "=")[0])
     32 	state := strings.Split(cHeader, "=")[1]
     33 
     34 	expectedLocation := fmt.Sprintf("%v?client_id=%v&redirect_uri=%v&response_type=code&scope=%v&state=%v",
     35 		testConfig.AuthURL,
     36 		testConfig.ClientID,
     37 		url.QueryEscape(testConfig.RedirectURI),
     38 		"email+other",
     39 		state,
     40 	)
     41 
     42 	Equal(t, expectedLocation, resp.Header().Get("Location"))
     43 }
     44 
     45 func Test_Authenticate(t *testing.T) {
     46 	// mock a server for token exchange
     47 	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
     48 		Equal(t, "POST", r.Method)
     49 		Equal(t, "application/x-www-form-urlencoded", r.Header.Get("Content-Type"))
     50 		Equal(t, "application/json", r.Header.Get("Accept"))
     51 
     52 		body, _ := ioutil.ReadAll(r.Body)
     53 		Equal(t, "client_id=client42&client_secret=secret&code=theCode&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%2Fcallback", string(body))
     54 
     55 		w.Header().Set("Content-Type", "application/json")
     56 		w.Write([]byte(`{"access_token":"e72e16c7e42f292c6912e7710c838347ae178b4a", "scope":"repo gist", "token_type":"bearer"}`))
     57 	}))
     58 	defer server.Close()
     59 
     60 	testConfigCopy := testConfig
     61 	testConfigCopy.TokenURL = server.URL
     62 
     63 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
     64 	request.Header.Set("Cookie", "oauthState=theState")
     65 	request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
     66 
     67 	tokenInfo, err := Authenticate(testConfigCopy, request)
     68 
     69 	NoError(t, err)
     70 	Equal(t, "e72e16c7e42f292c6912e7710c838347ae178b4a", tokenInfo.AccessToken)
     71 	Equal(t, "repo gist", tokenInfo.Scope)
     72 	Equal(t, "bearer", tokenInfo.TokenType)
     73 }
     74 
     75 func Test_Authenticate_CodeExchangeError(t *testing.T) {
     76 	var testReturnCode int
     77 	testResponseJSON := `{"error":"bad_verification_code","error_description":"The code passed is incorrect or expired.","error_uri":"https://developer.github.com/v3/oauth/#bad-verification-code"}`
     78 	// mock a server for token exchange
     79 	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
     80 		w.WriteHeader(testReturnCode)
     81 		w.Header().Set("Content-Type", "application/json")
     82 		w.Write([]byte(testResponseJSON))
     83 	}))
     84 	defer server.Close()
     85 
     86 	testConfigCopy := testConfig
     87 	testConfigCopy.TokenURL = server.URL
     88 
     89 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
     90 	request.Header.Set("Cookie", "oauthState=theState")
     91 	request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
     92 
     93 	testReturnCode = 500
     94 	tokenInfo, err := Authenticate(testConfigCopy, request)
     95 	Error(t, err)
     96 	EqualError(t, err, "error: expected http status 200 on token exchange, but got 500")
     97 	Equal(t, "", tokenInfo.AccessToken)
     98 
     99 	testReturnCode = 200
    100 	tokenInfo, err = Authenticate(testConfigCopy, request)
    101 	Error(t, err)
    102 	EqualError(t, err, `error: got "bad_verification_code" on token exchange`)
    103 	Equal(t, "", tokenInfo.AccessToken)
    104 
    105 	testReturnCode = 200
    106 	testResponseJSON = `{"foo": "bar"}`
    107 	tokenInfo, err = Authenticate(testConfigCopy, request)
    108 	Error(t, err)
    109 	EqualError(t, err, `error: no access_token on token exchange`)
    110 	Equal(t, "", tokenInfo.AccessToken)
    111 
    112 }
    113 
    114 func Test_Authentication_ProviderError(t *testing.T) {
    115 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
    116 	request.URL, _ = url.Parse("http://localhost/callback?error=provider_login_error")
    117 
    118 	_, err := Authenticate(testConfig, request)
    119 
    120 	Error(t, err)
    121 	Equal(t, "error: provider_login_error", err.Error())
    122 }
    123 
    124 func Test_Authentication_StateError(t *testing.T) {
    125 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
    126 	request.Header.Set("Cookie", "oauthState=XXXXXXX")
    127 	request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
    128 
    129 	_, err := Authenticate(testConfig, request)
    130 
    131 	Error(t, err)
    132 	Equal(t, "error: oauth state param could not be verified", err.Error())
    133 }
    134 
    135 func Test_Authentication_NoCodeError(t *testing.T) {
    136 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
    137 	request.Header.Set("Cookie", "oauthState=theState")
    138 	request.URL, _ = url.Parse("http://localhost/callback?state=theState")
    139 
    140 	_, err := Authenticate(testConfig, request)
    141 
    142 	Error(t, err)
    143 	Equal(t, "error: no auth code provided", err.Error())
    144 }
    145 
    146 func Test_Authentication_Provider500(t *testing.T) {
    147 	// mock a server for token exchange
    148 	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    149 		w.WriteHeader(500)
    150 	}))
    151 	defer server.Close()
    152 
    153 	testConfigCopy := testConfig
    154 	testConfigCopy.TokenURL = server.URL
    155 
    156 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
    157 	request.Header.Set("Cookie", "oauthState=theState")
    158 	request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
    159 
    160 	_, err := Authenticate(testConfigCopy, request)
    161 
    162 	Error(t, err)
    163 	Equal(t, "error: expected http status 200 on token exchange, but got 500", err.Error())
    164 }
    165 
    166 func Test_Authentication_ProviderNetworkError(t *testing.T) {
    167 
    168 	testConfigCopy := testConfig
    169 	testConfigCopy.TokenURL = "http://localhost:12345678"
    170 
    171 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
    172 	request.Header.Set("Cookie", "oauthState=theState")
    173 	request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
    174 
    175 	_, err := Authenticate(testConfigCopy, request)
    176 
    177 	Error(t, err)
    178 	Contains(t, err.Error(), "invalid port")
    179 }
    180 
    181 func Test_Authentication_TokenParseError(t *testing.T) {
    182 	// mock a server for token exchange
    183 	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    184 		w.WriteHeader(200)
    185 		w.Header().Set("Content-Type", "application/json")
    186 		w.Write([]byte(`{"access_t`))
    187 
    188 	}))
    189 	defer server.Close()
    190 
    191 	testConfigCopy := testConfig
    192 	testConfigCopy.TokenURL = server.URL
    193 
    194 	request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
    195 	request.Header.Set("Cookie", "oauthState=theState")
    196 	request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
    197 
    198 	_, err := Authenticate(testConfigCopy, request)
    199 
    200 	Error(t, err)
    201 	Equal(t, "error on parsing oauth token: unexpected end of JSON input", err.Error())
    202 }