@@ -6,10 +6,8 @@ package auth
66import (
77 "context"
88 "crypto/sha256"
9- "crypto/subtle"
109 "encoding/base32"
1110 "encoding/base64"
12- "encoding/hex"
1311 "errors"
1412 "fmt"
1513 "net"
@@ -694,312 +692,3 @@ func DeleteOAuth2RelictsByUserID(ctx context.Context, userID int64) error {
694692
695693 return nil
696694}
697-
698- type OAuth2Device struct {
699- ID int64 `xorm:"pk autoincr"`
700- DeviceCode string `xorm:"-"`
701- DeviceCodeHash string `xorm:"UNIQUE"` // sha256 of device code
702- DeviceCodeSalt string
703- DeviceCodeID string `xorm:"INDEX"`
704- UserCode string `xorm:"INDEX VARCHAR(9)"`
705- Application * OAuth2Application `xorm:"-"`
706- ApplicationID int64 `xorm:"INDEX"`
707- Scope string `xorm:"TEXT"`
708- GrantID int64
709- CreatedUnix timeutil.TimeStamp `xorm:"created"`
710- UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
711- ExpiredUnix timeutil.TimeStamp
712- }
713-
714- // TableName sets the table name to `oauth2_device`
715- func (device * OAuth2Device ) TableName () string {
716- return "oauth2_device"
717- }
718-
719- func (device * OAuth2Device ) LoadApplication (ctx context.Context ) error {
720- if device .Application != nil {
721- return nil
722- }
723-
724- application := new (OAuth2Application )
725- has , err := db .GetEngine (ctx ).ID (device .ApplicationID ).Get (application )
726- if err != nil {
727- return err
728- }
729- if ! has {
730- return & ErrOAuthApplicationNotFound {ID : device .ApplicationID }
731- }
732-
733- device .Application = application
734-
735- return nil
736- }
737-
738- func generateUserCode () (string , error ) {
739- rBytes , err := util .CryptoRandomBytes (8 )
740- if err != nil {
741- return "" , err
742- }
743- letters := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
744- code := make ([]byte , 8 )
745- for i := range code {
746- code [i ] = letters [int (rBytes [i ])% len (letters )]
747- }
748- return fmt .Sprintf ("%s-%s" , string (code [:4 ]), string (code [4 :])), nil
749- }
750-
751- // CreateDevice generates a device for an user
752- func (app * OAuth2Application ) CreateDevice (ctx context.Context , scope string ) (* OAuth2Device , error ) {
753- userCode , err := generateUserCode ()
754- if err != nil {
755- return nil , err
756- }
757-
758- device := & OAuth2Device {
759- ApplicationID : app .ID ,
760- UserCode : userCode ,
761- Scope : scope ,
762- ExpiredUnix : timeutil .TimeStampNow ().Add (setting .OAuth2 .DeviceFlowExpirationTime ),
763- }
764-
765- salt , err := util .CryptoRandomString (10 )
766- if err != nil {
767- return nil , err
768- }
769- code , err := util .CryptoRandomBytes (20 )
770- if err != nil {
771- return nil , err
772- }
773-
774- device .DeviceCode = hex .EncodeToString (code )
775- device .DeviceCodeSalt = salt
776- device .DeviceCodeID = device .DeviceCode [len (device .DeviceCode )- 8 :]
777- device .DeviceCodeHash = HashToken (device .DeviceCode , device .DeviceCodeSalt )
778-
779- err = db .Insert (ctx , device )
780- if err != nil {
781- return nil , err
782- }
783-
784- return device , nil
785- }
786-
787- func (app * OAuth2Application ) GetDeviceByDeviceCode (ctx context.Context , deviceCode string ) (* OAuth2Device , error ) {
788- if len (deviceCode ) != 40 {
789- return nil , & ErrOAuth2DeviceNotFound {UserCode : deviceCode }
790- }
791- for _ , x := range []byte (deviceCode ) {
792- if x < '0' || (x > '9' && x < 'a' ) || x > 'f' {
793- return nil , & ErrOAuth2DeviceNotFound {UserCode : deviceCode }
794- }
795- }
796-
797- deviceCodeID := deviceCode [len (deviceCode )- 8 :]
798- var deviceList []OAuth2Device
799- err := db .GetEngine (ctx ).Table (& OAuth2Device {}).Where ("device_code_id = ? AND application_id = ?" , deviceCodeID , app .ID ).Find (& deviceList )
800- if err != nil {
801- return nil , err
802- } else if len (deviceList ) == 0 {
803- return nil , & ErrOAuth2DeviceNotFound {UserCode : deviceCode }
804- }
805-
806- for _ , t := range deviceList {
807- tempHash := HashToken (deviceCode , t .DeviceCodeSalt )
808- if subtle .ConstantTimeCompare ([]byte (t .DeviceCodeHash ), []byte (tempHash )) == 1 {
809- return & t , nil
810- }
811- }
812-
813- return nil , & ErrOAuth2DeviceNotFound {UserCode : deviceCode }
814- }
815-
816- func (device * OAuth2Device ) GetGrant (ctx context.Context ) (* OAuth2DeviceGrant , error ) {
817- if device .GrantID <= 0 {
818- return nil , fmt .Errorf ("no grant found for device: %d" , device .ID )
819- }
820-
821- grant := new (OAuth2DeviceGrant )
822- _ , err := db .GetEngine (ctx ).ID (device .GrantID ).Get (grant )
823-
824- return grant , err
825- }
826-
827- type ErrOAuth2DeviceNotFound struct {
828- UserCode string
829- ID int64
830- }
831-
832- func (err * ErrOAuth2DeviceNotFound ) Error () string {
833- return fmt .Sprintf ("oauth2 device not found: [user_code: %s. id: %d]" , err .UserCode , err .ID )
834- }
835-
836- func IsErrOAuth2DeviceNotFound (err error ) bool {
837- _ , ok := err .(* ErrOAuth2DeviceNotFound )
838- return ok
839- }
840-
841- func GetDeviceByUserCode (ctx context.Context , userCode string ) (* OAuth2Device , error ) {
842- device := new (OAuth2Device )
843-
844- ok , err := db .GetEngine (ctx ).Where ("user_code = ? AND grant_id = ? AND expired_unix > ?" ,
845- userCode , 0 , timeutil .TimeStampNow ()).Get (device )
846- if err != nil {
847- return nil , err
848- }
849- if ! ok {
850- return nil , & ErrOAuth2DeviceNotFound {UserCode : userCode }
851- }
852-
853- return device , nil
854- }
855-
856- func GetDeviceByID (ctx context.Context , id int64 ) (* OAuth2Device , error ) {
857- device := new (OAuth2Device )
858- ok , err := db .GetEngine (ctx ).ID (id ).Get (device )
859- if err != nil {
860- return nil , err
861- }
862- if ! ok {
863- return nil , & ErrOAuth2DeviceNotFound {ID : id }
864- }
865-
866- return device , nil
867- }
868-
869- type OAuth2DeviceGrant struct {
870- ID int64 `xorm:"pk autoincr"`
871- UserID int64 `xorm:"INDEX"`
872- Application * OAuth2Application `xorm:"-"`
873- ApplicationID int64 `xorm:"INDEX"`
874- DeviceID int64 `xorm:"INDEX"`
875- Counter int64 `xorm:"NOT NULL DEFAULT 1"`
876- UserCode string `xorm:"VARCHAR(9)"`
877- Scope string `xorm:"TEXT"`
878- Nonce string `xorm:"TEXT"`
879- CreatedUnix timeutil.TimeStamp `xorm:"created"`
880- UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
881- }
882-
883- // TableName sets theOAuth2DeviceGrant table name to `oauth2_device_grant`
884- func (grant * OAuth2DeviceGrant ) TableName () string {
885- return "oauth2_device_grant"
886- }
887-
888- func (device * OAuth2Device ) CreateGrant (ctx context.Context , userID int64 ) error {
889- return db .WithTx (ctx , func (ctx context.Context ) error {
890- grant := & OAuth2DeviceGrant {
891- UserID : userID ,
892- DeviceID : device .ID ,
893- ApplicationID : device .ApplicationID ,
894- Scope : device .Scope ,
895- UserCode : device .UserCode ,
896- }
897- err := db .Insert (ctx , grant )
898- if err != nil {
899- return err
900- }
901-
902- device .GrantID = grant .ID
903- _ , err = db .GetEngine (ctx ).ID (device .ID ).Cols ("grant_id" ).Update (device )
904- return err
905- })
906- }
907-
908- // GetOAuth2GrantByID returns the grant with the given ID
909- func GetOAuth2DeviceGrantByID (ctx context.Context , id int64 ) (grant * OAuth2DeviceGrant , err error ) {
910- grant = new (OAuth2DeviceGrant )
911- if has , err := db .GetEngine (ctx ).ID (id ).Get (grant ); err != nil {
912- return nil , err
913- } else if ! has {
914- return nil , nil
915- }
916- return grant , err
917- }
918-
919- func (grant * OAuth2DeviceGrant ) IncreaseCounter (ctx context.Context ) error {
920- _ , err := db .GetEngine (ctx ).ID (grant .ID ).Incr ("counter" ).Update (new (OAuth2Grant ))
921- if err != nil {
922- return err
923- }
924- updatedGrant , err := GetOAuth2DeviceGrantByID (ctx , grant .ID )
925- if err != nil {
926- return err
927- }
928- grant .Counter = updatedGrant .Counter
929- return nil
930- }
931-
932- func (grant * OAuth2DeviceGrant ) GetID () int64 {
933- return - grant .ID
934- }
935-
936- func (grant * OAuth2DeviceGrant ) GetCounter () int64 {
937- return grant .Counter
938- }
939-
940- func (grant * OAuth2DeviceGrant ) ScopeContains (scope string ) bool {
941- return slices .Contains (strings .Split (grant .Scope , " " ), scope )
942- }
943-
944- func (grant * OAuth2DeviceGrant ) GetApplicationID () int64 {
945- return grant .ApplicationID
946- }
947-
948- func (grant * OAuth2DeviceGrant ) GetUserID () int64 {
949- return grant .UserID
950- }
951-
952- func (grant * OAuth2DeviceGrant ) GetNonce () string {
953- return grant .Nonce
954- }
955-
956- func (grant * OAuth2DeviceGrant ) GetScope () string {
957- return grant .Scope
958- }
959-
960- // GetOAuth2GrantsByUserID lists all grants of a certain user
961- func GetOAuth2DeviceGrantsByUserID (ctx context.Context , uid int64 ) ([]* OAuth2DeviceGrant , error ) {
962- type joinedOAuth2DeviceGrant struct {
963- Grant * OAuth2DeviceGrant `xorm:"extends"`
964- Application * OAuth2Application `xorm:"extends"`
965- }
966- var results * xorm.Rows
967- var err error
968- if results , err = db .GetEngine (ctx ).
969- Table ("oauth2_device_grant" ).
970- Where ("user_id = ?" , uid ).
971- Join ("INNER" , "oauth2_application" , "application_id = oauth2_application.id" ).
972- Rows (new (joinedOAuth2DeviceGrant )); err != nil {
973- return nil , err
974- }
975- defer results .Close ()
976- grants := make ([]* OAuth2DeviceGrant , 0 )
977- for results .Next () {
978- joinedGrant := new (joinedOAuth2DeviceGrant )
979- if err := results .Scan (joinedGrant ); err != nil {
980- return nil , err
981- }
982- joinedGrant .Grant .Application = joinedGrant .Application
983- grants = append (grants , joinedGrant .Grant )
984- }
985- return grants , nil
986- }
987-
988- // RevokeOAuth2Grant deletes the device grant with grantID and userID
989- func RevokeOAuth2DeviceGrant (ctx context.Context , grantID , userID int64 ) error {
990- if grantID <= 0 {
991- return errors .New ("invalid grant ID" )
992- }
993-
994- return db .WithTx (ctx , func (ctx context.Context ) error {
995- _ , err := db .GetEngine (ctx ).Where (builder.Eq {"grant_id" : grantID }).
996- Delete (& OAuth2Device {})
997- if err != nil {
998- return err
999- }
1000-
1001- _ , err = db .GetEngine (ctx ).Where (builder.Eq {"id" : grantID , "user_id" : userID }).
1002- Delete (& OAuth2DeviceGrant {})
1003- return err
1004- })
1005- }
0 commit comments