support for oidc id token

pull/1671/head
beltram 1 year ago committed by Herman Slatman
parent f5b346ee36
commit 7b5740153d
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -431,6 +431,25 @@ func wireOIDC01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSO
if err = db.UpdateChallenge(ctx, ch); err != nil {
return WrapErrorISE(err, "error updating challenge")
}
parsedIdToken, err := jwt.ParseSigned(wireChallengePayload.IdToken)
if err != nil {
return WrapErrorISE(err, "Invalid OIDC id token")
}
oidcToken := make(map[string]interface{})
if err := parsedIdToken.UnsafeClaimsWithoutVerification(&oidcToken); err != nil {
return WrapErrorISE(err, "Failed parsing OIDC id token")
}
orders, err := db.GetAllOrdersByAccountID(ctx, ch.AccountID)
if err != nil {
return WrapErrorISE(err, "Could not find current order by account id")
}
if err := db.CreateOidcToken(ctx, orders[0], oidcToken); err != nil {
return WrapErrorISE(err, "Failed storing OIDC id token")
}
return nil
}
@ -568,7 +587,7 @@ func wireDPOP01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSO
return WrapErrorISE(err, "Could not find current order by account id")
}
if err := db.CreateDpop(ctx, orders[0], dpop); err != nil {
if err := db.CreateDpopToken(ctx, orders[0], dpop); err != nil {
return WrapErrorISE(err, "Failed storing DPoP token")
}

@ -55,8 +55,10 @@ type DB interface {
GetAllOrdersByAccountID(ctx context.Context, accountID string) ([]string, error)
UpdateOrder(ctx context.Context, o *Order) error
CreateDpop(ctx context.Context, orderId string, dpop map[string]interface{}) error
GetDpop(ctx context.Context, orderId string) (map[string]interface{}, error)
CreateDpopToken(ctx context.Context, orderId string, dpop map[string]interface{}) error
GetDpopToken(ctx context.Context, orderId string) (map[string]interface{}, error)
CreateOidcToken(ctx context.Context, orderId string, idToken map[string]interface{}) error
GetOidcToken(ctx context.Context, orderId string) (map[string]interface{}, error)
}
type dbKey struct{}

@ -23,7 +23,8 @@ var (
externalAccountKeyTable = []byte("acme_external_account_keys")
externalAccountKeyIDsByReferenceTable = []byte("acme_external_account_keyID_reference_index")
externalAccountKeyIDsByProvisionerIDTable = []byte("acme_external_account_keyID_provisionerID_index")
dpopTable = []byte("acme_dpop")
dpopTokenTable = []byte("acme_dpop_token")
oidcTokenTable = []byte("oidc_token")
)
// DB is a struct that implements the AcmeDB interface.

@ -10,30 +10,31 @@ import (
"github.com/smallstep/nosql"
)
type dbDpop struct {
type dbDpopToken struct {
ID string `json:"id"`
Content []byte `json:"content"`
CreatedAt time.Time `json:"createdAt"`
}
// getDBDpop retrieves and unmarshals an DPoP type from the database.
func (db *DB) getDBDpop(ctx context.Context, orderId string) (*dbDpop, error) {
b, err := db.db.Get(dpopTable, []byte(orderId))
// getDBDpopToken retrieves and unmarshals an DPoP type from the database.
func (db *DB) getDBDpopToken(ctx context.Context, orderId string) (*dbDpopToken, error) {
b, err := db.db.Get(dpopTokenTable, []byte(orderId))
if nosql.IsErrNotFound(err) {
return nil, acme.NewError(acme.ErrorMalformedType, "dpop %s not found", orderId)
} else if err != nil {
return nil, errors.Wrapf(err, "error loading dpop %s", orderId)
}
o := new(dbDpop)
if err := json.Unmarshal(b, &o); err != nil {
return nil, errors.Wrapf(err, "error unmarshaling dpop %s into dbDpop", orderId)
d := new(dbDpopToken)
if err := json.Unmarshal(b, &d); err != nil {
return nil, errors.Wrapf(err, "error unmarshaling dpop %s into dbDpopToken", orderId)
}
return o, nil
return d, nil
}
// GetDpop retrieves an DPoP from the database.
func (db *DB) GetDpop(ctx context.Context, orderId string) (map[string]interface{}, error) {
dbDpop, err := db.getDBDpop(ctx, orderId)
// GetDpopToken retrieves an DPoP from the database.
func (db *DB) GetDpopToken(ctx context.Context, orderId string) (map[string]interface{}, error) {
dbDpop, err := db.getDBDpopToken(ctx, orderId)
if err != nil {
return nil, err
}
@ -44,20 +45,73 @@ func (db *DB) GetDpop(ctx context.Context, orderId string) (map[string]interface
return dpop, err
}
// CreateDpop creates DPoP resources and saves them to the DB.
func (db *DB) CreateDpop(ctx context.Context, orderId string, dpop map[string]interface{}) error {
// CreateDpopToken creates DPoP resources and saves them to the DB.
func (db *DB) CreateDpopToken(ctx context.Context, orderId string, dpop map[string]interface{}) error {
content, err := json.Marshal(dpop)
if err != nil {
return err
}
now := clock.Now()
dbDpop := &dbDpop{
dbDpop := &dbDpopToken{
ID: orderId,
Content: content,
CreatedAt: now,
}
if err := db.save(ctx, orderId, dbDpop, nil, "dpop", dpopTokenTable); err != nil {
return err
}
return nil
}
type dbOidcToken struct {
ID string `json:"id"`
Content []byte `json:"content"`
CreatedAt time.Time `json:"createdAt"`
}
// getDBOidcToken retrieves and unmarshals an OIDC id token type from the database.
func (db *DB) getDBOidcToken(ctx context.Context, orderId string) (*dbOidcToken, error) {
b, err := db.db.Get(oidcTokenTable, []byte(orderId))
if nosql.IsErrNotFound(err) {
return nil, acme.NewError(acme.ErrorMalformedType, "oidc token %s not found", orderId)
} else if err != nil {
return nil, errors.Wrapf(err, "error loading oidc token %s", orderId)
}
o := new(dbOidcToken)
if err := json.Unmarshal(b, &o); err != nil {
return nil, errors.Wrapf(err, "error unmarshaling oidc token %s into dbOidcToken", orderId)
}
return o, nil
}
// GetOidcToken retrieves an oidc token from the database.
func (db *DB) GetOidcToken(ctx context.Context, orderId string) (map[string]interface{}, error) {
dbOidc, err := db.getDBOidcToken(ctx, orderId)
if err != nil {
return nil, err
}
idToken := make(map[string]interface{})
err = json.Unmarshal(dbOidc.Content, &idToken)
return idToken, err
}
// CreateOidcToken creates oidc token resources and saves them to the DB.
func (db *DB) CreateOidcToken(ctx context.Context, orderId string, idToken map[string]interface{}) error {
content, err := json.Marshal(idToken)
if err != nil {
return err
}
now := clock.Now()
dbOidc := &dbOidcToken{
ID: orderId,
Content: content,
CreatedAt: now,
}
if err := db.save(ctx, orderId, dbDpop, nil, "dpop", dpopTable); err != nil {
if err := db.save(ctx, orderId, dbOidc, nil, "oidc", oidcTokenTable); err != nil {
return err
}
return nil

@ -210,43 +210,11 @@ func (o *Order) Finalize(ctx context.Context, db DB, csr *x509.CertificateReques
}
data.SetSubject(subject)
dpop, err := db.GetDpop(ctx, o.ID)
if err != nil {
return err
}
// Inject Wire's custom challenges into the template once they have been validated
dpop, err := db.GetDpopToken(ctx, o.ID)
data.Set("Dpop", dpop)
// inject the raw access token as template variable
/*
log.Printf(">> json raw content %v", ctx.Value(wire.AccessTokenKey{}))
access, ok := ctx.Value(wire.AccessTokenKey{}).(map[string]interface{})
if !ok {
return WrapErrorISE(err, "Invalid or absent access in context")
}
if access == nil {
return WrapErrorISE(err, "Access was nil in context")
}*/
/*// inject the raw dpop token as template variable
dpop, ok := ctx.Value("dpop").(map[string]interface{})
if !ok {
return WrapErrorISE(err, "Invalid or absent dpop in context")
}
data.Set("dpop", dpop)*/
// inject the raw access token as template variable
/*access, ok := ctx.Value("access").(map[string]interface{})
if !ok {
return WrapErrorISE(err, "Invalid or absent access in context")
}
data.Set("access", access)*/
/*// inject the raw OIDC id token as template variable
oidc, ok := ctx.Value("oidc").(map[string]interface{})
if !ok {
return WrapErrorISE(err, "Invalid or absent oidc in context")
}
data.Set("oidc", oidc)*/
oidc, err := db.GetOidcToken(ctx, o.ID)
data.Set("Oidc", oidc)
// Custom sign options passed to authority.Sign
var extraOptions []provisioner.SignOption

Loading…
Cancel
Save