mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-09 23:27:43 +02:00
proxy: add unit tests (#42)
- Fixed pomerium.io site description - Updated kubernetes examples to use the latest docker images. - Use cryputil hash function for proxy hmac. - Add unit tests for proxy handlers.
This commit is contained in:
parent
c886b924e7
commit
cedf9922d3
7 changed files with 336 additions and 40 deletions
|
@ -1,7 +1,7 @@
|
|||
// .vuepress/config.js
|
||||
module.exports = {
|
||||
title: "Pomerium",
|
||||
description: "Just playing around",
|
||||
description: "An open source identity-aware access proxy.",
|
||||
|
||||
themeConfig: {
|
||||
repo: "pomerium/pomerium",
|
||||
|
|
|
@ -16,7 +16,7 @@ spec:
|
|||
app: pomerium-authenticate
|
||||
spec:
|
||||
containers:
|
||||
- image: pomerium/pomerium:grpctest
|
||||
- image: pomerium/pomerium:latest
|
||||
name: pomerium-authenticate
|
||||
ports:
|
||||
- containerPort: 443
|
||||
|
|
|
@ -16,7 +16,7 @@ spec:
|
|||
app: pomerium-proxy
|
||||
spec:
|
||||
containers:
|
||||
- image: pomerium/pomerium:grpctest
|
||||
- image: pomerium/pomerium:latest
|
||||
name: pomerium-proxy
|
||||
ports:
|
||||
- containerPort: 443
|
||||
|
|
|
@ -2,7 +2,6 @@ package middleware // import "github.com/pomerium/pomerium/internal/middleware"
|
|||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -11,6 +10,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/cryptutil"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
)
|
||||
|
||||
|
@ -192,12 +192,12 @@ func ValidSignature(redirectURI, sigVal, timestamp, secret string) bool {
|
|||
return false
|
||||
}
|
||||
localSig := redirectURLSignature(redirectURI, tm, secret)
|
||||
|
||||
return hmac.Equal(requestSig, localSig)
|
||||
}
|
||||
|
||||
func redirectURLSignature(rawRedirect string, timestamp time.Time, secret string) []byte {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(rawRedirect))
|
||||
h.Write([]byte(fmt.Sprint(timestamp.Unix())))
|
||||
return h.Sum(nil)
|
||||
data := []byte(fmt.Sprint(rawRedirect, timestamp.Unix()))
|
||||
h := cryptutil.Hash(secret, data)
|
||||
return h
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ func Test_redirectURLSignature(t *testing.T) {
|
|||
secret string
|
||||
want string
|
||||
}{
|
||||
{"good signature", "https://example.com/redirect", time.Unix(1546797901, 0), "41aOD7VNtQ1/KZDCGrkYpaHwB50JC1y6BDs2KPRVd2A=", "GIDyWKjrG_7MwXwIq1o51f2pDT_rH9aLHdsHxSBEwy8="},
|
||||
{"good signature", "https://example.com/redirect", time.Unix(1546797901, 0), "K3yqsJPahIzu5CdfCVJlIK4N8Dc135-27Tg1ROuQdhc=", "XeVJC2Iysq7mRUwOL3FX_5vx1d_kZV2HONHNig9fcKk="},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package proxy // import "github.com/pomerium/pomerium/proxy"
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -85,7 +83,7 @@ func (p *Proxy) RobotsTxt(w http.ResponseWriter, _ *http.Request) {
|
|||
}
|
||||
|
||||
// Favicon will proxy the request as usual if the user is already authenticated but responds
|
||||
// with a 404 otherwise, to avoid spurious and confusing IdentityProvider attempts when a browser
|
||||
// with a 404 otherwise, to avoid spurious and confusing authenticate attempts when a browser
|
||||
// automatically requests the favicon on an error page.
|
||||
func (p *Proxy) Favicon(w http.ResponseWriter, r *http.Request) {
|
||||
err := p.Authenticate(w, r)
|
||||
|
@ -108,7 +106,7 @@ func (p *Proxy) SignOut(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, fullURL.String(), http.StatusFound)
|
||||
}
|
||||
|
||||
// OAuthStart begins the IdentityProvider flow, encrypting the redirect url
|
||||
// OAuthStart begins the authenticate flow, encrypting the redirect url
|
||||
// in a request to the provider's sign in endpoint.
|
||||
func (p *Proxy) OAuthStart(w http.ResponseWriter, r *http.Request) {
|
||||
requestURI := r.URL.String()
|
||||
|
@ -139,10 +137,8 @@ func (p *Proxy) OAuthStart(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
signinURL := p.GetSignInURL(p.AuthenticateURL, callbackURL, encryptedState)
|
||||
log.FromRequest(r).Info().
|
||||
Str("SigninURL", signinURL.String()).
|
||||
Msg("redirecting to begin auth flow")
|
||||
// redirect the user to the IdentityProvider provider along with the encrypted state which
|
||||
log.FromRequest(r).Info().Str("SigninURL", signinURL.String()).Msg("proxy: oauth start")
|
||||
// redirect the user to the authenticate provider along with the encrypted state which
|
||||
// contains a redirect uri pointing back to the proxy
|
||||
http.Redirect(w, r, signinURL.String(), http.StatusFound)
|
||||
}
|
||||
|
@ -239,10 +235,10 @@ func (p *Proxy) AuthenticateOnly(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Proxy authenticates a request, either proxying the request if it is authenticated,
|
||||
// or starting the IdentityProvider service for validation if not.
|
||||
// or starting the authenticate service for validation if not.
|
||||
func (p *Proxy) Proxy(w http.ResponseWriter, r *http.Request) {
|
||||
err := p.Authenticate(w, r)
|
||||
// If the IdentityProvider is not successful we proceed to start the OAuth Flow with
|
||||
// If the authenticate is not successful we proceed to start the OAuth Flow with
|
||||
// OAuthStart. If successful, we proceed to proxy to the configured upstream.
|
||||
if err != nil {
|
||||
switch err {
|
||||
|
@ -307,10 +303,7 @@ func (p *Proxy) Authenticate(w http.ResponseWriter, r *http.Request) (err error)
|
|||
}
|
||||
session.AccessToken = accessToken
|
||||
session.RefreshDeadline = expiry
|
||||
log.FromRequest(r).Info().
|
||||
Str("RefreshToken", session.RefreshToken).
|
||||
Str("AccessToken", session.AccessToken).
|
||||
Msg("proxy.Authenticate: refresh success")
|
||||
log.FromRequest(r).Info().Msg("proxy.Authenticate: refresh success")
|
||||
}
|
||||
|
||||
err = p.sessionStore.SaveSession(w, r, session)
|
||||
|
@ -340,24 +333,20 @@ func (p *Proxy) router(r *http.Request) (http.Handler, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
// GetRedirectURL returns the redirect url for a given Proxy,
|
||||
// setting the scheme to be https if CookieSecure is true.
|
||||
// GetRedirectURL returns the redirect url for a single reverse proxy host. HTTPS is set explicitly.
|
||||
func (p *Proxy) GetRedirectURL(host string) *url.URL {
|
||||
u := p.redirectURL
|
||||
// Build redirect URI from request host
|
||||
if u.Scheme == "" {
|
||||
u.Scheme = "https"
|
||||
}
|
||||
u.Host = host
|
||||
return u
|
||||
}
|
||||
|
||||
// signRedirectURL signs the redirect url string, given a timestamp, and returns it
|
||||
// signRedirectURL takes a redirect url string and timestamp and returns the base64
|
||||
// encoded HMAC result.
|
||||
func (p *Proxy) signRedirectURL(rawRedirect string, timestamp time.Time) string {
|
||||
h := hmac.New(sha256.New, []byte(p.SharedKey))
|
||||
h.Write([]byte(rawRedirect))
|
||||
h.Write([]byte(fmt.Sprint(timestamp.Unix())))
|
||||
return base64.URLEncoding.EncodeToString(h.Sum(nil))
|
||||
data := []byte(fmt.Sprint(rawRedirect, timestamp.Unix()))
|
||||
h := cryptutil.Hash(p.SharedKey, data)
|
||||
return base64.URLEncoding.EncodeToString(h)
|
||||
}
|
||||
|
||||
// GetSignInURL with typical oauth parameters
|
||||
|
|
|
@ -4,18 +4,20 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/version"
|
||||
)
|
||||
|
||||
func TestProxy_RobotsTxt(t *testing.T) {
|
||||
proxy := Proxy{}
|
||||
req, err := http.NewRequest("GET", "/robots.txt", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req := httptest.NewRequest("GET", "/robots.txt", nil)
|
||||
rr := httptest.NewRecorder()
|
||||
handler := http.HandlerFunc(proxy.RobotsTxt)
|
||||
handler.ServeHTTP(rr, req)
|
||||
proxy.RobotsTxt(rr, req)
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
@ -24,3 +26,308 @@ func TestProxy_RobotsTxt(t *testing.T) {
|
|||
t.Errorf("handler returned wrong body: got %v want %v", rr.Body.String(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_GetRedirectURL(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
host string
|
||||
want *url.URL
|
||||
}{
|
||||
{"google", "google.com", &url.URL{Scheme: "https", Host: "google.com", Path: "/.pomerium/callback"}},
|
||||
{"pomerium", "pomerium.io", &url.URL{Scheme: "https", Host: "pomerium.io", Path: "/.pomerium/callback"}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &Proxy{redirectURL: &url.URL{Path: "/.pomerium/callback"}}
|
||||
|
||||
if got := p.GetRedirectURL(tt.host); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Proxy.GetRedirectURL() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_signRedirectURL(t *testing.T) {
|
||||
fixedDate := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
rawRedirect string
|
||||
timestamp time.Time
|
||||
want string
|
||||
}{
|
||||
{"pomerium", "https://pomerium.io/.pomerium/callback", fixedDate, "wq3rAjRGN96RXS8TAzH-uxQTD0XgY_8ZYEKMiOLD5P4="},
|
||||
{"google", "https://google.com/.pomerium/callback", fixedDate, "7EYHZObq167CuyuPm5CqOtkU4zg5dFeUCs7W7QOrgNQ="},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &Proxy{}
|
||||
if got := p.signRedirectURL(tt.rawRedirect, tt.timestamp); got != tt.want {
|
||||
t.Errorf("Proxy.signRedirectURL() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_GetSignOutURL(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
authenticate string
|
||||
redirect string
|
||||
wantPrefix string
|
||||
}{
|
||||
{"without scheme", "auth.corp.pomerium.io", "hello.corp.pomerium.io", "https://auth.corp.pomerium.io/sign_out?redirect_uri=https%3A%2F%2Fhello.corp.pomerium.io"},
|
||||
{"with scheme", "https://auth.corp.pomerium.io", "https://hello.corp.pomerium.io", "https://auth.corp.pomerium.io/sign_out?redirect_uri=https%3A%2F%2Fhello.corp.pomerium.io"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
authenticateURL, _ := urlParse(tt.authenticate)
|
||||
redirectURL, _ := urlParse(tt.redirect)
|
||||
|
||||
p := &Proxy{}
|
||||
// signature is ignored as it is tested above. Avoids testing time.Now
|
||||
if got := p.GetSignOutURL(authenticateURL, redirectURL); !strings.HasPrefix(got.String(), tt.wantPrefix) {
|
||||
t.Errorf("Proxy.GetSignOutURL() = %v, wantPrefix %v", got.String(), tt.wantPrefix)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_GetSignInURL(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
authenticate string
|
||||
redirect string
|
||||
state string
|
||||
|
||||
wantPrefix string
|
||||
}{
|
||||
{"without scheme", "auth.corp.pomerium.io", "hello.corp.pomerium.io", "example_state", "https://auth.corp.pomerium.io/sign_in?redirect_uri=https%3A%2F%2Fhello.corp.pomerium.io&response_type=code&shared_secret=shared-secret"},
|
||||
{"with scheme", "https://auth.corp.pomerium.io", "https://hello.corp.pomerium.io", "example_state", "https://auth.corp.pomerium.io/sign_in?redirect_uri=https%3A%2F%2Fhello.corp.pomerium.io&response_type=code&shared_secret=shared-secret"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &Proxy{SharedKey: "shared-secret"}
|
||||
authenticateURL, _ := urlParse(tt.authenticate)
|
||||
redirectURL, _ := urlParse(tt.redirect)
|
||||
|
||||
if got := p.GetSignInURL(authenticateURL, redirectURL, tt.state); !strings.HasPrefix(got.String(), tt.wantPrefix) {
|
||||
t.Errorf("Proxy.GetSignOutURL() = %v, wantPrefix %v", got.String(), tt.wantPrefix)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxy_Favicon(t *testing.T) {
|
||||
proxy, err := New(testOptions())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req := httptest.NewRequest("GET", "/favicon.ico", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
proxy.Favicon(rr, req)
|
||||
if status := rr.Code; status != http.StatusNotFound {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNotFound)
|
||||
}
|
||||
// todo(bdd) : good way of mocking auth then serving a simple favicon?
|
||||
}
|
||||
|
||||
func TestProxy_Signout(t *testing.T) {
|
||||
proxy, err := New(testOptions())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req := httptest.NewRequest("GET", "/.pomerium/sign_out", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
proxy.SignOut(rr, req)
|
||||
if status := rr.Code; status != http.StatusFound {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusFound)
|
||||
}
|
||||
// todo(bdd) : good way of mocking auth then serving a simple favicon?
|
||||
}
|
||||
|
||||
func TestProxy_OAuthStart(t *testing.T) {
|
||||
proxy, err := New(testOptions())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req := httptest.NewRequest("GET", "/oauth-start", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
proxy.OAuthStart(rr, req)
|
||||
// expect oauth redirect
|
||||
if status := rr.Code; status != http.StatusFound {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusFound)
|
||||
}
|
||||
// expected url
|
||||
expected := `<a href="https://sso-auth.corp.beyondperimeter.com/sign_in`
|
||||
body := rr.Body.String()
|
||||
if !strings.HasPrefix(body, expected) {
|
||||
t.Errorf("handler returned unexpected body: got %v want %v", body, expected)
|
||||
}
|
||||
}
|
||||
func TestProxy_Handler(t *testing.T) {
|
||||
proxy, err := New(testOptions())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := proxy.Handler()
|
||||
if h == nil {
|
||||
t.Error("handler cannot be nil")
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", h)
|
||||
req := httptest.NewRequest("GET", "/ping", nil)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
mux.ServeHTTP(rr, req)
|
||||
expected := version.UserAgent()
|
||||
body := rr.Body.String()
|
||||
if body != expected {
|
||||
t.Errorf("handler returned unexpected body: got %v want %v", body, expected)
|
||||
}
|
||||
}
|
||||
|
||||
// func (p *Proxy) OAuthCallback(w http.ResponseWriter, r *http.Request) {
|
||||
// err := r.ParseForm()
|
||||
// if err != nil {
|
||||
// log.FromRequest(r).Error().Err(err).Msg("failed parsing request form")
|
||||
// httputil.ErrorResponse(w, r, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// errorString := r.Form.Get("error")
|
||||
// if errorString != "" {
|
||||
// httputil.ErrorResponse(w, r, errorString, http.StatusForbidden)
|
||||
// return
|
||||
// }
|
||||
// // We begin the process of redeeming the code for an access token.
|
||||
// session, err := p.AuthenticateRedeem(r.Form.Get("code"))
|
||||
// if err != nil {
|
||||
// log.FromRequest(r).Error().Err(err).Msg("error redeeming authorization code")
|
||||
// httputil.ErrorResponse(w, r, "Internal error", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// encryptedState := r.Form.Get("state")
|
||||
// stateParameter := &StateParameter{}
|
||||
// err = p.cipher.Unmarshal(encryptedState, stateParameter)
|
||||
// if err != nil {
|
||||
// log.FromRequest(r).Error().Err(err).Msg("could not unmarshal state")
|
||||
// httputil.ErrorResponse(w, r, "Internal error", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// c, err := p.csrfStore.GetCSRF(r)
|
||||
// if err != nil {
|
||||
// log.FromRequest(r).Error().Err(err).Msg("failed parsing csrf cookie")
|
||||
// httputil.ErrorResponse(w, r, err.Error(), http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
// p.csrfStore.ClearCSRF(w, r)
|
||||
|
||||
// encryptedCSRF := c.Value
|
||||
// csrfParameter := &StateParameter{}
|
||||
// err = p.cipher.Unmarshal(encryptedCSRF, csrfParameter)
|
||||
// if err != nil {
|
||||
// log.FromRequest(r).Error().Err(err).Msg("couldn't unmarshal CSRF")
|
||||
// httputil.ErrorResponse(w, r, "Internal error", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// if encryptedState == encryptedCSRF {
|
||||
// log.FromRequest(r).Error().Msg("encrypted state and CSRF should not be equal")
|
||||
// httputil.ErrorResponse(w, r, "Bad request", http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// if !reflect.DeepEqual(stateParameter, csrfParameter) {
|
||||
// log.FromRequest(r).Error().Msg("state and CSRF should be equal")
|
||||
// httputil.ErrorResponse(w, r, "Bad request", http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// // We store the session in a cookie and redirect the user back to the application
|
||||
// err = p.sessionStore.SaveSession(w, r, session)
|
||||
// if err != nil {
|
||||
// log.FromRequest(r).Error().Msg("error saving session")
|
||||
// httputil.ErrorResponse(w, r, "Error saving session", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// log.FromRequest(r).Info().
|
||||
// Str("code", r.Form.Get("code")).
|
||||
// Str("state", r.Form.Get("state")).
|
||||
// Str("RefreshToken", session.RefreshToken).
|
||||
// Str("session", session.AccessToken).
|
||||
// Str("RedirectURI", stateParameter.RedirectURI).
|
||||
// Msg("session")
|
||||
|
||||
// // This is the redirect back to the original requested application
|
||||
// http.Redirect(w, r, stateParameter.RedirectURI, http.StatusFound)
|
||||
// }
|
||||
|
||||
// func TestProxy_OAuthCallback2(t *testing.T) {
|
||||
// proxy, err := New(testOptions())
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// testError := url.Values{"error": []string{"There was a bad error to handle"}}
|
||||
// req := httptest.NewRequest("GET", "/oauth-callback", strings.NewReader(testError.Encode()))
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// rr := httptest.NewRecorder()
|
||||
// proxy.OAuthCallback)
|
||||
// // expect oauth redirect
|
||||
// if status := rr.Code; status != http.StatusInternalServerError {
|
||||
// t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusInternalServerError)
|
||||
// }
|
||||
// // expected url
|
||||
// // expected := `<a href="https://sso-auth.corp.beyondperimeter.com/sign_in`
|
||||
// // body := rr.Body.String()
|
||||
// // if !strings.HasPrefix(body, expected) {
|
||||
// // t.Errorf("handler returned unexpected body: got %v want %v", body, expected)
|
||||
// // }
|
||||
// }
|
||||
|
||||
func TestProxy_OAuthCallback(t *testing.T) {
|
||||
proxy, err := New(testOptions())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
method string
|
||||
params map[string]string
|
||||
wantCode int
|
||||
}{
|
||||
{"nil", http.MethodPost, nil, http.StatusInternalServerError},
|
||||
{"error", http.MethodPost, map[string]string{"error": "some error"}, http.StatusForbidden},
|
||||
{"state", http.MethodPost, map[string]string{"code": "code"}, http.StatusInternalServerError},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
req := httptest.NewRequest(tt.method, "/.pomerium/callback", nil)
|
||||
q := req.URL.Query()
|
||||
for k, v := range tt.params {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
fmt.Println("OK OK OK OK")
|
||||
|
||||
fmt.Println(req.URL.String())
|
||||
w := httptest.NewRecorder()
|
||||
proxy.OAuthCallback(w, req)
|
||||
if status := w.Code; status != tt.wantCode {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v", status, tt.wantCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue