mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-04 04:46:01 +02:00
- Update changelog. - Update docs to cover authorization support. - Updates helm to support authorization, and policy file.
125 lines
4.4 KiB
Go
125 lines
4.4 KiB
Go
package clients // import "github.com/pomerium/pomerium/proxy/clients"
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
"github.com/pomerium/pomerium/internal/sessions"
|
|
pb "github.com/pomerium/pomerium/proto/authenticate"
|
|
)
|
|
|
|
// Authenticator provides the authenticate service interface
|
|
type Authenticator interface {
|
|
// Redeem takes a code and returns a validated session or an error
|
|
Redeem(context.Context, string) (*sessions.SessionState, error)
|
|
// Refresh attempts to refresh a valid session with a refresh token. Returns a refreshed session.
|
|
Refresh(context.Context, *sessions.SessionState) (*sessions.SessionState, error)
|
|
// Validate evaluates a given oidc id_token for validity. Returns validity and any error.
|
|
Validate(context.Context, string) (bool, error)
|
|
// Close closes the authenticator connection if any.
|
|
Close() error
|
|
}
|
|
|
|
// NewAuthenticateClient returns a new authenticate service client. Presently,
|
|
// only gRPC is supported and is always returned so name is ignored.
|
|
func NewAuthenticateClient(name string, opts *Options) (a Authenticator, err error) {
|
|
return NewGRPCAuthenticateClient(opts)
|
|
}
|
|
|
|
// NewGRPCAuthenticateClient returns a new authenticate service client.
|
|
func NewGRPCAuthenticateClient(opts *Options) (p *AuthenticateGRPC, err error) {
|
|
conn, err := NewGRPCClientConn(opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
authClient := pb.NewAuthenticatorClient(conn)
|
|
return &AuthenticateGRPC{Conn: conn, client: authClient}, nil
|
|
}
|
|
|
|
// AuthenticateGRPC is a gRPC implementation of an authenticator (authenticate client)
|
|
type AuthenticateGRPC struct {
|
|
Conn *grpc.ClientConn
|
|
client pb.AuthenticatorClient
|
|
}
|
|
|
|
// Redeem makes an RPC call to the authenticate service to creates a session state
|
|
// from an encrypted code provided as a result of an oauth2 callback process.
|
|
func (a *AuthenticateGRPC) Redeem(ctx context.Context, code string) (*sessions.SessionState, error) {
|
|
if code == "" {
|
|
return nil, errors.New("missing code")
|
|
}
|
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
protoSession, err := a.client.Authenticate(ctx, &pb.AuthenticateRequest{Code: code})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
session, err := pb.SessionFromProto(protoSession)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return session, nil
|
|
}
|
|
|
|
// Refresh makes an RPC call to the authenticate service to attempt to refresh the
|
|
// user's session. Requires a valid refresh token. Will return an error if the identity provider
|
|
// has revoked the session or if the refresh token is no longer valid in this context.
|
|
func (a *AuthenticateGRPC) Refresh(ctx context.Context, s *sessions.SessionState) (*sessions.SessionState, error) {
|
|
if s.RefreshToken == "" {
|
|
return nil, errors.New("missing refresh token")
|
|
}
|
|
req, err := pb.ProtoFromSession(s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// todo(bdd): handle request id in grpc receiver and add to ctx logger
|
|
// reqID, ok := middleware.IDFromCtx(ctx)
|
|
// if ok {
|
|
// md := metadata.Pairs("req_id", reqID)
|
|
// ctx = metadata.NewOutgoingContext(ctx, md)
|
|
// }
|
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
// todo(bdd): add grpc specific timeouts to main options
|
|
// todo(bdd): handle request id (metadata!?) in grpc receiver and add to ctx logger
|
|
reply, err := a.client.Refresh(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newSession, err := pb.SessionFromProto(reply)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newSession, nil
|
|
}
|
|
|
|
// Validate makes an RPC call to the authenticate service to validate the JWT id token;
|
|
// does NOT do nonce or revokation validation.
|
|
// https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
|
|
func (a *AuthenticateGRPC) Validate(ctx context.Context, idToken string) (bool, error) {
|
|
if idToken == "" {
|
|
return false, errors.New("missing id token")
|
|
}
|
|
// todo(bdd): add grpc specific timeouts to main options
|
|
// todo(bdd): handle request id in grpc receiver and add to ctx logger
|
|
// reqID, ok := middleware.IDFromCtx(ctx)
|
|
// if ok {
|
|
// md := metadata.Pairs("req_id", reqID)
|
|
// ctx = metadata.NewOutgoingContext(ctx, md)
|
|
// }
|
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
r, err := a.client.Validate(ctx, &pb.ValidateRequest{IdToken: idToken})
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return r.IsValid, nil
|
|
}
|
|
|
|
// Close tears down the ClientConn and all underlying connections.
|
|
func (a *AuthenticateGRPC) Close() error {
|
|
return a.Conn.Close()
|
|
}
|