mirror of
https://github.com/pomerium/pomerium.git
synced 2025-06-16 09:42:50 +02:00
authenticate: fix expiring user info endpoint (#2976)
* authenticate: fix expiring user info endpoint * add test
This commit is contained in:
parent
fbdbe9c86f
commit
2f328e7de0
4 changed files with 122 additions and 37 deletions
|
@ -16,7 +16,6 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
"github.com/pomerium/pomerium/internal/urlutil"
|
||||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||||
"github.com/pomerium/pomerium/pkg/webauthnutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ValidateOptions checks that configuration are complete and valid.
|
// ValidateOptions checks that configuration are complete and valid.
|
||||||
|
@ -125,25 +124,6 @@ func (a *Authenticate) updateProvider(cfg *config.Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authenticate) getWebAuthnURL(values url.Values) (*url.URL, error) {
|
|
||||||
uri, err := a.options.Load().GetAuthenticateURL()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uri = uri.ResolveReference(&url.URL{
|
|
||||||
Path: "/.pomerium/webauthn",
|
|
||||||
RawQuery: buildURLValues(values, url.Values{
|
|
||||||
urlutil.QueryDeviceType: {webauthnutil.DefaultDeviceType},
|
|
||||||
urlutil.QueryEnrollmentToken: nil,
|
|
||||||
urlutil.QueryRedirectURI: {uri.ResolveReference(&url.URL{
|
|
||||||
Path: "/.pomerium/device-enrolled",
|
|
||||||
}).String()},
|
|
||||||
}).Encode(),
|
|
||||||
})
|
|
||||||
return urlutil.NewSignedURL(a.state.Load().sharedKey, uri).Sign(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildURLValues creates a new url.Values map by traversing the keys in `defaults` and using the values
|
// buildURLValues creates a new url.Values map by traversing the keys in `defaults` and using the values
|
||||||
// from `values` if they exist, otherwise the provided defaults
|
// from `values` if they exist, otherwise the provided defaults
|
||||||
func buildURLValues(values, defaults url.Values) url.Values {
|
func buildURLValues(values, defaults url.Values) url.Values {
|
||||||
|
|
|
@ -448,6 +448,19 @@ func (a *Authenticate) userInfo(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx, span := trace.StartSpan(r.Context(), "authenticate.userInfo")
|
ctx, span := trace.StartSpan(r.Context(), "authenticate.userInfo")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
|
// if we came in with a redirect URI, save it to a cookie so it doesn't expire with the HMAC
|
||||||
|
if redirectURI := r.FormValue(urlutil.QueryRedirectURI); redirectURI != "" {
|
||||||
|
u := urlutil.GetAbsoluteURL(r)
|
||||||
|
u.RawQuery = ""
|
||||||
|
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: urlutil.QueryRedirectURI,
|
||||||
|
Value: redirectURI,
|
||||||
|
})
|
||||||
|
http.Redirect(w, r, u.String(), http.StatusFound)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
state := a.state.Load()
|
state := a.state.Load()
|
||||||
|
|
||||||
s, err := a.getSessionFromCtx(ctx)
|
s, err := a.getSessionFromCtx(ctx)
|
||||||
|
@ -626,23 +639,6 @@ func (a *Authenticate) revokeSession(ctx context.Context, w http.ResponseWriter,
|
||||||
return rawIDToken
|
return rawIDToken
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authenticate) getSignOutURL(r *http.Request) (*url.URL, error) {
|
|
||||||
uri, err := a.options.Load().GetAuthenticateURL()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uri = uri.ResolveReference(&url.URL{
|
|
||||||
Path: "/.pomerium/sign_out",
|
|
||||||
})
|
|
||||||
if redirectURI := r.FormValue(urlutil.QueryRedirectURI); redirectURI != "" {
|
|
||||||
uri.RawQuery = (&url.Values{
|
|
||||||
urlutil.QueryRedirectURI: {redirectURI},
|
|
||||||
}).Encode()
|
|
||||||
}
|
|
||||||
return urlutil.NewSignedURL(a.state.Load().sharedKey, uri).Sign(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Authenticate) getCurrentSession(ctx context.Context) (s *session.Session, isImpersonated bool, err error) {
|
func (a *Authenticate) getCurrentSession(ctx context.Context) (s *session.Session, isImpersonated bool, err error) {
|
||||||
client := a.state.Load().dataBrokerClient
|
client := a.state.Load().dataBrokerClient
|
||||||
|
|
||||||
|
|
57
authenticate/url.go
Normal file
57
authenticate/url.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package authenticate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/internal/urlutil"
|
||||||
|
"github.com/pomerium/pomerium/pkg/webauthnutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *Authenticate) getRedirectURI(r *http.Request) (string, bool) {
|
||||||
|
if v := r.FormValue(urlutil.QueryRedirectURI); v != "" {
|
||||||
|
return v, true
|
||||||
|
}
|
||||||
|
|
||||||
|
if c, err := r.Cookie(urlutil.QueryRedirectURI); err == nil {
|
||||||
|
return c.Value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Authenticate) getSignOutURL(r *http.Request) (*url.URL, error) {
|
||||||
|
uri, err := a.options.Load().GetAuthenticateURL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uri = uri.ResolveReference(&url.URL{
|
||||||
|
Path: "/.pomerium/sign_out",
|
||||||
|
})
|
||||||
|
if redirectURI, ok := a.getRedirectURI(r); ok {
|
||||||
|
uri.RawQuery = (&url.Values{
|
||||||
|
urlutil.QueryRedirectURI: {redirectURI},
|
||||||
|
}).Encode()
|
||||||
|
}
|
||||||
|
return urlutil.NewSignedURL(a.state.Load().sharedKey, uri).Sign(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Authenticate) getWebAuthnURL(values url.Values) (*url.URL, error) {
|
||||||
|
uri, err := a.options.Load().GetAuthenticateURL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
uri = uri.ResolveReference(&url.URL{
|
||||||
|
Path: "/.pomerium/webauthn",
|
||||||
|
RawQuery: buildURLValues(values, url.Values{
|
||||||
|
urlutil.QueryDeviceType: {webauthnutil.DefaultDeviceType},
|
||||||
|
urlutil.QueryEnrollmentToken: nil,
|
||||||
|
urlutil.QueryRedirectURI: {uri.ResolveReference(&url.URL{
|
||||||
|
Path: "/.pomerium/device-enrolled",
|
||||||
|
}).String()},
|
||||||
|
}).Encode(),
|
||||||
|
})
|
||||||
|
return urlutil.NewSignedURL(a.state.Load().sharedKey, uri).Sign(), nil
|
||||||
|
}
|
52
authenticate/url_test.go
Normal file
52
authenticate/url_test.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package authenticate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/internal/urlutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuthenticate_getRedirectURI(t *testing.T) {
|
||||||
|
t.Run("query", func(t *testing.T) {
|
||||||
|
r, err := http.NewRequest("GET", "https://www.example.com?"+(url.Values{
|
||||||
|
urlutil.QueryRedirectURI: {"https://www.example.com/redirect"},
|
||||||
|
}).Encode(), nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
a := new(Authenticate)
|
||||||
|
redirectURI, ok := a.getRedirectURI(r)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, "https://www.example.com/redirect", redirectURI)
|
||||||
|
})
|
||||||
|
t.Run("form", func(t *testing.T) {
|
||||||
|
r, err := http.NewRequest("POST", "https://www.example.com", strings.NewReader((url.Values{
|
||||||
|
urlutil.QueryRedirectURI: {"https://www.example.com/redirect"},
|
||||||
|
}).Encode()))
|
||||||
|
require.NoError(t, err)
|
||||||
|
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
a := new(Authenticate)
|
||||||
|
redirectURI, ok := a.getRedirectURI(r)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, "https://www.example.com/redirect", redirectURI)
|
||||||
|
})
|
||||||
|
t.Run("cookie", func(t *testing.T) {
|
||||||
|
r, err := http.NewRequest("GET", "https://www.example.com", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
r.AddCookie(&http.Cookie{
|
||||||
|
Name: urlutil.QueryRedirectURI,
|
||||||
|
Value: "https://www.example.com/redirect",
|
||||||
|
})
|
||||||
|
|
||||||
|
a := new(Authenticate)
|
||||||
|
redirectURI, ok := a.getRedirectURI(r)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, "https://www.example.com/redirect", redirectURI)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue