lot of unfinished changes

This commit is contained in:
Livio Amstutz 2020-09-08 16:07:49 +02:00
parent 9cb0fff23f
commit a37a8461a5
16 changed files with 502 additions and 328 deletions

View file

@ -275,7 +275,7 @@ func (p *DefaultOP) Crypto() Crypto {
return p.crypto
}
func (p *DefaultOP) Verifier() rp.Verifier {
func (p *DefaultOP) ClientJWTVerifier() rp.Verifier {
return p.verifier
}

View file

@ -7,6 +7,12 @@ import (
"github.com/caos/oidc/pkg/utils"
)
func DiscoveryHandler(c Configuration, s Signer) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
Discover(w, CreateDiscoveryConfig(c, s))
}
}
func Discover(w http.ResponseWriter, config *oidc.DiscoveryConfiguration) {
utils.MarshalJSON(w, config)
}

View file

@ -97,7 +97,7 @@ func (mr *MockStorageMockRecorder) CreateAuthRequest(arg0, arg1, arg2 interface{
}
// CreateToken mocks base method
func (m *MockStorage) CreateToken(arg0 context.Context, arg1 op.AuthRequest) (string, time.Time, error) {
func (m *MockStorage) CreateToken(arg0 context.Context, arg1 op.TokenRequest) (string, time.Time, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CreateToken", arg0, arg1)
ret0, _ := ret[0].(string)

View file

@ -22,9 +22,12 @@ type OpenIDProvider interface {
HandleAuthorizeCallback(w http.ResponseWriter, r *http.Request)
HandleExchange(w http.ResponseWriter, r *http.Request)
HandleUserinfo(w http.ResponseWriter, r *http.Request)
HandleEndSession(w http.ResponseWriter, r *http.Request)
//HandleEndSession(w http.ResponseWriter, r *http.Request)
HandleKeys(w http.ResponseWriter, r *http.Request)
HttpHandler() http.Handler
SessionEnder
Signer() Signer
Probes() []ProbesFn
}
type HttpInterceptor func(http.Handler) http.Handler
@ -42,13 +45,13 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router
handlers.AllowedOriginValidator(allowAllOrigins),
))
router.HandleFunc(healthzEndpoint, Healthz)
router.HandleFunc(readinessEndpoint, o.HandleReady)
router.HandleFunc(oidc.DiscoveryEndpoint, o.HandleDiscovery)
router.HandleFunc(readinessEndpoint, Ready(o.Probes()))
router.HandleFunc(oidc.DiscoveryEndpoint, DiscoveryHandler(o, o.Signer()))
router.Handle(o.AuthorizationEndpoint().Relative(), intercept(o.HandleAuthorize))
router.Handle(o.AuthorizationEndpoint().Relative()+"/{id}", intercept(o.HandleAuthorizeCallback))
router.Handle(o.TokenEndpoint().Relative(), intercept(o.HandleExchange))
router.HandleFunc(o.UserinfoEndpoint().Relative(), o.HandleUserinfo)
router.Handle(o.EndSessionEndpoint().Relative(), intercept(o.HandleEndSession))
router.Handle(o.EndSessionEndpoint().Relative(), intercept(EndSessionHandler(o)))
router.HandleFunc(o.KeysEndpoint().Relative(), o.HandleKeys)
return router
}

View file

@ -14,6 +14,12 @@ func Healthz(w http.ResponseWriter, r *http.Request) {
ok(w)
}
func Ready(probes []ProbesFn) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
Readiness(w, r, probes...)
}
}
func Readiness(w http.ResponseWriter, r *http.Request, probes ...ProbesFn) {
ctx := r.Context()
for _, probe := range probes {

View file

@ -16,6 +16,12 @@ type SessionEnder interface {
DefaultLogoutRedirectURI() string
}
func EndSessionHandler(ender SessionEnder) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
EndSession(w, r, ender)
}
}
func EndSession(w http.ResponseWriter, r *http.Request, ender SessionEnder) {
req, err := ParseEndSessionRequest(r, ender.Decoder())
if err != nil {

View file

@ -16,7 +16,7 @@ type AuthStorage interface {
SaveAuthCode(context.Context, string, string) error
DeleteAuthRequest(context.Context, string) error
CreateToken(context.Context, AuthRequest) (string, time.Time, error)
CreateToken(context.Context, TokenRequest) (string, time.Time, error)
TerminateSession(context.Context, string, string) error

View file

@ -14,12 +14,19 @@ type TokenCreator interface {
Crypto() Crypto
}
type TokenRequest interface {
GetClientID() string
GetSubject() string
GetAudience() []string
GetScopes() []string
}
func CreateTokenResponse(ctx context.Context, authReq AuthRequest, client Client, creator TokenCreator, createAccessToken bool, code string) (*oidc.AccessTokenResponse, error) {
var accessToken string
var validity time.Duration
if createAccessToken {
var err error
accessToken, validity, err = CreateAccessToken(ctx, authReq, client, creator)
accessToken, validity, err = CreateAccessToken(ctx, authReq, client.AccessTokenType(), creator)
if err != nil {
return nil, err
}
@ -43,8 +50,8 @@ func CreateTokenResponse(ctx context.Context, authReq AuthRequest, client Client
}, nil
}
func CreateJWTTokenResponse(ctx context.Context, authReq AuthRequest, client Client, creator TokenCreator) (*oidc.AccessTokenResponse, error) {
accessToken, validity, err := CreateAccessToken(ctx, authReq, client, creator)
func CreateJWTTokenResponse(ctx context.Context, tokenRequest TokenRequest, creator TokenCreator) (*oidc.AccessTokenResponse, error) {
accessToken, validity, err := CreateAccessToken(ctx, tokenRequest, AccessTokenTypeBearer, creator)
if err != nil {
return nil, err
}
@ -57,13 +64,13 @@ func CreateJWTTokenResponse(ctx context.Context, authReq AuthRequest, client Cli
}, nil
}
func CreateAccessToken(ctx context.Context, authReq AuthRequest, client Client, creator TokenCreator) (token string, validity time.Duration, err error) {
func CreateAccessToken(ctx context.Context, authReq TokenRequest, accessTokenType AccessTokenType, creator TokenCreator) (token string, validity time.Duration, err error) {
id, exp, err := creator.Storage().CreateToken(ctx, authReq)
if err != nil {
return "", 0, err
}
validity = exp.Sub(time.Now().UTC())
if client.AccessTokenType() == AccessTokenTypeJWT {
if accessTokenType == AccessTokenTypeJWT {
token, err = CreateJWT(creator.Issuer(), authReq, exp, id, creator.Signer())
return
}
@ -75,7 +82,7 @@ func CreateBearerToken(id string, crypto Crypto) (string, error) {
return crypto.Encrypt(id)
}
func CreateJWT(issuer string, authReq AuthRequest, exp time.Time, id string, signer Signer) (string, error) {
func CreateJWT(issuer string, authReq TokenRequest, exp time.Time, id string, signer Signer) (string, error) {
now := time.Now().UTC()
nbf := now
claims := &oidc.AccessTokenClaims{

View file

@ -3,7 +3,6 @@ package op
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/caos/oidc/pkg/oidc"
@ -22,7 +21,7 @@ type Exchanger interface {
type VerifyExchanger interface {
Exchanger
Verifier() rp.Verifier
ClientJWTVerifier() rp.Verifier
}
func CodeExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
@ -121,17 +120,31 @@ func AuthorizeCodeChallenge(ctx context.Context, tokenReq *oidc.AccessTokenReque
return authReq, nil
}
type ClientJWTVerifier struct {
claims *oidc.JWTTokenRequest
Storage
}
func (c *ClientJWTVerifier) Issuer() string {
client, err := Storage.GetClientByClientID(context.TODO(), c.claims.Issuer)
return client.GetID()
}
func JWTExchange(w http.ResponseWriter, r *http.Request, exchanger VerifyExchanger) {
assertion, err := ParseJWTTokenRequest(r, exchanger.Decoder())
if err != nil {
RequestError(w, r, err)
}
claims, err := exchanger.Verifier().Verify(r.Context(), "", assertion)
claims := new(oidc.JWTTokenRequest)
//var keyset oidc.KeySet
verifier := new(ClientJWTVerifier)
verifier.claims = claims
err = verifier.VerifyToken(r.Context(), assertion, claims)
if err != nil {
RequestError(w, r, err)
}
fmt.Println(claims, err)
var authReq AuthRequest
var client Client
resp, err := CreateJWTTokenResponse(r.Context(), authReq, client, exchanger)
resp, err := CreateJWTTokenResponse(r.Context(), claims, exchanger)
if err != nil {
RequestError(w, r, err)
return
@ -139,7 +152,7 @@ func JWTExchange(w http.ResponseWriter, r *http.Request, exchanger VerifyExchang
utils.MarshalJSON(w, resp)
}
func ParseJWTTokenRequest(r *http.Request, decoder *schema.Decoder) (string, error) {
func ParseJWTTokenRequest(r *http.Request, decoder utils.Decoder) (string, error) {
err := r.ParseForm()
if err != nil {
return "", ErrInvalidRequest("error parsing form")