WIP: Begin OAuth2 implementation #598

Closed
JonasFranz wants to merge 9 commits from feature/oauth2 into master
3 changed files with 90 additions and 2 deletions
Showing only changes of commit e1b4feef60 - Show all commits

View File

@ -0,0 +1,62 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package models
import (
"crypto"
"encoding/base64"
"time"
)
// OAuth2JTIBlocklist contains all JTI signatures for already assinged JWT tokens
type OAuth2BlockedJTI struct {
Signature string `xorm:"pk not null"`
ExpiresAt *time.Time
}
func calculateSignatureOfJTI(jti string) string {
hasher := crypto.SHA256.New()
hasher.Write([]byte(jti))
return base64.URLEncoding.EncodeToString(hasher.Sum(nil))
}
// BlockOAuth2JTI blocks the given JTI from reassigning until it expires
func BlockOAuth2JTI(jti string, expiresAt *time.Time) error {
_, err := x.Insert(&OAuth2BlockedJTI{
Signature: calculateSignatureOfJTI(jti),
ExpiresAt: expiresAt,
})
return err
}
// DeleteExpiredJTIs deletes all expired JTIs from the database
func DeleteExpiredJTIs() error {
_, err := x.Where("expires_at < now()").Delete(&OAuth2BlockedJTI{})
return err
}
// IsJTIBlocked checks if a given JTI is already present in the block list and if present checks if the present
// JTI is expired. True is the default value if an error occurs.
func IsJTIBlocked(jti string) (bool, error) {
blockedJTI := new(OAuth2BlockedJTI)
if has, err := x.ID(calculateSignatureOfJTI(jti)).Get(&blockedJTI); err != nil {
return true, err
} else if !has {
return false, nil
}
return blockedJTI.ExpiresAt.Before(time.Now()), nil
}

View File

@ -1,3 +1,19 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

Will xorm make this a text or varchar? It should be a varchar since it's used as primary key.

Will xorm make this a text or varchar? It should be a varchar since it's used as primary key.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package models
import (

View File

@ -2,6 +2,7 @@ package oauth
import (
"context"
"github.com/pkg/errors"
"time"
"github.com/ory/fosite"
@ -20,11 +21,20 @@ func (s *Storage) GetClient(ctx context.Context, id string) (fosite.Client, erro
}
func (s *Storage) ClientAssertionJWTValid(ctx context.Context, jti string) error {
panic("implement me")
if isBlocked, err := models.IsJTIBlocked(jti); err != nil {
return err
} else if isBlocked {
return errors.WithStack(fosite.ErrJTIKnown)
}
return nil
}
func (s *Storage) SetClientAssertionJWT(ctx context.Context, jti string, exp time.Time) error {
panic("implement me")
// Clean up the database
if err := models.DeleteExpiredJTIs(); err != nil {
return err
}
return models.BlockOAuth2JTI(jti, &exp)
}
func (s *Storage) CreateAuthorizeCodeSession(ctx context.Context, code string, request fosite.Requester) (err error) {