mirror of
https://github.com/pomerium/pomerium.git
synced 2025-08-03 08:50:42 +02:00
store raw id token so it can be passed to the logout url (#1543)
This commit is contained in:
parent
6c4dfcfa88
commit
a85b3b04c1
11 changed files with 112 additions and 53 deletions
|
@ -11,6 +11,17 @@ import (
|
|||
"github.com/pomerium/pomerium/pkg/protoutil"
|
||||
)
|
||||
|
||||
// SessionClaims are claims that are attached to a session so we can store the raw id token.
|
||||
type SessionClaims struct {
|
||||
Claims
|
||||
RawIDToken string
|
||||
}
|
||||
|
||||
// SetRawIDToken sets the raw id token.
|
||||
func (claims *SessionClaims) SetRawIDToken(rawIDToken string) {
|
||||
claims.RawIDToken = rawIDToken
|
||||
}
|
||||
|
||||
// Claims are JWT claims.
|
||||
type Claims map[string]interface{}
|
||||
|
||||
|
|
7
internal/identity/identity/identity.go
Normal file
7
internal/identity/identity/identity.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Package identity is a package to avoid a dependency cycle.
|
||||
package identity
|
||||
|
||||
// State is the state for authentication.
|
||||
type State interface {
|
||||
SetRawIDToken(rawIDToken string)
|
||||
}
|
|
@ -15,6 +15,7 @@ import (
|
|||
"gopkg.in/tomb.v2"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/directory"
|
||||
"github.com/pomerium/pomerium/internal/identity/identity"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/scheduler"
|
||||
"github.com/pomerium/pomerium/pkg/grpc/databroker"
|
||||
|
@ -24,9 +25,9 @@ import (
|
|||
|
||||
// Authenticator is an identity.Provider with only the methods needed by the manager.
|
||||
type Authenticator interface {
|
||||
Refresh(context.Context, *oauth2.Token, interface{}) (*oauth2.Token, error)
|
||||
Refresh(context.Context, *oauth2.Token, identity.State) (*oauth2.Token, error)
|
||||
Revoke(context.Context, *oauth2.Token) error
|
||||
UpdateUserInfo(ctx context.Context, t *oauth2.Token, v interface{}) error
|
||||
UpdateUserInfo(context.Context, *oauth2.Token, interface{}) error
|
||||
}
|
||||
|
||||
type (
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"net/url"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/identity/identity"
|
||||
)
|
||||
|
||||
// MockProvider provides a mocked implementation of the providers interface.
|
||||
|
@ -21,12 +23,12 @@ type MockProvider struct {
|
|||
}
|
||||
|
||||
// Authenticate is a mocked providers function.
|
||||
func (mp MockProvider) Authenticate(context.Context, string, interface{}) (*oauth2.Token, error) {
|
||||
func (mp MockProvider) Authenticate(context.Context, string, identity.State) (*oauth2.Token, error) {
|
||||
return &mp.AuthenticateResponse, mp.AuthenticateError
|
||||
}
|
||||
|
||||
// Refresh is a mocked providers function.
|
||||
func (mp MockProvider) Refresh(context.Context, *oauth2.Token, interface{}) (*oauth2.Token, error) {
|
||||
func (mp MockProvider) Refresh(context.Context, *oauth2.Token, identity.State) (*oauth2.Token, error) {
|
||||
return &mp.RefreshResponse, mp.RefreshError
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/identity/identity"
|
||||
"github.com/pomerium/pomerium/internal/identity/oauth"
|
||||
"github.com/pomerium/pomerium/internal/identity/oidc"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
|
@ -77,7 +78,7 @@ func New(ctx context.Context, o *oauth.Options) (*Provider, error) {
|
|||
|
||||
// Authenticate creates an identity session with github from a authorization code, and follows up
|
||||
// call to the user and user group endpoint with the
|
||||
func (p *Provider) Authenticate(ctx context.Context, code string, v interface{}) (*oauth2.Token, error) {
|
||||
func (p *Provider) Authenticate(ctx context.Context, code string, v identity.State) (*oauth2.Token, error) {
|
||||
oauth2Token, err := p.Oauth.Exchange(ctx, code)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("github: token exchange failed %v", err)
|
||||
|
@ -112,7 +113,7 @@ func (p *Provider) UpdateUserInfo(ctx context.Context, t *oauth2.Token, v interf
|
|||
}
|
||||
|
||||
// Refresh is a no-op for github, because github sessions never expire.
|
||||
func (p *Provider) Refresh(ctx context.Context, t *oauth2.Token, v interface{}) (*oauth2.Token, error) {
|
||||
func (p *Provider) Refresh(ctx context.Context, t *oauth2.Token, v identity.State) (*oauth2.Token, error) {
|
||||
t.Expiry = time.Now().Add(refreshDeadline)
|
||||
return t, nil
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/identity/identity"
|
||||
"github.com/pomerium/pomerium/internal/identity/oauth"
|
||||
"github.com/pomerium/pomerium/internal/urlutil"
|
||||
"github.com/pomerium/pomerium/internal/version"
|
||||
|
@ -105,7 +106,7 @@ func (p *Provider) GetSignInURL(state string) string {
|
|||
|
||||
// Authenticate converts an authorization code returned from the identity
|
||||
// provider into a token which is then converted into a user session.
|
||||
func (p *Provider) Authenticate(ctx context.Context, code string, v interface{}) (*oauth2.Token, error) {
|
||||
func (p *Provider) Authenticate(ctx context.Context, code string, v identity.State) (*oauth2.Token, error) {
|
||||
// Exchange converts an authorization code into a token.
|
||||
oauth2Token, err := p.Oauth.Exchange(ctx, code)
|
||||
if err != nil {
|
||||
|
@ -117,6 +118,10 @@ func (p *Provider) Authenticate(ctx context.Context, code string, v interface{})
|
|||
return nil, fmt.Errorf("identity/oidc: failed getting id_token: %w", err)
|
||||
}
|
||||
|
||||
if rawIDToken, ok := oauth2Token.Extra("id_token").(string); ok {
|
||||
v.SetRawIDToken(rawIDToken)
|
||||
}
|
||||
|
||||
// hydrate `v` using claims inside the returned `id_token`
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
||||
if err := idToken.Claims(v); err != nil {
|
||||
|
@ -148,7 +153,7 @@ func (p *Provider) UpdateUserInfo(ctx context.Context, t *oauth2.Token, v interf
|
|||
// Refresh renews a user's session using an oidc refresh token without reprompting the user.
|
||||
// Group membership is also refreshed.
|
||||
// https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens
|
||||
func (p *Provider) Refresh(ctx context.Context, t *oauth2.Token, v interface{}) (*oauth2.Token, error) {
|
||||
func (p *Provider) Refresh(ctx context.Context, t *oauth2.Token, v identity.State) (*oauth2.Token, error) {
|
||||
if t == nil {
|
||||
return nil, ErrMissingAccessToken
|
||||
}
|
||||
|
@ -165,6 +170,10 @@ func (p *Provider) Refresh(ctx context.Context, t *oauth2.Token, v interface{})
|
|||
// https://github.com/FusionAuth/fusionauth-issues/issues/110#issuecomment-481526544
|
||||
idToken, err := p.getIDToken(ctx, newToken)
|
||||
if err == nil {
|
||||
if rawIDToken, ok := newToken.Extra("id_token").(string); ok {
|
||||
v.SetRawIDToken(rawIDToken)
|
||||
}
|
||||
|
||||
if err := idToken.Claims(v); err != nil {
|
||||
return nil, fmt.Errorf("identity/oidc: couldn't unmarshal extra claims %w", err)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/identity/identity"
|
||||
"github.com/pomerium/pomerium/internal/identity/oauth"
|
||||
"github.com/pomerium/pomerium/internal/identity/oauth/github"
|
||||
"github.com/pomerium/pomerium/internal/identity/oidc"
|
||||
|
@ -23,8 +24,8 @@ import (
|
|||
|
||||
// Authenticator is an interface representing the ability to authenticate with an identity provider.
|
||||
type Authenticator interface {
|
||||
Authenticate(context.Context, string, interface{}) (*oauth2.Token, error)
|
||||
Refresh(context.Context, *oauth2.Token, interface{}) (*oauth2.Token, error)
|
||||
Authenticate(context.Context, string, identity.State) (*oauth2.Token, error)
|
||||
Refresh(context.Context, *oauth2.Token, identity.State) (*oauth2.Token, error)
|
||||
Revoke(context.Context, *oauth2.Token) error
|
||||
GetSignInURL(state string) string
|
||||
Name() string
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue