@@ -13,6 +13,7 @@ import (
13
13
"strings"
14
14
15
15
"code.gitea.io/gitea/models"
16
+ "code.gitea.io/gitea/modules/auth/sso"
16
17
"code.gitea.io/gitea/modules/base"
17
18
"code.gitea.io/gitea/modules/context"
18
19
"code.gitea.io/gitea/modules/log"
@@ -93,6 +94,24 @@ func (err AccessTokenError) Error() string {
93
94
return fmt .Sprintf ("%s: %s" , err .ErrorCode , err .ErrorDescription )
94
95
}
95
96
97
+ // BearerTokenErrorCode represents an error code specified in RFC 6750
98
+ type BearerTokenErrorCode string
99
+
100
+ const (
101
+ // BearerTokenErrorCodeInvalidRequest represents an error code specified in RFC 6750
102
+ BearerTokenErrorCodeInvalidRequest BearerTokenErrorCode = "invalid_request"
103
+ // BearerTokenErrorCodeInvalidToken represents an error code specified in RFC 6750
104
+ BearerTokenErrorCodeInvalidToken BearerTokenErrorCode = "invalid_token"
105
+ // BearerTokenErrorCodeInsufficientScope represents an error code specified in RFC 6750
106
+ BearerTokenErrorCodeInsufficientScope BearerTokenErrorCode = "insufficient_scope"
107
+ )
108
+
109
+ // BearerTokenError represents an error response specified in RFC 6750
110
+ type BearerTokenError struct {
111
+ ErrorCode BearerTokenErrorCode `json:"error" form:"error"`
112
+ ErrorDescription string `json:"error_description"`
113
+ }
114
+
96
115
// TokenType specifies the kind of token
97
116
type TokenType string
98
117
@@ -193,6 +212,45 @@ func newAccessTokenResponse(grant *models.OAuth2Grant, clientSecret string) (*Ac
193
212
}, nil
194
213
}
195
214
215
+ type userInfoResponse struct {
216
+ Sub string `json:"sub"`
217
+ Name string `json:"name"`
218
+ Username string `json:"preferred_username"`
219
+ Email string `json:"email"`
220
+ Picture string `json:"picture"`
221
+ }
222
+
223
+ // InfoOAuth manages request for userinfo endpoint
224
+ func InfoOAuth (ctx * context.Context ) {
225
+ header := ctx .Req .Header .Get ("Authorization" )
226
+ auths := strings .Fields (header )
227
+ if len (auths ) != 2 || auths [0 ] != "Bearer" {
228
+ ctx .HandleText (http .StatusUnauthorized , "no valid auth token authorization" )
229
+ return
230
+ }
231
+ uid := sso .CheckOAuthAccessToken (auths [1 ])
232
+ if uid == 0 {
233
+ handleBearerTokenError (ctx , BearerTokenError {
234
+ ErrorCode : BearerTokenErrorCodeInvalidToken ,
235
+ ErrorDescription : "Access token not assigned to any user" ,
236
+ })
237
+ return
238
+ }
239
+ authUser , err := models .GetUserByID (uid )
240
+ if err != nil {
241
+ ctx .ServerError ("GetUserByID" , err )
242
+ return
243
+ }
244
+ response := & userInfoResponse {
245
+ Sub : fmt .Sprint (authUser .ID ),
246
+ Name : authUser .FullName ,
247
+ Username : authUser .Name ,
248
+ Email : authUser .Email ,
249
+ Picture : authUser .AvatarLink (),
250
+ }
251
+ ctx .JSON (http .StatusOK , response )
252
+ }
253
+
196
254
// AuthorizeOAuth manages authorize requests
197
255
func AuthorizeOAuth (ctx * context.Context ) {
198
256
form := web .GetForm (ctx ).(* forms.AuthorizationForm )
@@ -571,3 +629,18 @@ func handleAuthorizeError(ctx *context.Context, authErr AuthorizeError, redirect
571
629
redirect .RawQuery = q .Encode ()
572
630
ctx .Redirect (redirect .String (), 302 )
573
631
}
632
+
633
+ func handleBearerTokenError (ctx * context.Context , beErr BearerTokenError ) {
634
+ ctx .Resp .Header ().Set ("WWW-Authenticate" , fmt .Sprintf ("Bearer realm=\" \" , error=\" %s\" , error_description=\" %s\" " , beErr .ErrorCode , beErr .ErrorDescription ))
635
+ switch beErr .ErrorCode {
636
+ case BearerTokenErrorCodeInvalidRequest :
637
+ ctx .JSON (http .StatusBadRequest , beErr )
638
+ case BearerTokenErrorCodeInvalidToken :
639
+ ctx .JSON (http .StatusUnauthorized , beErr )
640
+ case BearerTokenErrorCodeInsufficientScope :
641
+ ctx .JSON (http .StatusForbidden , beErr )
642
+ default :
643
+ log .Error ("Invalid BearerTokenErrorCode: %v" , beErr .ErrorCode )
644
+ ctx .ServerError ("Unhandled BearerTokenError" , fmt .Errorf ("BearerTokenError: error=\" %v\" , error_description=\" %v\" " , beErr .ErrorCode , beErr .ErrorDescription ))
645
+ }
646
+ }
0 commit comments