...
1
21
22 package oauth2
23
24 import (
25 "context"
26 "net/url"
27 "strings"
28 "time"
29
30 "github.com/ory/x/errorsx"
31
32 "github.com/ory/fosite"
33 )
34
35
36
37 type AuthorizeExplicitGrantHandler struct {
38 AccessTokenStrategy AccessTokenStrategy
39 RefreshTokenStrategy RefreshTokenStrategy
40 AuthorizeCodeStrategy AuthorizeCodeStrategy
41 CoreStorage CoreStorage
42
43
44
45 AuthCodeLifespan time.Duration
46
47
48 AccessTokenLifespan time.Duration
49
50
51 RefreshTokenLifespan time.Duration
52
53 ScopeStrategy fosite.ScopeStrategy
54 AudienceMatchingStrategy fosite.AudienceMatchingStrategy
55
56
57
58 SanitationWhiteList []string
59
60 TokenRevocationStorage TokenRevocationStorage
61
62 IsRedirectURISecure func(*url.URL) bool
63
64 RefreshTokenScopes []string
65
66
67
68 OmitRedirectScopeParam bool
69 }
70
71 func (c *AuthorizeExplicitGrantHandler) secureChecker() func(*url.URL) bool {
72 if c.IsRedirectURISecure == nil {
73 c.IsRedirectURISecure = fosite.IsRedirectURISecure
74 }
75 return c.IsRedirectURISecure
76 }
77
78 func (c *AuthorizeExplicitGrantHandler) HandleAuthorizeEndpointRequest(ctx context.Context, ar fosite.AuthorizeRequester, resp fosite.AuthorizeResponder) error {
79
80 if !ar.GetResponseTypes().ExactOne("code") {
81 return nil
82 }
83
84 ar.SetDefaultResponseMode(fosite.ResponseModeQuery)
85
86
87
88
89
90
91 if !c.secureChecker()(ar.GetRedirectURI()) {
92 return errorsx.WithStack(fosite.ErrInvalidRequest.WithHint("Redirect URL is using an insecure protocol, http is only allowed for hosts with suffix `localhost`, for example: http://myapp.localhost/."))
93 }
94
95 client := ar.GetClient()
96 for _, scope := range ar.GetRequestedScopes() {
97 if !c.ScopeStrategy(client.GetScopes(), scope) {
98 return errorsx.WithStack(fosite.ErrInvalidScope.WithHintf("The OAuth 2.0 Client is not allowed to request scope '%s'.", scope))
99 }
100 }
101
102 if err := c.AudienceMatchingStrategy(client.GetAudience(), ar.GetRequestedAudience()); err != nil {
103 return err
104 }
105
106 return c.IssueAuthorizeCode(ctx, ar, resp)
107 }
108
109 func (c *AuthorizeExplicitGrantHandler) IssueAuthorizeCode(ctx context.Context, ar fosite.AuthorizeRequester, resp fosite.AuthorizeResponder) error {
110 code, signature, err := c.AuthorizeCodeStrategy.GenerateAuthorizeCode(ctx, ar)
111 if err != nil {
112 return errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
113 }
114
115 ar.GetSession().SetExpiresAt(fosite.AuthorizeCode, time.Now().UTC().Add(c.AuthCodeLifespan))
116 if err := c.CoreStorage.CreateAuthorizeCodeSession(ctx, signature, ar.Sanitize(c.GetSanitationWhiteList())); err != nil {
117 return errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
118 }
119
120 resp.AddParameter("code", code)
121 resp.AddParameter("state", ar.GetState())
122 if !c.OmitRedirectScopeParam {
123 resp.AddParameter("scope", strings.Join(ar.GetGrantedScopes(), " "))
124 }
125
126 ar.SetResponseTypeHandled("code")
127 return nil
128 }
129
130 func (c *AuthorizeExplicitGrantHandler) GetSanitationWhiteList() []string {
131 if len(c.SanitationWhiteList) > 0 {
132 return c.SanitationWhiteList
133 }
134 return []string{
135 "code",
136 "redirect_uri",
137 }
138 }
139
View as plain text