mirror of
https://github.com/wahyd4/loginsrv.git
synced 2026-08-10 13:26:42 +10:00
203 lines
6.5 KiB
Go
203 lines
6.5 KiB
Go
package oauth2
|
|
|
|
import (
|
|
"fmt"
|
|
. "github.com/stretchr/testify/assert"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
var testConfig = Config{
|
|
ClientID: "client42",
|
|
ClientSecret: "secret",
|
|
AuthURL: "http://auth-provider/auth",
|
|
TokenURL: "http://auth-provider/token",
|
|
RedirectURI: "http://localhost/callback",
|
|
Scope: "email other",
|
|
}
|
|
|
|
func Test_StartFlow(t *testing.T) {
|
|
resp := httptest.NewRecorder()
|
|
StartFlow(testConfig, resp)
|
|
|
|
Equal(t, http.StatusFound, resp.Code)
|
|
|
|
// assert that we received a state cookie
|
|
cHeader := strings.Split(resp.Header().Get("Set-Cookie"), ";")[0]
|
|
Equal(t, stateCookieName, strings.Split(cHeader, "=")[0])
|
|
state := strings.Split(cHeader, "=")[1]
|
|
|
|
expectedLocation := fmt.Sprintf("%v?client_id=%v&redirect_uri=%v&response_type=code&scope=%v&state=%v",
|
|
testConfig.AuthURL,
|
|
testConfig.ClientID,
|
|
url.QueryEscape(testConfig.RedirectURI),
|
|
"email+other",
|
|
state,
|
|
)
|
|
|
|
Equal(t, expectedLocation, resp.Header().Get("Location"))
|
|
}
|
|
|
|
func Test_Authenticate(t *testing.T) {
|
|
// mock a server for token exchange
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
Equal(t, "POST", r.Method)
|
|
Equal(t, "application/x-www-form-urlencoded", r.Header.Get("Content-Type"))
|
|
Equal(t, "application/json", r.Header.Get("Accept"))
|
|
|
|
body, _ := ioutil.ReadAll(r.Body)
|
|
Equal(t, "client_id=client42&client_secret=secret&code=theCode", string(body))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"access_token":"e72e16c7e42f292c6912e7710c838347ae178b4a", "scope":"repo gist", "token_type":"bearer"}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
testConfigCopy := testConfig
|
|
testConfigCopy.TokenURL = server.URL
|
|
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=theState")
|
|
request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
|
|
|
|
tokenInfo, err := Authenticate(testConfigCopy, request)
|
|
|
|
NoError(t, err)
|
|
Equal(t, "e72e16c7e42f292c6912e7710c838347ae178b4a", tokenInfo.AccessToken)
|
|
Equal(t, "repo gist", tokenInfo.Scope)
|
|
Equal(t, "bearer", tokenInfo.TokenType)
|
|
}
|
|
|
|
func Test_Authenticate_CodeExchangeError(t *testing.T) {
|
|
var testReturnCode int
|
|
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"}`
|
|
// mock a server for token exchange
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(testReturnCode)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(testResponseJSON))
|
|
}))
|
|
defer server.Close()
|
|
|
|
testConfigCopy := testConfig
|
|
testConfigCopy.TokenURL = server.URL
|
|
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=theState")
|
|
request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
|
|
|
|
testReturnCode = 500
|
|
tokenInfo, err := Authenticate(testConfigCopy, request)
|
|
Error(t, err)
|
|
EqualError(t, err, "error: expected http status 200 on token exchange, but got 500")
|
|
Equal(t, "", tokenInfo.AccessToken)
|
|
|
|
testReturnCode = 200
|
|
tokenInfo, err = Authenticate(testConfigCopy, request)
|
|
Error(t, err)
|
|
EqualError(t, err, `error: got "bad_verification_code" on token exchange`)
|
|
Equal(t, "", tokenInfo.AccessToken)
|
|
|
|
testReturnCode = 200
|
|
testResponseJSON = `{"foo": "bar"}`
|
|
tokenInfo, err = Authenticate(testConfigCopy, request)
|
|
Error(t, err)
|
|
EqualError(t, err, `error: no access_token on token exchange`)
|
|
Equal(t, "", tokenInfo.AccessToken)
|
|
|
|
}
|
|
|
|
func Test_Authentication_ProviderError(t *testing.T) {
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.URL, _ = url.Parse("http://localhost/callback?error=provider_login_error")
|
|
|
|
_, err := Authenticate(testConfig, request)
|
|
|
|
Error(t, err)
|
|
Equal(t, "error: provider_login_error", err.Error())
|
|
}
|
|
|
|
func Test_Authentication_StateError(t *testing.T) {
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=XXXXXXX")
|
|
request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
|
|
|
|
_, err := Authenticate(testConfig, request)
|
|
|
|
Error(t, err)
|
|
Equal(t, "error: oauth state param could not be verified", err.Error())
|
|
}
|
|
|
|
func Test_Authentication_NoCodeError(t *testing.T) {
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=theState")
|
|
request.URL, _ = url.Parse("http://localhost/callback?state=theState")
|
|
|
|
_, err := Authenticate(testConfig, request)
|
|
|
|
Error(t, err)
|
|
Equal(t, "error: no auth code provided", err.Error())
|
|
}
|
|
|
|
func Test_Authentication_Provider500(t *testing.T) {
|
|
// mock a server for token exchange
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(500)
|
|
}))
|
|
defer server.Close()
|
|
|
|
testConfigCopy := testConfig
|
|
testConfigCopy.TokenURL = server.URL
|
|
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=theState")
|
|
request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
|
|
|
|
_, err := Authenticate(testConfigCopy, request)
|
|
|
|
Error(t, err)
|
|
Equal(t, "error: expected http status 200 on token exchange, but got 500", err.Error())
|
|
}
|
|
|
|
func Test_Authentication_ProviderNetworkError(t *testing.T) {
|
|
|
|
testConfigCopy := testConfig
|
|
testConfigCopy.TokenURL = "http://localhost:12345678"
|
|
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=theState")
|
|
request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
|
|
|
|
_, err := Authenticate(testConfigCopy, request)
|
|
|
|
Error(t, err)
|
|
Contains(t, err.Error(), "invalid port")
|
|
}
|
|
|
|
func Test_Authentication_TokenParseError(t *testing.T) {
|
|
// mock a server for token exchange
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(200)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{"access_t`))
|
|
|
|
}))
|
|
defer server.Close()
|
|
|
|
testConfigCopy := testConfig
|
|
testConfigCopy.TokenURL = server.URL
|
|
|
|
request, _ := http.NewRequest("GET", testConfig.RedirectURI, nil)
|
|
request.Header.Set("Cookie", "oauthState=theState")
|
|
request.URL, _ = url.Parse("http://localhost/callback?code=theCode&state=theState")
|
|
|
|
_, err := Authenticate(testConfigCopy, request)
|
|
|
|
Error(t, err)
|
|
Equal(t, "error on parsing oauth token: unexpected end of JSON input", err.Error())
|
|
}
|