Skip to content
Snippets Groups Projects
proxytoken.go 3.38 KiB
Newer Older
package transfercoderepo

import (
	"database/sql"
	"errors"

	"github.com/jmoiron/sqlx"
	"github.com/oidc-mytoken/server/internal/db"
	"github.com/oidc-mytoken/server/internal/utils/hashUtils"
	"github.com/oidc-mytoken/server/shared/mytoken/pkg/mtid"
	"github.com/oidc-mytoken/server/shared/utils"
	"github.com/oidc-mytoken/server/shared/utils/cryptUtils"
)

// proxyToken holds information for proxy tokens, i.e. tokens that proxy another token, e.g. a short token
type proxyToken struct {
	id    string
	token string
	mtID  mtid.MTID

	encryptedJWT string
	decryptedJWT string
}

// newProxyToken creates a new proxyToken of the given length
Gabriel Zachmann's avatar
Gabriel Zachmann committed
func newProxyToken(size int) *proxyToken {
	token := utils.RandASCIIString(size)
	return createProxyToken(token)
}

func createProxyToken(token string) *proxyToken {
	id := hashUtils.SHA512Str([]byte(token))
	return &proxyToken{
		id:    id,
		token: token,
	}
}

// parseProxyToken parses the proxy token string into a proxyToken
func parseProxyToken(token string) *proxyToken {
	if token != "" {
		id = hashUtils.SHA512Str([]byte(token))
	}
	return &proxyToken{
		id:    id,
		token: token,
	}
}

func (pt proxyToken) String() string {
	return pt.Token()
}

// Token returns the token of this proxyToken
func (pt proxyToken) Token() string {
	return pt.token
}

// ID returns the id of this token
func (pt *proxyToken) ID() string {
	if pt.id == "" {
		pt.id = hashUtils.SHA512Str([]byte(pt.token))
	}
	return pt.id
}

// SetJWT sets the jwt for this proxyToken
func (pt *proxyToken) SetJWT(jwt string, mID mtid.MTID) (err error) {
Gabriel Zachmann's avatar
Gabriel Zachmann committed
	pt.mtID = mID
	pt.decryptedJWT = jwt
	pt.encryptedJWT, err = cryptUtils.AES256Encrypt(jwt, pt.token)
	return
}

// JWT returns the decrypted jwt that is linked to this proxyToken
func (pt *proxyToken) JWT(tx *sqlx.Tx) (jwt string, valid bool, err error) {
	jwt = pt.decryptedJWT
	if jwt != "" {
		valid = true
		return
	}
	if pt.encryptedJWT == "" {
		if err = db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
Gabriel Zachmann's avatar
Gabriel Zachmann committed
			var res struct {
				JWT  string    `db:"jwt"`
				MTID mtid.MTID `db:"MT_id"`
			if err = tx.Get(&res, `SELECT jwt, MT_id FROM ProxyTokens WHERE id=?`, pt.id); err != nil {
Gabriel Zachmann's avatar
Gabriel Zachmann committed
				return err
			}
			pt.encryptedJWT = res.JWT
			pt.mtID = res.MTID
			return nil
		}); err != nil {
			if errors.Is(err, sql.ErrNoRows) {
				err = nil
				return
			}
			return
		}
	}
	valid = true
	if pt.encryptedJWT == "" {
Gabriel Zachmann's avatar
Gabriel Zachmann committed
		return
	}
	jwt, err = cryptUtils.AES256Decrypt(pt.encryptedJWT, pt.token)
	pt.decryptedJWT = jwt
	return
}

// Store stores the proxyToken
func (pt proxyToken) Store(tx *sqlx.Tx) error {
	return db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
Gabriel Zachmann's avatar
Gabriel Zachmann committed
		_, err := tx.Exec(`INSERT INTO ProxyTokens (id, jwt, MT_id) VALUES (?,?,?)`, pt.id, pt.encryptedJWT, pt.mtID)
// Update updates the jwt of the proxyToken
func (pt proxyToken) Update(tx *sqlx.Tx) error {
	return db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
Gabriel Zachmann's avatar
Gabriel Zachmann committed
		_, err := tx.Exec(`UPDATE ProxyTokens SET jwt=?, MT_id=? WHERE id=?`, pt.encryptedJWT, pt.mtID, pt.id)
// Delete deletes the proxyToken from the database, it does not delete the linked Mytoken, the jwt should have been retrieved earlier and the Mytoken if desired be revoked separately
func (pt proxyToken) Delete(tx *sqlx.Tx) error {
	return db.RunWithinTransaction(tx, func(tx *sqlx.Tx) error {
		_, err := tx.Exec(`DELETE FROM ProxyTokens WHERE id=?`, pt.id)
		return err
	})
}