mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-05 19:08:03 +02:00
Bumps the go group with 24 updates: | Package | From | To | | --- | --- | --- | | [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) | `1.53.0` | `1.55.0` | | [github.com/VictoriaMetrics/fastcache](https://github.com/VictoriaMetrics/fastcache) | `1.12.2` | `1.12.4` | | [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) | `1.79.3` | `1.80.0` | | [github.com/docker/docker](https://github.com/docker/docker) | `28.1.1+incompatible` | `28.2.2+incompatible` | | [github.com/exaring/otelpgx](https://github.com/exaring/otelpgx) | `0.9.1` | `0.9.3` | | [github.com/google/go-jsonnet](https://github.com/google/go-jsonnet) | `0.20.0` | `0.21.0` | | [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) | `5.7.4` | `5.7.5` | | [github.com/miekg/dns](https://github.com/miekg/dns) | `1.1.65` | `1.1.66` | | [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) | `7.0.91` | `7.0.92` | | [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) | `1.4.2` | `1.5.0` | | [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) | `0.8.0` | `0.8.1` | | [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) | `0.51.0` | `0.52.0` | | [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.60.0` | `0.61.0` | | [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.60.0` | `0.61.0` | | [go.opentelemetry.io/contrib/propagators/autoprop](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.60.0` | `0.61.0` | | [go.opentelemetry.io/otel/bridge/opencensus](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) | `1.35.0` | `1.36.0` | | [go.opentelemetry.io/proto/otlp](https://github.com/open-telemetry/opentelemetry-proto-go) | `1.6.0` | `1.7.0` | | [google.golang.org/api](https://github.com/googleapis/google-api-go-client) | `0.230.0` | `0.235.0` | | [google.golang.org/genproto/googleapis/rpc](https://github.com/googleapis/go-genproto) | `0.0.0-20250428153025-10db94c68c34` | `0.0.0-20250528174236-200df99c418a` | | [google.golang.org/grpc](https://github.com/grpc/grpc-go) | `1.72.0` | `1.72.2` | Updates `cloud.google.com/go/storage` from 1.53.0 to 1.55.0 - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](googleapis/google-cloud-go@spanner/v1.53.0...spanner/v1.55.0) Updates `github.com/VictoriaMetrics/fastcache` from 1.12.2 to 1.12.4 - [Release notes](https://github.com/VictoriaMetrics/fastcache/releases) - [Commits](VictoriaMetrics/fastcache@v1.12.2...v1.12.4) Updates `github.com/aws/aws-sdk-go-v2/service/s3` from 1.79.3 to 1.80.0 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json) - [Commits](aws/aws-sdk-go-v2@service/s3/v1.79.3...service/s3/v1.80.0) Updates `github.com/docker/docker` from 28.1.1+incompatible to 28.2.2+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](moby/moby@v28.1.1...v28.2.2) Updates `github.com/exaring/otelpgx` from 0.9.1 to 0.9.3 - [Release notes](https://github.com/exaring/otelpgx/releases) - [Commits](exaring/otelpgx@v0.9.1...v0.9.3) Updates `github.com/google/go-jsonnet` from 0.20.0 to 0.21.0 - [Release notes](https://github.com/google/go-jsonnet/releases) - [Changelog](https://github.com/google/go-jsonnet/blob/master/.goreleaser.yml) - [Commits](google/go-jsonnet@v0.20.0...v0.21.0) Updates `github.com/jackc/pgx/v5` from 5.7.4 to 5.7.5 - [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md) - [Commits](jackc/pgx@v5.7.4...v5.7.5) Updates `github.com/miekg/dns` from 1.1.65 to 1.1.66 - [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release) - [Commits](miekg/dns@v1.1.65...v1.1.66) Updates `github.com/minio/minio-go/v7` from 7.0.91 to 7.0.92 - [Release notes](https://github.com/minio/minio-go/releases) - [Commits](minio/minio-go@v7.0.91...v7.0.92) Updates `github.com/open-policy-agent/opa` from 1.4.2 to 1.5.0 - [Release notes](https://github.com/open-policy-agent/opa/releases) - [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md) - [Commits](open-policy-agent/opa@v1.4.2...v1.5.0) Updates `github.com/pires/go-proxyproto` from 0.8.0 to 0.8.1 - [Release notes](https://github.com/pires/go-proxyproto/releases) - [Commits](pires/go-proxyproto@v0.8.0...v0.8.1) Updates `github.com/quic-go/quic-go` from 0.51.0 to 0.52.0 - [Release notes](https://github.com/quic-go/quic-go/releases) - [Commits](quic-go/quic-go@v0.51.0...v0.52.0) Updates `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc` from 0.60.0 to 0.61.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.60.0...zpages/v0.61.0) Updates `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` from 0.60.0 to 0.61.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.60.0...zpages/v0.61.0) Updates `go.opentelemetry.io/contrib/propagators/autoprop` from 0.60.0 to 0.61.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.60.0...zpages/v0.61.0) Updates `go.opentelemetry.io/otel/bridge/opencensus` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` from 1.35.0 to 1.36.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.35.0...v1.36.0) Updates `go.opentelemetry.io/proto/otlp` from 1.6.0 to 1.7.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-proto-go/releases) - [Commits](open-telemetry/opentelemetry-proto-go@v1.6.0...v1.7.0) Updates `google.golang.org/api` from 0.230.0 to 0.235.0 - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](googleapis/google-api-go-client@v0.230.0...v0.235.0) Updates `google.golang.org/genproto/googleapis/rpc` from 0.0.0-20250428153025-10db94c68c34 to 0.0.0-20250528174236-200df99c418a - [Commits](https://github.com/googleapis/go-genproto/commits) Updates `google.golang.org/grpc` from 1.72.0 to 1.72.2 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](grpc/grpc-go@v1.72.0...v1.72.2) --- updated-dependencies: - dependency-name: cloud.google.com/go/storage dependency-version: 1.55.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/VictoriaMetrics/fastcache dependency-version: 1.12.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/aws/aws-sdk-go-v2/service/s3 dependency-version: 1.80.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/docker/docker dependency-version: 28.2.2+incompatible dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/exaring/otelpgx dependency-version: 0.9.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/google/go-jsonnet dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/jackc/pgx/v5 dependency-version: 5.7.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/miekg/dns dependency-version: 1.1.66 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/minio/minio-go/v7 dependency-version: 7.0.92 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/open-policy-agent/opa dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: github.com/pires/go-proxyproto dependency-version: 0.8.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: github.com/quic-go/quic-go dependency-version: 0.52.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/contrib/propagators/autoprop dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/bridge/opencensus dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: go.opentelemetry.io/proto/otlp dependency-version: 1.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: google.golang.org/api dependency-version: 0.235.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go - dependency-name: google.golang.org/genproto/googleapis/rpc dependency-version: 0.0.0-20250528174236-200df99c418a dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go - dependency-name: google.golang.org/grpc dependency-version: 1.72.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go ... Signed-off-by: dependabot[bot] <support@github.com>
731 lines
24 KiB
Go
731 lines
24 KiB
Go
package authenticate
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-jose/go-jose/v3/jwt"
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
oteltrace "go.opentelemetry.io/otel/trace"
|
|
"go.uber.org/mock/gomock"
|
|
"golang.org/x/crypto/chacha20poly1305"
|
|
"golang.org/x/oauth2"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
"github.com/pomerium/pomerium/config"
|
|
"github.com/pomerium/pomerium/internal/atomicutil"
|
|
"github.com/pomerium/pomerium/internal/encoding/jws"
|
|
"github.com/pomerium/pomerium/internal/encoding/mock"
|
|
"github.com/pomerium/pomerium/internal/handlers"
|
|
"github.com/pomerium/pomerium/internal/httputil"
|
|
"github.com/pomerium/pomerium/internal/sessions"
|
|
mstore "github.com/pomerium/pomerium/internal/sessions/mock"
|
|
"github.com/pomerium/pomerium/internal/testutil"
|
|
"github.com/pomerium/pomerium/internal/urlutil"
|
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
|
configproto "github.com/pomerium/pomerium/pkg/grpc/config"
|
|
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
|
"github.com/pomerium/pomerium/pkg/identity"
|
|
"github.com/pomerium/pomerium/pkg/identity/oidc"
|
|
)
|
|
|
|
func testAuthenticate(t *testing.T) *Authenticate {
|
|
opts := newTestOptions(t)
|
|
opts.AuthenticateURLString = "https://auth.example.com/oauth/callback"
|
|
auth, err := New(t.Context(), &config.Config{
|
|
Options: opts,
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
auth.state.Load().flow = new(stubFlow)
|
|
return auth
|
|
}
|
|
|
|
func TestAuthenticate_RobotsTxt(t *testing.T) {
|
|
auth := testAuthenticate(t)
|
|
req, err := http.NewRequest(http.MethodGet, "/robots.txt", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rr := httptest.NewRecorder()
|
|
handler := http.HandlerFunc(auth.RobotsTxt)
|
|
handler.ServeHTTP(rr, req)
|
|
if status := rr.Code; status != http.StatusOK {
|
|
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
|
|
}
|
|
expected := "User-agent: *\nDisallow: /"
|
|
if rr.Body.String() != expected {
|
|
t.Errorf("handler returned wrong body: got %v want %v", rr.Body.String(), expected)
|
|
}
|
|
}
|
|
|
|
func TestAuthenticate_Handler(t *testing.T) {
|
|
auth := testAuthenticate(t)
|
|
|
|
h := auth.Handler()
|
|
if h == nil {
|
|
t.Error("handler cannot be nil")
|
|
}
|
|
req := httptest.NewRequest(http.MethodGet, "/robots.txt", nil)
|
|
req.Header.Set("Accept", "application/json")
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, req)
|
|
expected := "User-agent: *\nDisallow: /"
|
|
|
|
body := rr.Body.String()
|
|
if body != expected {
|
|
t.Errorf("handler returned unexpected body: got %v want %v", body, expected)
|
|
}
|
|
|
|
// cors preflight
|
|
req = httptest.NewRequest(http.MethodOptions, "/.pomerium/sign_in", nil)
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("Access-Control-Request-Method", http.MethodGet)
|
|
req.Header.Set("Access-Control-Request-Headers", "X-Requested-With")
|
|
rr = httptest.NewRecorder()
|
|
h.ServeHTTP(rr, req)
|
|
expected = "User-agent: *\nDisallow: /"
|
|
code := rr.Code
|
|
if code/100 != 2 {
|
|
t.Errorf("bad preflight code %v", code)
|
|
}
|
|
resp := rr.Result()
|
|
body = resp.Header.Get("vary")
|
|
if body == "" {
|
|
t.Errorf("handler returned unexpected body: got %v want %v", body, expected)
|
|
}
|
|
}
|
|
|
|
func uriParseHelper(s string) *url.URL {
|
|
uri, _ := url.Parse(s)
|
|
return uri
|
|
}
|
|
|
|
func TestAuthenticate_SignOut(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
method string
|
|
|
|
ctxError error
|
|
redirectURL string
|
|
signoutRedirectURL string
|
|
sig string
|
|
ts string
|
|
|
|
provider identity.Authenticator
|
|
sessionStore sessions.SessionStore
|
|
wantCode int
|
|
wantBody string
|
|
wantLocation string
|
|
}{
|
|
{
|
|
"good post",
|
|
http.MethodPost,
|
|
nil,
|
|
"https://corp.pomerium.io/",
|
|
"",
|
|
"sig",
|
|
"ts",
|
|
identity.MockProvider{SignOutError: oidc.ErrSignoutNotImplemented},
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
|
http.StatusFound,
|
|
"",
|
|
"https://corp.pomerium.io/",
|
|
},
|
|
{
|
|
"signout redirect url",
|
|
http.MethodPost,
|
|
nil,
|
|
"",
|
|
"https://signout-redirect-url.example.com",
|
|
"sig",
|
|
"ts",
|
|
identity.MockProvider{SignOutError: oidc.ErrSignoutNotImplemented},
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
|
http.StatusFound,
|
|
"",
|
|
"https://signout-redirect-url.example.com",
|
|
},
|
|
{
|
|
"empty redirect url",
|
|
http.MethodPost,
|
|
nil,
|
|
"",
|
|
"",
|
|
"sig",
|
|
"ts",
|
|
identity.MockProvider{SignOutError: oidc.ErrSignoutNotImplemented},
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
|
http.StatusFound,
|
|
"",
|
|
"https://authenticate.pomerium.app/.pomerium/signed_out",
|
|
},
|
|
{
|
|
"failed revoke",
|
|
http.MethodPost,
|
|
nil,
|
|
"https://corp.pomerium.io/",
|
|
"",
|
|
"sig",
|
|
"ts",
|
|
identity.MockProvider{SignOutError: oidc.ErrSignoutNotImplemented, RevokeError: errors.New("OH NO")},
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
|
http.StatusFound,
|
|
"",
|
|
"https://corp.pomerium.io/",
|
|
},
|
|
{
|
|
"load session error",
|
|
http.MethodPost,
|
|
errors.New("error"),
|
|
"https://corp.pomerium.io/",
|
|
"",
|
|
"sig",
|
|
"ts",
|
|
identity.MockProvider{SignOutError: oidc.ErrSignoutNotImplemented, RevokeError: errors.New("OH NO")},
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
|
http.StatusFound,
|
|
"",
|
|
"https://corp.pomerium.io/",
|
|
},
|
|
{
|
|
"bad redirect uri",
|
|
http.MethodPost,
|
|
nil,
|
|
"corp.pomerium.io/",
|
|
"",
|
|
"sig",
|
|
"ts",
|
|
identity.MockProvider{SignOutError: oidc.ErrSignoutNotImplemented},
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{}},
|
|
http.StatusFound,
|
|
"",
|
|
"/corp.pomerium.io/",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
a := testAuthenticate(t)
|
|
a.cfg = getAuthenticateConfig(WithGetIdentityProvider(func(_ context.Context, _ oteltrace.TracerProvider, _ *config.Options, _ string) (identity.Authenticator, error) {
|
|
return tt.provider, nil
|
|
}))
|
|
a.state = atomicutil.NewValue(&authenticateState{
|
|
sessionStore: tt.sessionStore,
|
|
sharedEncoder: mock.Encoder{},
|
|
flow: new(stubFlow),
|
|
})
|
|
a.options = config.NewAtomicOptions()
|
|
if tt.signoutRedirectURL != "" {
|
|
opts := a.options.Load()
|
|
opts.SignOutRedirectURLString = tt.signoutRedirectURL
|
|
a.options.Store(opts)
|
|
}
|
|
u, _ := url.Parse("/sign_out")
|
|
params, _ := url.ParseQuery(u.RawQuery)
|
|
params.Add("sig", tt.sig)
|
|
params.Add("ts", tt.ts)
|
|
if tt.redirectURL != "" {
|
|
params.Add(urlutil.QueryRedirectURI, tt.redirectURL)
|
|
}
|
|
u.RawQuery = params.Encode()
|
|
r := httptest.NewRequest(tt.method, u.String(), nil)
|
|
state, err := tt.sessionStore.LoadSession(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := r.Context()
|
|
ctx = sessions.NewContext(ctx, state, tt.ctxError)
|
|
r = r.WithContext(ctx)
|
|
r.Header.Set("Accept", "application/json")
|
|
|
|
w := httptest.NewRecorder()
|
|
httputil.HandlerFunc(a.signOutRedirect).ServeHTTP(w, r)
|
|
if status := w.Code; status != tt.wantCode {
|
|
t.Errorf("handler returned wrong status code: got %v want %v", status, tt.wantCode)
|
|
}
|
|
body := w.Body.String()
|
|
if diff := cmp.Diff(body, tt.wantBody); diff != "" {
|
|
t.Errorf("handler returned wrong body Body: %s", diff)
|
|
}
|
|
loc := w.Header().Get("Location")
|
|
assert.Equal(t, tt.wantLocation, loc)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthenticate_SignOutDoesNotRequireSession(t *testing.T) {
|
|
// A direct sign_out request would not be signed.
|
|
f := new(stubFlow)
|
|
f.verifySignatureErr = errors.New("no signature")
|
|
|
|
sessionStore := &mstore.Store{LoadError: errors.New("no session")}
|
|
a := &Authenticate{
|
|
cfg: getAuthenticateConfig(WithGetIdentityProvider(func(_ context.Context, _ oteltrace.TracerProvider, _ *config.Options, _ string) (identity.Authenticator, error) {
|
|
return identity.MockProvider{}, nil
|
|
})),
|
|
state: atomicutil.NewValue(&authenticateState{
|
|
cookieSecret: cryptutil.NewKey(),
|
|
sessionLoader: sessionStore,
|
|
sessionStore: sessionStore,
|
|
sharedEncoder: mock.Encoder{},
|
|
flow: f,
|
|
}),
|
|
options: config.NewAtomicOptions(),
|
|
}
|
|
r := httptest.NewRequest(http.MethodGet, "/.pomerium/sign_out", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
a.Handler().ServeHTTP(w, r)
|
|
result := w.Result()
|
|
|
|
// The handler should serve a sign out confirmation page, not a login redirect.
|
|
expectedStatus := "200 OK"
|
|
if result.Status != expectedStatus {
|
|
t.Fatalf("wrong status code: got %q want %q", result.Status, expectedStatus)
|
|
}
|
|
body, _ := io.ReadAll(result.Body)
|
|
assert.Contains(t, string(body), `"page":"SignOutConfirm"`)
|
|
}
|
|
|
|
func TestAuthenticate_OAuthCallback(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
method string
|
|
|
|
ts int64
|
|
stateOvveride string
|
|
extraMac string
|
|
extraState string
|
|
paramErr string
|
|
code string
|
|
redirectURI string
|
|
|
|
authenticateURL string
|
|
session sessions.SessionStore
|
|
provider identity.MockProvider
|
|
|
|
want string
|
|
wantCode int
|
|
}{
|
|
{"good", http.MethodGet, time.Now().Unix(), "", "", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusFound},
|
|
{"failed authenticate", http.MethodGet, time.Now().Unix(), "", "", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}, AuthenticateError: errors.New("error")}, "", http.StatusInternalServerError},
|
|
{"failed save session", http.MethodGet, time.Now().Unix(), "", "", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{SaveError: errors.New("error")}, identity.MockProvider{}, "", http.StatusInternalServerError},
|
|
{"provider returned error", http.MethodGet, time.Now().Unix(), "", "", "", "idp error", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "", http.StatusBadRequest},
|
|
{"provider returned error imply 401", http.MethodGet, time.Now().Unix(), "", "", "", "access_denied", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "", http.StatusUnauthorized},
|
|
{"empty code", http.MethodGet, time.Now().Unix(), "", "", "", "", "", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "", http.StatusBadRequest},
|
|
{"invalid redirect uri", http.MethodGet, time.Now().Unix(), "", "", "", "", "code", "corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "", http.StatusBadRequest},
|
|
{"bad redirect uri", http.MethodGet, time.Now().Unix(), "", "", "", "", "code", "http://^^^", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
{"bad timing - too soon", http.MethodGet, time.Now().Add(1 * time.Hour).Unix(), "", "", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
{"bad timing - expired", http.MethodGet, time.Now().Add(-1 * time.Hour).Unix(), "", "", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
{"bad base64", http.MethodGet, time.Now().Unix(), "", "", "^", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
{"too many separators", http.MethodGet, time.Now().Unix(), "", "", "|ok|now|what", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
{"bad hmac", http.MethodGet, time.Now().Unix(), "", "NOTMAC", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
{"bad hmac", http.MethodGet, time.Now().Unix(), base64.URLEncoding.EncodeToString([]byte("malformed_state")), "", "", "", "code", "https://corp.pomerium.io", "https://authenticate.pomerium.io", &mstore.Store{}, identity.MockProvider{AuthenticateResponse: oauth2.Token{}}, "https://corp.pomerium.io", http.StatusBadRequest},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
aead, err := chacha20poly1305.NewX(cryptutil.NewKey())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
authURL, _ := url.Parse(tt.authenticateURL)
|
|
a := testAuthenticate(t)
|
|
a.cfg = getAuthenticateConfig(WithGetIdentityProvider(func(_ context.Context, _ oteltrace.TracerProvider, _ *config.Options, _ string) (identity.Authenticator, error) {
|
|
return tt.provider, nil
|
|
}))
|
|
a.state = atomicutil.NewValue(&authenticateState{
|
|
redirectURL: authURL,
|
|
sessionStore: tt.session,
|
|
cookieCipher: aead,
|
|
flow: new(stubFlow),
|
|
})
|
|
a.options = config.NewAtomicOptions()
|
|
u, _ := url.Parse("/oauthGet")
|
|
params, _ := url.ParseQuery(u.RawQuery)
|
|
params.Add("error", tt.paramErr)
|
|
params.Add("code", tt.code)
|
|
nonce := cryptutil.NewBase64Key() // mock csrf
|
|
// (nonce|timestamp|trace_id+flags|encrypt(redirect_url),mac(nonce,ts))
|
|
b := []byte(fmt.Sprintf("%s|%d||%s", nonce, tt.ts, tt.extraMac))
|
|
enc := cryptutil.Encrypt(a.state.Load().cookieCipher, []byte(tt.redirectURI), b)
|
|
b = append(b, enc...)
|
|
encodedState := base64.URLEncoding.EncodeToString(b)
|
|
if tt.extraState != "" {
|
|
encodedState += tt.extraState
|
|
}
|
|
if tt.stateOvveride != "" {
|
|
encodedState = tt.stateOvveride
|
|
}
|
|
params.Add("state", encodedState)
|
|
|
|
u.RawQuery = params.Encode()
|
|
|
|
r := httptest.NewRequest(tt.method, u.String(), nil)
|
|
r.Header.Set("Accept", "application/json")
|
|
w := httptest.NewRecorder()
|
|
httputil.HandlerFunc(a.OAuthCallback).ServeHTTP(w, r)
|
|
if w.Result().StatusCode != tt.wantCode {
|
|
t.Errorf("Authenticate.OAuthCallback() error = %v, wantErr %v\n%v", w.Result().StatusCode, tt.wantCode, w.Body.String())
|
|
return
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthenticate_SessionValidatorMiddleware(t *testing.T) {
|
|
t.Parallel()
|
|
fn := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
|
fmt.Fprintln(w, "RVSI FILIVS CAISAR")
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
|
|
idp, _ := new(config.Options).GetIdentityProviderForID("")
|
|
|
|
tests := []struct {
|
|
name string
|
|
headers map[string]string
|
|
|
|
session sessions.SessionStore
|
|
ctxError error
|
|
provider identity.Authenticator
|
|
|
|
wantStatus int
|
|
}{
|
|
{
|
|
"invalid session",
|
|
nil,
|
|
&mstore.Store{Session: &sessions.State{IdentityProviderID: idp.GetId(), ID: "xyz"}},
|
|
errors.New("hi"),
|
|
identity.MockProvider{},
|
|
http.StatusOK,
|
|
},
|
|
{
|
|
"expired,refresh error",
|
|
nil,
|
|
&mstore.Store{Session: &sessions.State{IdentityProviderID: idp.GetId(), ID: "xyz"}},
|
|
sessions.ErrExpired,
|
|
identity.MockProvider{RefreshError: errors.New("error")},
|
|
http.StatusOK,
|
|
},
|
|
{
|
|
"expired,save error",
|
|
nil,
|
|
&mstore.Store{SaveError: errors.New("error"), Session: &sessions.State{IdentityProviderID: idp.GetId(), ID: "xyz"}},
|
|
sessions.ErrExpired,
|
|
identity.MockProvider{RefreshResponse: oauth2.Token{Expiry: time.Now().Add(10 * time.Minute)}},
|
|
http.StatusOK,
|
|
},
|
|
{
|
|
"expired XHR,refresh error",
|
|
map[string]string{"X-Requested-With": "XmlHttpRequest"},
|
|
&mstore.Store{Session: &sessions.State{IdentityProviderID: idp.GetId(), ID: "xyz"}},
|
|
sessions.ErrExpired,
|
|
identity.MockProvider{RefreshError: errors.New("error")},
|
|
http.StatusUnauthorized,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
aead, err := chacha20poly1305.NewX(cryptutil.NewKey())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
signer, err := jws.NewHS256Signer(nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a := testAuthenticate(t)
|
|
a.cfg = getAuthenticateConfig(WithGetIdentityProvider(func(_ context.Context, _ oteltrace.TracerProvider, _ *config.Options, _ string) (identity.Authenticator, error) {
|
|
return tt.provider, nil
|
|
}))
|
|
a.state = atomicutil.NewValue(&authenticateState{
|
|
cookieSecret: cryptutil.NewKey(),
|
|
redirectURL: uriParseHelper("https://authenticate.corp.beyondperimeter.com"),
|
|
sessionStore: tt.session,
|
|
cookieCipher: aead,
|
|
sharedEncoder: signer,
|
|
flow: new(stubFlow),
|
|
})
|
|
a.options = config.NewAtomicOptions()
|
|
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
state, err := tt.session.LoadSession(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := r.Context()
|
|
ctx = sessions.NewContext(ctx, state, tt.ctxError)
|
|
r = r.WithContext(ctx)
|
|
|
|
r.Header.Set("Accept", "application/json")
|
|
if len(tt.headers) != 0 {
|
|
for k, v := range tt.headers {
|
|
r.Header.Set(k, v)
|
|
}
|
|
}
|
|
w := httptest.NewRecorder()
|
|
|
|
got := a.VerifySession(fn)
|
|
got.ServeHTTP(w, r)
|
|
if status := w.Code; status != tt.wantStatus {
|
|
t.Errorf("VerifySession() error = %v, wantErr %v\n%v\n%v", w.Result().StatusCode, tt.wantStatus, w.Header(), w.Body.String())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthenticate_userInfo(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("cookie-redirect-uri", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "https://authenticate.service.cluster.local/.pomerium/?pomerium_redirect_uri=https://www.example.com", nil)
|
|
a := testAuthenticate(t)
|
|
a.state = atomicutil.NewValue(&authenticateState{
|
|
cookieSecret: cryptutil.NewKey(),
|
|
flow: new(stubFlow),
|
|
})
|
|
a.options = config.NewAtomicOptions()
|
|
a.options.Store(&config.Options{
|
|
SharedKey: cryptutil.NewBase64Key(),
|
|
AuthenticateURLString: "https://authenticate.example.com",
|
|
AuthenticateInternalURLString: "https://authenticate.service.cluster.local",
|
|
})
|
|
err := a.userInfo(w, r)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, http.StatusFound, w.Code)
|
|
assert.Equal(t, "https://authenticate.example.com/.pomerium/", w.Header().Get("Location"))
|
|
})
|
|
|
|
now := time.Now()
|
|
tests := []struct {
|
|
name string
|
|
url string
|
|
validSignature bool
|
|
sessionStore sessions.SessionStore
|
|
wantCode int
|
|
}{
|
|
{
|
|
"not a redirect",
|
|
"/",
|
|
true,
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{ID: "SESSION_ID", IssuedAt: jwt.NewNumericDate(now)}},
|
|
http.StatusOK,
|
|
},
|
|
{
|
|
"signed redirect",
|
|
"/?pomerium_redirect_uri=http://example.com",
|
|
true,
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{ID: "SESSION_ID", IssuedAt: jwt.NewNumericDate(now)}},
|
|
http.StatusFound,
|
|
},
|
|
{
|
|
"invalid redirect",
|
|
"/?pomerium_redirect_uri=http://example.com",
|
|
false,
|
|
&mstore.Store{Encrypted: true, Session: &sessions.State{ID: "SESSION_ID", IssuedAt: jwt.NewNumericDate(now)}},
|
|
http.StatusBadRequest,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
signer, err := jws.NewHS256Signer(nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
o := config.NewAtomicOptions()
|
|
o.Store(&config.Options{
|
|
AuthenticateURLString: "https://authenticate.localhost.pomerium.io",
|
|
SharedKey: "SHARED KEY",
|
|
})
|
|
f := new(stubFlow)
|
|
if !tt.validSignature {
|
|
f.verifySignatureErr = errors.New("bad signature")
|
|
}
|
|
a := testAuthenticate(t)
|
|
a.options = o
|
|
a.state = atomicutil.NewValue(&authenticateState{
|
|
sessionStore: tt.sessionStore,
|
|
sharedEncoder: signer,
|
|
flow: f,
|
|
})
|
|
r := httptest.NewRequest(http.MethodGet, tt.url, nil)
|
|
state, err := tt.sessionStore.LoadSession(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := r.Context()
|
|
ctx = sessions.NewContext(ctx, state, nil)
|
|
r = r.WithContext(ctx)
|
|
r.Header.Set("Accept", "application/json")
|
|
|
|
w := httptest.NewRecorder()
|
|
a.requireValidSignatureOnRedirect(a.userInfo).ServeHTTP(w, r)
|
|
if status := w.Code; status != tt.wantCode {
|
|
t.Errorf("handler returned wrong status code: got %v want %v", status, tt.wantCode)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAuthenticate_CORS(t *testing.T) {
|
|
f := new(stubFlow)
|
|
auth := testAuthenticate(t)
|
|
state := auth.state.Load()
|
|
state.sessionLoader = &mstore.Store{Session: &sessions.State{}}
|
|
state.sharedEncoder = mock.Encoder{}
|
|
state.flow = f
|
|
auth.state.Store(state)
|
|
|
|
t.Run("unsigned", func(t *testing.T) {
|
|
f.verifySignatureErr = errors.New("no signature")
|
|
req, _ := http.NewRequest(http.MethodGet, "/.pomerium/", nil)
|
|
req.Header.Set("Origin", "foo.example.com")
|
|
rr := httptest.NewRecorder()
|
|
logOutput := testutil.CaptureLogs(t, func() {
|
|
auth.Handler().ServeHTTP(rr, req)
|
|
})
|
|
assert.NotContains(t, logOutput, "authenticate: signed URL")
|
|
h := rr.Result().Header
|
|
assert.Empty(t, h.Get("Access-Control-Allow-Credentials"))
|
|
assert.Empty(t, h.Get("Access-Control-Allow-Origin"))
|
|
})
|
|
t.Run("signed", func(t *testing.T) {
|
|
f.verifySignatureErr = nil
|
|
req, _ := http.NewRequest(http.MethodGet, "/.pomerium/", nil)
|
|
req.Header.Set("Origin", "foo.example.com")
|
|
rr := httptest.NewRecorder()
|
|
logOutput := testutil.CaptureLogs(t, func() {
|
|
auth.Handler().ServeHTTP(rr, req)
|
|
})
|
|
assert.Contains(t, logOutput,
|
|
`{"level":"info","message":"authenticate: signed URL, adding CORS headers"}`)
|
|
h := rr.Result().Header
|
|
assert.Equal(t, "true", h.Get("Access-Control-Allow-Credentials"))
|
|
assert.Equal(t, "foo.example.com", h.Get("Access-Control-Allow-Origin"))
|
|
})
|
|
}
|
|
|
|
func TestSignOutBranding(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
auth := testAuthenticate(t)
|
|
auth.state.Load().flow.(*stubFlow).verifySignatureErr = errors.New("unsigned URL")
|
|
auth.options.Store(&config.Options{
|
|
BrandingOptions: &configproto.Settings{
|
|
PrimaryColor: proto.String("red"),
|
|
SecondaryColor: proto.String("orange"),
|
|
},
|
|
})
|
|
|
|
t.Run("sign_out", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "/.pomerium/sign_out", nil)
|
|
err := auth.SignOut(w, r)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, w.Code)
|
|
|
|
b, err := io.ReadAll(w.Body)
|
|
require.NoError(t, err)
|
|
|
|
assert.Contains(t, string(b), `"primaryColor":"red","secondaryColor":"orange"`)
|
|
})
|
|
|
|
t.Run("signed_out", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodGet, "/.pomerium/signed_out", nil)
|
|
err := auth.signedOut(w, r)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, w.Code)
|
|
|
|
b, err := io.ReadAll(w.Body)
|
|
require.NoError(t, err)
|
|
|
|
assert.Contains(t, string(b), `"primaryColor":"red","secondaryColor":"orange"`)
|
|
})
|
|
}
|
|
|
|
type mockDataBrokerServiceClient struct {
|
|
databroker.DataBrokerServiceClient
|
|
|
|
get func(ctx context.Context, in *databroker.GetRequest, opts ...grpc.CallOption) (*databroker.GetResponse, error)
|
|
put func(ctx context.Context, in *databroker.PutRequest, opts ...grpc.CallOption) (*databroker.PutResponse, error)
|
|
}
|
|
|
|
func (m mockDataBrokerServiceClient) Get(ctx context.Context, in *databroker.GetRequest, opts ...grpc.CallOption) (*databroker.GetResponse, error) {
|
|
return m.get(ctx, in, opts...)
|
|
}
|
|
|
|
func (m mockDataBrokerServiceClient) Put(ctx context.Context, in *databroker.PutRequest, opts ...grpc.CallOption) (*databroker.PutResponse, error) {
|
|
return m.put(ctx, in, opts...)
|
|
}
|
|
|
|
// stubFlow is a stub implementation of the flow interface.
|
|
type stubFlow struct {
|
|
verifySignatureErr error
|
|
}
|
|
|
|
func (f *stubFlow) VerifyAuthenticateSignature(*http.Request) error {
|
|
return f.verifySignatureErr
|
|
}
|
|
|
|
func (*stubFlow) SignIn(http.ResponseWriter, *http.Request, *sessions.State) error {
|
|
return nil
|
|
}
|
|
|
|
func (*stubFlow) PersistSession(
|
|
context.Context, http.ResponseWriter, *sessions.State, identity.SessionClaims, *oauth2.Token,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
func (*stubFlow) VerifySession(context.Context, *http.Request, *sessions.State) error {
|
|
return nil
|
|
}
|
|
|
|
func (*stubFlow) RevokeSession(
|
|
context.Context, *http.Request, identity.Authenticator, *sessions.State,
|
|
) string {
|
|
return ""
|
|
}
|
|
|
|
func (*stubFlow) GetUserInfoData(*http.Request, *sessions.State) handlers.UserInfoData {
|
|
return handlers.UserInfoData{}
|
|
}
|
|
|
|
func (*stubFlow) LogAuthenticateEvent(*http.Request) {}
|
|
|
|
func (*stubFlow) GetIdentityProviderIDForURLValues(url.Values) string {
|
|
return ""
|
|
}
|