...
1
21
22 package openid
23
24 import (
25 "context"
26 "time"
27
28 "github.com/ory/x/errorsx"
29
30 "github.com/ory/fosite"
31 "github.com/ory/fosite/handler/oauth2"
32 "github.com/ory/fosite/token/jwt"
33 )
34
35 type OpenIDConnectHybridHandler struct {
36 AuthorizeImplicitGrantTypeHandler *oauth2.AuthorizeImplicitGrantTypeHandler
37 AuthorizeExplicitGrantHandler *oauth2.AuthorizeExplicitGrantHandler
38 IDTokenHandleHelper *IDTokenHandleHelper
39 ScopeStrategy fosite.ScopeStrategy
40 OpenIDConnectRequestValidator *OpenIDConnectRequestValidator
41 OpenIDConnectRequestStorage OpenIDConnectRequestStorage
42
43 Enigma *jwt.RS256JWTStrategy
44
45 MinParameterEntropy int
46 }
47
48 func (c *OpenIDConnectHybridHandler) HandleAuthorizeEndpointRequest(ctx context.Context, ar fosite.AuthorizeRequester, resp fosite.AuthorizeResponder) error {
49 if len(ar.GetResponseTypes()) < 2 {
50 return nil
51 }
52
53 if !(ar.GetResponseTypes().Matches("token", "id_token", "code") || ar.GetResponseTypes().Matches("token", "code") || ar.GetResponseTypes().Matches("id_token", "code")) {
54 return nil
55 }
56
57 ar.SetDefaultResponseMode(fosite.ResponseModeFragment)
58
59
60
61
62
63
64
65
66
67
68
69
70
71 nonce := ar.GetRequestForm().Get("nonce")
72
73 if len(nonce) == 0 && ar.GetResponseTypes().Has("id_token") {
74 return errorsx.WithStack(fosite.ErrInvalidRequest.WithHint("Parameter 'nonce' must be set when requesting an ID Token using the OpenID Connect Hybrid Flow."))
75 }
76
77 if len(nonce) > 0 && len(nonce) < c.MinParameterEntropy {
78 return errorsx.WithStack(fosite.ErrInsufficientEntropy.WithHintf("Parameter 'nonce' is set but does not satisfy the minimum entropy of %d characters.", c.MinParameterEntropy))
79 }
80
81 sess, ok := ar.GetSession().(Session)
82 if !ok {
83 return errorsx.WithStack(ErrInvalidSession)
84 }
85
86 if err := c.OpenIDConnectRequestValidator.ValidatePrompt(ctx, ar); err != nil {
87 return err
88 }
89
90 client := ar.GetClient()
91 for _, scope := range ar.GetRequestedScopes() {
92 if !c.ScopeStrategy(client.GetScopes(), scope) {
93 return errorsx.WithStack(fosite.ErrInvalidScope.WithHintf("The OAuth 2.0 Client is not allowed to request scope '%s'.", scope))
94 }
95 }
96
97 claims := sess.IDTokenClaims()
98 if ar.GetResponseTypes().Has("code") {
99 if !ar.GetClient().GetGrantTypes().Has("authorization_code") {
100 return errorsx.WithStack(fosite.ErrInvalidGrant.WithHint("The OAuth 2.0 Client is not allowed to use authorization grant 'authorization_code'."))
101 }
102
103 code, signature, err := c.AuthorizeExplicitGrantHandler.AuthorizeCodeStrategy.GenerateAuthorizeCode(ctx, ar)
104 if err != nil {
105 return errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
106 }
107
108
109
110
111
112
113
114
115
116 ar.GetSession().SetExpiresAt(fosite.AuthorizeCode, time.Now().UTC().Add(c.AuthorizeExplicitGrantHandler.AuthCodeLifespan).Round(time.Second))
117 if err := c.AuthorizeExplicitGrantHandler.CoreStorage.CreateAuthorizeCodeSession(ctx, signature, ar.Sanitize(c.AuthorizeExplicitGrantHandler.GetSanitationWhiteList())); err != nil {
118 return errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
119 }
120
121 resp.AddParameter("code", code)
122 ar.SetResponseTypeHandled("code")
123
124 hash, err := c.IDTokenHandleHelper.ComputeHash(ctx, sess, resp.GetParameters().Get("code"))
125 if err != nil {
126 return err
127 }
128 claims.CodeHash = hash
129
130 if ar.GetGrantedScopes().Has("openid") {
131 if err := c.OpenIDConnectRequestStorage.CreateOpenIDConnectSession(ctx, resp.GetCode(), ar.Sanitize(oidcParameters)); err != nil {
132 return errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
133 }
134 }
135 }
136
137 if ar.GetResponseTypes().Has("token") {
138 if !ar.GetClient().GetGrantTypes().Has("implicit") {
139 return errorsx.WithStack(fosite.ErrInvalidGrant.WithHint("The OAuth 2.0 Client is not allowed to use the authorization grant 'implicit'."))
140 } else if err := c.AuthorizeImplicitGrantTypeHandler.IssueImplicitAccessToken(ctx, ar, resp); err != nil {
141 return errorsx.WithStack(err)
142 }
143 ar.SetResponseTypeHandled("token")
144
145 hash, err := c.IDTokenHandleHelper.ComputeHash(ctx, sess, resp.GetParameters().Get("access_token"))
146 if err != nil {
147 return err
148 }
149 claims.AccessTokenHash = hash
150 }
151
152 if resp.GetParameters().Get("state") == "" {
153 resp.AddParameter("state", ar.GetState())
154 }
155
156 if !ar.GetGrantedScopes().Has("openid") || !ar.GetResponseTypes().Has("id_token") {
157 ar.SetResponseTypeHandled("id_token")
158 return nil
159 }
160
161 if err := c.IDTokenHandleHelper.IssueImplicitIDToken(ctx, ar, resp); err != nil {
162 return errorsx.WithStack(err)
163 }
164
165 ar.SetResponseTypeHandled("id_token")
166 return nil
167
168
169 }
170
View as plain text