package barcode import ( "context" "github.com/ory/fosite" "github.com/ory/fosite/handler/openid" "github.com/ory/x/errorsx" "golang.org/x/crypto/bcrypt" "edge-infra.dev/pkg/edge/iam/config" "edge-infra.dev/pkg/edge/iam/prometheus" "edge-infra.dev/pkg/edge/iam/util" ) type ScopeHandler struct { BarcodeGenStrategy Strategy BarcodeStorage Storage // Custom metrics Metrics *prometheus.Metrics } func (h *ScopeHandler) HandleTokenEndpointRequest(_ context.Context, request fosite.AccessRequester) error { if !request.GetClient().GetGrantTypes().Has("barcode") { return errorsx.WithStack(fosite.ErrUnauthorizedClient.WithHint("The OAuth 2.0 Client is not allowed to use scope 'barcode'.")) } h.Metrics.IncHTTPRequestsTotal(signUpBarcodeScope) return nil } func (h *ScopeHandler) CanHandleTokenEndpointRequest(requester fosite.AccessRequester) bool { return requester.GetGrantedScopes().Has("barcode") && !requester.GetGrantTypes().ExactOne("barcode") } func (h *ScopeHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) (err error) { if !h.CanHandleTokenEndpointRequest(requester) { return errorsx.WithStack(fosite.ErrUnknownRequest) } barcode, err := h.BarcodeGenStrategy.Generate() if err != nil { return errorsx.WithStack(fosite.ErrServerError.WithHint("encountered internal server error")) } openIDSession, ok := requester.GetSession().(openid.Session) if !ok { return errorsx.WithStack(fosite.ErrInvalidGrant.WithHint("should be an openID session")) } key := h.BarcodeGenStrategy.GetKey(barcode) if err = h.BarcodeStorage.CreateBarcodeUser(ctx, openIDSession.IDTokenClaims().Subject, key); err != nil { return errorsx.WithStack(fosite.ErrServerError) } barcodePrefixLen := uint8(len(config.BarcodePrefix())) /* #nosec G115 value from ENV and ENV is considered trusted */ secret := barcode[barcodePrefixLen+config.GetBarcodeKeyLength():] hash, _ := bcrypt.GenerateFromPassword([]byte(secret), config.BcryptCost()) if err := h.BarcodeStorage.CreateBarcode(ctx, key, string(hash), openIDSession.IDTokenClaims().Subject); err != nil { return err } responder.SetExtra("barcode", barcode) h.Metrics.IncSignUpRequestsTotal(signUpBarcodeScope, util.Succeeded) return nil } func (h *ScopeHandler) CanSkipClientAuth(_ fosite.AccessRequester) bool { return false }