forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
grant.go
124 lines (104 loc) · 3.83 KB
/
grant.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
package handlers
import (
"errors"
"net/http"
"net/url"
"github.com/RangelReale/osin"
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/user"
"github.com/openshift/origin/pkg/auth/api"
)
// GrantCheck implements osinserver.AuthorizeHandler to ensure requested scopes have been authorized
type GrantCheck struct {
check GrantChecker
handler GrantHandler
errorHandler GrantErrorHandler
}
// NewGrantCheck returns a new GrantCheck
func NewGrantCheck(check GrantChecker, handler GrantHandler, errorHandler GrantErrorHandler) *GrantCheck {
return &GrantCheck{check, handler, errorHandler}
}
// HandleAuthorize implements osinserver.AuthorizeHandler to ensure the requested scopes have been authorized.
// The AuthorizeRequest.Authorized field must already be set to true for the grant check to occur.
// If the requested scopes are authorized, the AuthorizeRequest is unchanged.
// If the requested scopes are not authorized, or an error occurs, AuthorizeRequest.Authorized is set to false.
// If the response is written, true is returned.
// If the response is not written, false is returned.
func (h *GrantCheck) HandleAuthorize(ar *osin.AuthorizeRequest, w http.ResponseWriter) (bool, error) {
// Requests must already be authorized before we will check grants
if !ar.Authorized {
return false, nil
}
// Reset request to unauthorized until we verify the grant
ar.Authorized = false
user, ok := ar.UserData.(user.Info)
if !ok || user == nil {
return h.errorHandler.GrantError(errors.New("the provided user data is not user.Info"), w, ar.HttpRequest)
}
grant := &api.Grant{
Client: ar.Client,
Scope: ar.Scope,
Expiration: int64(ar.Expiration),
RedirectURI: ar.RedirectUri,
}
// Check if the user has already authorized this grant
authorized, err := h.check.HasAuthorizedClient(user, grant)
if err != nil {
return h.errorHandler.GrantError(err, w, ar.HttpRequest)
}
if authorized {
ar.Authorized = true
return false, nil
}
// React to an unauthorized grant
authorized, handled, err := h.handler.GrantNeeded(user, grant, w, ar.HttpRequest)
if authorized {
ar.Authorized = true
}
return handled, err
}
type emptyGrant struct{}
// NewEmptyGrant returns a no-op grant handler
func NewEmptyGrant() GrantHandler {
return emptyGrant{}
}
// GrantNeeded implements the GrantHandler interface
func (emptyGrant) GrantNeeded(user user.Info, grant *api.Grant, w http.ResponseWriter, req *http.Request) (bool, bool, error) {
return false, false, nil
}
type autoGrant struct {
}
// NewAutoGrant returns a grant handler that automatically approves client authorizations
func NewAutoGrant() GrantHandler {
return &autoGrant{}
}
// GrantNeeded implements the GrantHandler interface
func (g *autoGrant) GrantNeeded(user user.Info, grant *api.Grant, w http.ResponseWriter, req *http.Request) (bool, bool, error) {
return true, false, nil
}
type redirectGrant struct {
url string
}
// NewRedirectGrant returns a grant handler that redirects to the given URL when a grant is needed.
// The following query parameters are added to the URL:
// then - original request URL
// client_id - requesting client's ID
// scopes - grant scope requested
// redirect_uri - original authorize request redirect_uri
func NewRedirectGrant(url string) GrantHandler {
return &redirectGrant{url}
}
// GrantNeeded implements the GrantHandler interface
func (g *redirectGrant) GrantNeeded(user user.Info, grant *api.Grant, w http.ResponseWriter, req *http.Request) (bool, bool, error) {
redirectURL, err := url.Parse(g.url)
if err != nil {
return false, false, err
}
redirectURL.RawQuery = url.Values{
"then": {req.URL.String()},
"client_id": {grant.Client.GetId()},
"scopes": {grant.Scope},
"redirect_uri": {grant.RedirectURI},
}.Encode()
http.Redirect(w, req, redirectURL.String(), http.StatusFound)
return false, true, nil
}