-
Notifications
You must be signed in to change notification settings - Fork 28
/
authz_service.go
130 lines (111 loc) · 2.83 KB
/
authz_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package oauth
import (
"errors"
"github.com/authgear/authgear-server/pkg/lib/config"
"github.com/authgear/authgear-server/pkg/lib/session"
"github.com/authgear/authgear-server/pkg/util/clock"
"github.com/authgear/authgear-server/pkg/util/uuid"
)
type OfflineGrantSessionManager interface {
List(userID string) ([]session.Session, error)
Delete(session session.Session) error
}
type AuthorizationService struct {
AppID config.AppID
Store AuthorizationStore
Clock clock.Clock
OAuthSessionManager OfflineGrantSessionManager
}
func (s *AuthorizationService) GetByID(id string) (*Authorization, error) {
return s.Store.GetByID(id)
}
func (s *AuthorizationService) ListByUser(userID string, filters ...AuthorizationFilter) ([]*Authorization, error) {
as, err := s.Store.ListByUserID(userID)
if err != nil {
return nil, err
}
filtered := []*Authorization{}
for _, a := range as {
keep := true
for _, f := range filters {
if !f.Keep(a) {
keep = false
break
}
}
if keep {
filtered = append(filtered, a)
}
}
return filtered, nil
}
func (s *AuthorizationService) Delete(a *Authorization) error {
sessions, err := s.OAuthSessionManager.List(a.UserID)
if err != nil {
return err
}
// delete the offline grants that belong to the authorization
for _, sess := range sessions {
if offlineGrant, ok := sess.(*OfflineGrant); ok {
if offlineGrant.AuthorizationID == a.ID {
err := s.OAuthSessionManager.Delete(sess)
if err != nil {
return err
}
}
}
}
return s.Store.Delete(a)
}
func (s *AuthorizationService) CheckAndGrant(
clientID string,
userID string,
scopes []string,
) (*Authorization, error) {
timestamp := s.Clock.NowUTC()
authz, err := s.Store.Get(userID, clientID)
if err == nil && authz.IsAuthorized(scopes) {
return authz, nil
} else if err != nil && !errors.Is(err, ErrAuthorizationNotFound) {
return nil, err
}
// Authorization of requested scopes not granted, requesting consent.
// TODO(oauth): request consent, for now just always implicitly grant scopes.
if authz == nil {
authz = &Authorization{
ID: uuid.New(),
AppID: string(s.AppID),
ClientID: clientID,
UserID: userID,
CreatedAt: timestamp,
UpdatedAt: timestamp,
Scopes: scopes,
}
err = s.Store.Create(authz)
if err != nil {
return nil, err
}
} else {
authz = authz.WithScopesAdded(scopes)
authz.UpdatedAt = timestamp
err = s.Store.UpdateScopes(authz)
if err != nil {
return nil, err
}
}
return authz, nil
}
func (s *AuthorizationService) Check(
clientID string,
userID string,
scopes []string,
) (*Authorization, error) {
authz, err := s.Store.Get(userID, clientID)
if err != nil {
return nil, err
}
if !authz.IsAuthorized(scopes) {
return nil, ErrAuthorizationScopesNotGranted
}
return authz, nil
}