cleanup
This commit is contained in:
parent
5b6175acfc
commit
64797c1df6
9 changed files with 39 additions and 44 deletions
|
@ -152,7 +152,7 @@ func (s *AuthStorage) AuthRequestByID(_ context.Context, id string) (op.AuthRequ
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
func (s *AuthStorage) CreateToken(_ context.Context, authReq op.TokenRequest) (string, time.Time, error) {
|
func (s *AuthStorage) CreateToken(_ context.Context, authReq op.TokenRequest) (string, time.Time, error) {
|
||||||
return "authReq.GetID()", time.Now().UTC().Add(5 * time.Minute), nil
|
return "id", time.Now().UTC().Add(5 * time.Minute), nil
|
||||||
}
|
}
|
||||||
func (s *AuthStorage) TerminateSession(_ context.Context, userID, clientID string) error {
|
func (s *AuthStorage) TerminateSession(_ context.Context, userID, clientID string) error {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -23,7 +23,7 @@ type TokenExchangeRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type JWTProfileRequest struct {
|
type JWTProfileRequest struct {
|
||||||
assertion string `schema:"assertion"`
|
Assertion string `schema:"assertion"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTokenExchangeRequest(subjectToken, subjectTokenType string, opts ...TokenExchangeOption) *TokenExchangeRequest {
|
func NewTokenExchangeRequest(subjectToken, subjectTokenType string, opts ...TokenExchangeOption) *TokenExchangeRequest {
|
||||||
|
|
|
@ -212,7 +212,7 @@ func (o *openidProvider) IDTokenHintVerifier() IDTokenHintVerifier {
|
||||||
|
|
||||||
func (o *openidProvider) JWTProfileVerifier() JWTProfileVerifier {
|
func (o *openidProvider) JWTProfileVerifier() JWTProfileVerifier {
|
||||||
if o.jwtProfileVerifier == nil {
|
if o.jwtProfileVerifier == nil {
|
||||||
o.jwtProfileVerifier = NewJWTProfileVerifier(o.Storage(), o.Issuer())
|
o.jwtProfileVerifier = NewJWTProfileVerifier(o.Storage(), o.Issuer(), 1*time.Hour, time.Second)
|
||||||
}
|
}
|
||||||
return o.jwtProfileVerifier
|
return o.jwtProfileVerifier
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package op
|
package op
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"gopkg.in/square/go-jose.v2"
|
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
|
||||||
"github.com/caos/oidc/pkg/oidc"
|
"github.com/caos/oidc/pkg/oidc"
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,7 +15,6 @@ type TokenCreator interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenRequest interface {
|
type TokenRequest interface {
|
||||||
GetClientID() string
|
|
||||||
GetSubject() string
|
GetSubject() string
|
||||||
GetAudience() []string
|
GetAudience() []string
|
||||||
GetScopes() []string
|
GetScopes() []string
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/caos/oidc/pkg/oidc"
|
"github.com/caos/oidc/pkg/oidc"
|
||||||
|
"github.com/caos/oidc/pkg/oidc/grants/tokenexchange"
|
||||||
"github.com/caos/oidc/pkg/utils"
|
"github.com/caos/oidc/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -161,14 +162,12 @@ func ParseJWTProfileRequest(r *http.Request, decoder utils.Decoder) (string, err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ErrInvalidRequest("error parsing form")
|
return "", ErrInvalidRequest("error parsing form")
|
||||||
}
|
}
|
||||||
tokenReq := new(struct {
|
tokenReq := new(tokenexchange.JWTProfileRequest)
|
||||||
Token string `schema:"assertion"`
|
|
||||||
})
|
|
||||||
err = decoder.Decode(tokenReq, r.Form)
|
err = decoder.Decode(tokenReq, r.Form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ErrInvalidRequest("error decoding form")
|
return "", ErrInvalidRequest("error decoding form")
|
||||||
}
|
}
|
||||||
return tokenReq.Token, nil
|
return tokenReq.Assertion, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TokenExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
func TokenExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||||
|
|
|
@ -16,14 +16,18 @@ type JWTProfileVerifier interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type jwtProfileVerifier struct {
|
type jwtProfileVerifier struct {
|
||||||
storage Storage
|
storage Storage
|
||||||
issuer string
|
issuer string
|
||||||
|
maxAgeIAT time.Duration
|
||||||
|
offset time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJWTProfileVerifier(storage Storage, issuer string) JWTProfileVerifier {
|
func NewJWTProfileVerifier(storage Storage, issuer string, maxAgeIAT, offset time.Duration) JWTProfileVerifier {
|
||||||
return &jwtProfileVerifier{
|
return &jwtProfileVerifier{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
issuer: issuer,
|
issuer: issuer,
|
||||||
|
maxAgeIAT: maxAgeIAT,
|
||||||
|
offset: offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +40,11 @@ func (v *jwtProfileVerifier) Storage() Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *jwtProfileVerifier) MaxAgeIAT() time.Duration {
|
func (v *jwtProfileVerifier) MaxAgeIAT() time.Duration {
|
||||||
//TODO: define in conf/opts
|
return v.maxAgeIAT
|
||||||
return 1 * time.Hour
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *jwtProfileVerifier) Offset() time.Duration {
|
func (v *jwtProfileVerifier) Offset() time.Duration {
|
||||||
//TODO: define in conf/opts
|
return v.offset
|
||||||
return time.Second
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyJWTAssertion(ctx context.Context, assertion string, v JWTProfileVerifier) (*oidc.JWTTokenRequest, error) {
|
func VerifyJWTAssertion(ctx context.Context, assertion string, v JWTProfileVerifier) (*oidc.JWTTokenRequest, error) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/caos/oidc/pkg/oidc"
|
"github.com/caos/oidc/pkg/oidc"
|
||||||
"github.com/caos/oidc/pkg/oidc/grants"
|
"github.com/caos/oidc/pkg/oidc/grants"
|
||||||
"github.com/caos/oidc/pkg/utils"
|
"github.com/caos/oidc/pkg/utils"
|
||||||
|
@ -31,12 +33,16 @@ type RelayingParty interface {
|
||||||
//CookieHandler returns a http cookie handler used for various state transfer cookies
|
//CookieHandler returns a http cookie handler used for various state transfer cookies
|
||||||
CookieHandler() *utils.CookieHandler
|
CookieHandler() *utils.CookieHandler
|
||||||
|
|
||||||
//Client return a standard http client where the token can be used
|
//HttpClient returns a http client used for calls to the openid provider, e.g. calling token endpoint
|
||||||
Client(ctx context.Context, token *oauth2.Token) *http.Client
|
|
||||||
|
|
||||||
HttpClient() *http.Client
|
HttpClient() *http.Client
|
||||||
|
|
||||||
|
//IsOAuth2Only specifies whether relaying party handles only oauth2 or oidc calls
|
||||||
IsOAuth2Only() bool
|
IsOAuth2Only() bool
|
||||||
|
|
||||||
|
//IDTokenVerifier returns the verifier interface used for oidc id_token verification
|
||||||
IDTokenVerifier() IDTokenVerifier
|
IDTokenVerifier() IDTokenVerifier
|
||||||
|
|
||||||
|
//ErrorHandler returns the handler used for callback errors
|
||||||
ErrorHandler() func(http.ResponseWriter, *http.Request, string, string, string)
|
ErrorHandler() func(http.ResponseWriter, *http.Request, string, string, string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +96,6 @@ func (rp *relayingParty) IDTokenVerifier() IDTokenVerifier {
|
||||||
return rp.idTokenVerifier
|
return rp.idTokenVerifier
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rp *relayingParty) Client(ctx context.Context, token *oauth2.Token) *http.Client {
|
|
||||||
return rp.oauthConfig.Client(ctx, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rp *relayingParty) ErrorHandler() func(http.ResponseWriter, *http.Request, string, string, string) {
|
func (rp *relayingParty) ErrorHandler() func(http.ResponseWriter, *http.Request, string, string, string) {
|
||||||
if rp.errorHandler == nil {
|
if rp.errorHandler == nil {
|
||||||
rp.errorHandler = DefaultErrorHandler
|
rp.errorHandler = DefaultErrorHandler
|
||||||
|
@ -234,18 +236,17 @@ func AuthURLHandler(stateFn func() string, rp RelayingParty) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//GenerateAndStoreCodeChallenge generates a PKCE code challenge and stores its verifier into a secure cookie
|
||||||
func GenerateAndStoreCodeChallenge(w http.ResponseWriter, rp RelayingParty) (string, error) {
|
func GenerateAndStoreCodeChallenge(w http.ResponseWriter, rp RelayingParty) (string, error) {
|
||||||
var codeVerifier string
|
codeVerifier := uuid.New().String()
|
||||||
codeVerifier = "s"
|
|
||||||
if err := rp.CookieHandler().SetCookie(w, pkceCode, codeVerifier); err != nil {
|
if err := rp.CookieHandler().SetCookie(w, pkceCode, codeVerifier); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return oidc.NewSHACodeChallenge(codeVerifier), nil
|
return oidc.NewSHACodeChallenge(codeVerifier), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//AuthURL is the `RelayingParty` interface implementation
|
//CodeExchange handles the oauth2 code exchange, extracting and validating the id_token
|
||||||
//handling the oauth2 code exchange, extracting and validating the id_token
|
//returning it parsed together with the oauth2 tokens (access, refresh)
|
||||||
//returning it paresed together with the oauth2 tokens (access, refresh)
|
|
||||||
func CodeExchange(ctx context.Context, code string, rp RelayingParty, opts ...CodeExchangeOpt) (tokens *oidc.Tokens, err error) {
|
func CodeExchange(ctx context.Context, code string, rp RelayingParty, opts ...CodeExchangeOpt) (tokens *oidc.Tokens, err error) {
|
||||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, rp.HttpClient())
|
ctx = context.WithValue(ctx, oauth2.HTTPClient, rp.HttpClient())
|
||||||
codeOpts := make([]oauth2.AuthCodeOption, 0)
|
codeOpts := make([]oauth2.AuthCodeOption, 0)
|
||||||
|
@ -255,7 +256,7 @@ func CodeExchange(ctx context.Context, code string, rp RelayingParty, opts ...Co
|
||||||
|
|
||||||
token, err := rp.OAuthConfig().Exchange(ctx, code, codeOpts...)
|
token, err := rp.OAuthConfig().Exchange(ctx, code, codeOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err //TODO: our error
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if rp.IsOAuth2Only() {
|
if rp.IsOAuth2Only() {
|
||||||
|
@ -275,8 +276,9 @@ func CodeExchange(ctx context.Context, code string, rp RelayingParty, opts ...Co
|
||||||
return &oidc.Tokens{Token: token, IDTokenClaims: idToken, IDToken: idTokenString}, nil
|
return &oidc.Tokens{Token: token, IDTokenClaims: idToken, IDToken: idTokenString}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//AuthURL is the `RelayingParty` interface implementation
|
//CodeExchangeHandler extends the `CodeExchange` method with a http handler
|
||||||
//extending the `CodeExchange` method with callback function
|
//including cookie handling for secure `state` transfer
|
||||||
|
//and optional PKCE code verifier checking
|
||||||
func CodeExchangeHandler(callback func(http.ResponseWriter, *http.Request, *oidc.Tokens, string), rp RelayingParty) http.HandlerFunc {
|
func CodeExchangeHandler(callback func(http.ResponseWriter, *http.Request, *oidc.Tokens, string), rp RelayingParty) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
state, err := tryReadStateCookie(w, r, rp)
|
state, err := tryReadStateCookie(w, r, rp)
|
||||||
|
@ -365,11 +367,6 @@ func tryReadStateCookie(w http.ResponseWriter, r *http.Request, rp RelayingParty
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Configuration struct {
|
|
||||||
Issuer string
|
|
||||||
*oauth2.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
type OptionFunc func(RelayingParty)
|
type OptionFunc func(RelayingParty)
|
||||||
|
|
||||||
type Endpoints struct {
|
type Endpoints struct {
|
||||||
|
|
|
@ -32,18 +32,17 @@ type DelegationTokenExchangeRP interface {
|
||||||
DelegationTokenExchange(context.Context, string, ...tokenexchange.TokenExchangeOption) (*oauth2.Token, error)
|
DelegationTokenExchange(context.Context, string, ...tokenexchange.TokenExchangeOption) (*oauth2.Token, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TokenExchange is the `TokenExchangeRP` interface implementation
|
//TokenExchange handles the oauth2 token exchange
|
||||||
//handling the oauth2 token exchange (draft)
|
|
||||||
func TokenExchange(ctx context.Context, request *tokenexchange.TokenExchangeRequest, rp RelayingParty) (newToken *oauth2.Token, err error) {
|
func TokenExchange(ctx context.Context, request *tokenexchange.TokenExchangeRequest, rp RelayingParty) (newToken *oauth2.Token, err error) {
|
||||||
return CallTokenEndpoint(request, rp)
|
return CallTokenEndpoint(request, rp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//DelegationTokenExchange is the `TokenExchangeRP` interface implementation
|
//DelegationTokenExchange handles the oauth2 token exchange for a delegation token
|
||||||
//handling the oauth2 token exchange for a delegation token (draft)
|
|
||||||
func DelegationTokenExchange(ctx context.Context, subjectToken string, rp RelayingParty, reqOpts ...tokenexchange.TokenExchangeOption) (newToken *oauth2.Token, err error) {
|
func DelegationTokenExchange(ctx context.Context, subjectToken string, rp RelayingParty, reqOpts ...tokenexchange.TokenExchangeOption) (newToken *oauth2.Token, err error) {
|
||||||
return TokenExchange(ctx, DelegationTokenRequest(subjectToken, reqOpts...), rp)
|
return TokenExchange(ctx, DelegationTokenRequest(subjectToken, reqOpts...), rp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//JWTProfileExchange handles the oauth2 jwt profile exchange
|
||||||
func JWTProfileExchange(ctx context.Context, assertion *oidc.JWTProfileAssertion, rp RelayingParty) (*oauth2.Token, error) {
|
func JWTProfileExchange(ctx context.Context, assertion *oidc.JWTProfileAssertion, rp RelayingParty) (*oauth2.Token, error) {
|
||||||
token, err := generateJWTProfileToken(assertion)
|
token, err := generateJWTProfileToken(assertion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue