2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/ *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   GoToSocial 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-05 12:43:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								   Copyright  ( C )  2021 - 2023  GoToSocial  Authors  admin @ gotosocial . org 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   This  program  is  free  software :  you  can  redistribute  it  and / or  modify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   it  under  the  terms  of  the  GNU  Affero  General  Public  License  as  published  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   the  Free  Software  Foundation ,  either  version  3  of  the  License ,  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   ( at  your  option )  any  later  version . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   This  program  is  distributed  in  the  hope  that  it  will  be  useful , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   but  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .   See  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   GNU  Affero  General  Public  License  for  more  details . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   You  should  have  received  a  copy  of  the  GNU  Affero  General  Public  License 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   along  with  this  program .   If  not ,  see  < http : //www.gnu.org/licenses/>. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* /  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  oauth  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-28 11:38:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/db" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-11 10:39:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtserror" 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/log" 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/oauth2/v4" 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-28 11:38:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									oautherr  "github.com/superseriousbusiness/oauth2/v4/errors" 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/oauth2/v4/manage" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/oauth2/v4/server" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
									
										
										
										
											2021-04-19 19:42:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// SessionAuthorizedToken is the key set in the gin context for the Token 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// of a User who has successfully passed Bearer token authorization. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// The interface returned from grabbing this key should be parsed as oauth2.TokenInfo 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									SessionAuthorizedToken  =  "authorized_token" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// SessionAuthorizedUser is the key set in the gin context for the id of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// a User who has successfully passed Bearer token authorization. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// The interface returned from grabbing this key should be parsed as a *gtsmodel.User 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SessionAuthorizedUser  =  "authorized_user" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// SessionAuthorizedAccount is the key set in the gin context for the Account 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// of a User who has successfully passed Bearer token authorization. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// The interface returned from grabbing this key should be parsed as a *gtsmodel.Account 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SessionAuthorizedAccount  =  "authorized_account" 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-20 18:14:23 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// SessionAuthorizedApplication is the key set in the gin context for the Application 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// of a Client who has successfully passed Bearer token authorization. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// The interface returned from grabbing this key should be parsed as a *gtsmodel.Application 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SessionAuthorizedApplication  =  "authorized_app" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// OOBURI is the out-of-band oauth token uri 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									OOBURI  =  "urn:ietf:wg:oauth:2.0:oob" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// OOBTokenPath is the path to redirect out-of-band token requests to. 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-18 16:47:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									OOBTokenPath  =  "/oauth/oob"  // #nosec G101 else we get a hardcoded credentials warning 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// HelpfulAdvice is a handy hint to users; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// particularly important during the login flow 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-28 11:38:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									HelpfulAdvice       =  "If you arrived at this error during a login/oauth flow, please try clearing your session cookies and logging in again; if problems persist, make sure you're using the correct credentials" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									HelpfulAdviceGrant  =  "If you arrived at this error during a login/oauth flow, your client is trying to use an unsupported OAuth grant type. Supported grant types are: authorization_code, client_credentials; please reach out to developer of your client" 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Server wraps some oauth2 server functions in an interface, exposing only what is needed  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Server  interface  {  
						 
					
						
							
								
									
										
										
										
											2022-06-11 10:39:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									HandleTokenRequest ( r  * http . Request )  ( map [ string ] interface { } ,  gtserror . WithCode ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									HandleAuthorizeRequest ( w  http . ResponseWriter ,  r  * http . Request )  gtserror . WithCode 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ValidationBearerToken ( r  * http . Request )  ( oauth2 . TokenInfo ,  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-04 15:24:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									GenerateUserAccessToken ( ctx  context . Context ,  ti  oauth2 . TokenInfo ,  clientSecret  string ,  userID  string )  ( accessToken  oauth2 . TokenInfo ,  err  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									LoadAccessToken ( ctx  context . Context ,  access  string )  ( accessToken  oauth2 . TokenInfo ,  err  error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// s fulfils the Server interface using the underlying oauth2 server  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  s  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									server  * server . Server 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// New returns a new oauth server that implements the Server interface  
						 
					
						
							
								
									
										
										
										
											2021-10-11 05:37:33 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  New ( ctx  context . Context ,  database  db . Basic )  Server  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ts  :=  newTokenStore ( ctx ,  database ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cs  :=  NewClientStore ( database ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									manager  :=  manage . NewDefaultManager ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									manager . MapTokenStorage ( ts ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									manager . MapClientStorage ( cs ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-10 16:29:05 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									manager . SetAuthorizeCodeTokenCfg ( & manage . Config { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AccessTokenExp :     0 ,      // access tokens don't expire -- they must be revoked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IsGenerateRefresh :  false ,  // don't use refresh tokens 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sc  :=  & server . Config { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										TokenType :  "Bearer" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Must follow the spec. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AllowGetAccessRequest :  false , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Support only the non-implicit flow. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AllowedResponseTypes :  [ ] oauth2 . ResponseType { oauth2 . Code } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Allow: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// - Authorization Code (for first & third parties) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// - Client Credentials (for applications) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AllowedGrantTypes :  [ ] oauth2 . GrantType { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oauth2 . AuthorizationCode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											oauth2 . ClientCredentials , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AllowedCodeChallengeMethods :  [ ] oauth2 . CodeChallengeMethod { oauth2 . CodeChallengePlain } , 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									srv  :=  server . NewServer ( sc ,  manager ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-28 11:38:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									srv . SetInternalErrorHandler ( func ( err  error )  * oautherr . Response  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-17 12:02:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										log . Errorf ( nil ,  "internal oauth error: %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-28 11:38:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									srv . SetResponseErrorHandler ( func ( re  * oautherr . Response )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-17 12:02:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										log . Errorf ( nil ,  "internal response error: %s" ,  re . Error ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									srv . SetUserAuthorizationHandler ( func ( w  http . ResponseWriter ,  r  * http . Request )  ( string ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										userID  :=  r . FormValue ( "userid" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  userID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  "" ,  errors . New ( "userid was empty" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-08 14:25:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  userID ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									srv . SetClientInfoHandler ( server . ClientFormHandler ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & s { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										server :  srv , 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// HandleTokenRequest wraps the oauth2 library's HandleTokenRequest function  
						 
					
						
							
								
									
										
										
										
											2022-06-11 10:39:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( s  * s )  HandleTokenRequest ( r  * http . Request )  ( map [ string ] interface { } ,  gtserror . WithCode )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  r . Context ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									gt ,  tgr ,  err  :=  s . server . ValidationTokenRequest ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										help  :=  fmt . Sprintf ( "could not validate token request: %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-28 11:38:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										adv  :=  HelpfulAdvice 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  errors . Is ( err ,  oautherr . ErrUnsupportedGrantType )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											adv  =  HelpfulAdviceGrant 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorBadRequest ( err ,  help ,  adv ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-11 10:39:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ti ,  err  :=  s . server . GetAccessToken ( ctx ,  gt ,  tgr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										help  :=  fmt . Sprintf ( "could not get access token: %s" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorBadRequest ( err ,  help ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-11 10:39:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									data  :=  s . server . GetTokenData ( ti ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  expiresInI ,  ok  :=  data [ "expires_in" ] ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  expiresIn  :=  expiresInI . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  int64 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// remove this key from the returned map 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// if the value is 0 or less, so that clients 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// don't interpret the token as already expired 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  expiresIn  <=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												delete ( data ,  "expires_in" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  :=  errors . New ( "expires_in was set on token response, but was not an int64" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil ,  gtserror . NewErrorInternalError ( err ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// add this for mastodon api compatibility 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-11 10:39:39 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									data [ "created_at" ]  =  ti . GetAccessCreateAt ( ) . Unix ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  data ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( s  * s )  errorOrRedirect ( err  error ,  w  http . ResponseWriter ,  req  * server . AuthorizeRequest )  gtserror . WithCode  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  req  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  gtserror . NewErrorUnauthorized ( err ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									data ,  _ ,  _  :=  s . server . GetErrorData ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uri ,  err  :=  s . server . GetRedirectURI ( req ,  data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  gtserror . NewErrorInternalError ( err ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									w . Header ( ) . Set ( "Location" ,  uri ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									w . WriteHeader ( http . StatusFound ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// HandleAuthorizeRequest wraps the oauth2 library's HandleAuthorizeRequest function  
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( s  * s )  HandleAuthorizeRequest ( w  http . ResponseWriter ,  r  * http . Request )  gtserror . WithCode  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ctx  :=  r . Context ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									req ,  err  :=  s . server . ValidationAuthorizeRequest ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  s . errorOrRedirect ( err ,  w ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// user authorization 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									userID ,  err  :=  s . server . UserAuthorizationHandler ( w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  s . errorOrRedirect ( err ,  w ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  userID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										help  :=  "userID was empty" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  gtserror . NewErrorUnauthorized ( err ,  help ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									req . UserID  =  userID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// specify the scope of authorization 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  fn  :=  s . server . AuthorizeScopeHandler ;  fn  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										scope ,  err  :=  fn ( w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  s . errorOrRedirect ( err ,  w ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  scope  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											req . Scope  =  scope 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// specify the expiration time of access token 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  fn  :=  s . server . AccessTokenExpHandler ;  fn  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										exp ,  err  :=  fn ( w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  s . errorOrRedirect ( err ,  w ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										req . AccessTokenExp  =  exp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ti ,  err  :=  s . server . GetAuthorizeToken ( ctx ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  s . errorOrRedirect ( err ,  w ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If the redirect URI is empty, the default domain provided by the client is used. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  req . RedirectURI  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										client ,  err  :=  s . server . Manager . GetClient ( ctx ,  req . ClientID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  gtserror . NewErrorUnauthorized ( err ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										req . RedirectURI  =  client . GetDomain ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uri ,  err  :=  s . server . GetRedirectURI ( req ,  s . server . GetAuthorizeData ( req . ResponseType ,  ti ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  gtserror . NewErrorUnauthorized ( err ,  HelpfulAdvice ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  strings . Contains ( uri ,  OOBURI )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										w . Header ( ) . Set ( "Location" ,  strings . ReplaceAll ( uri ,  OOBURI ,  OOBTokenPath ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										w . Header ( ) . Set ( "Location" ,  uri ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									w . WriteHeader ( http . StatusFound ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ValidationBearerToken wraps the oauth2 library's ValidationBearerToken function  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * s )  ValidationBearerToken ( r  * http . Request )  ( oauth2 . TokenInfo ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  s . server . ValidationBearerToken ( r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GenerateUserAccessToken shortcuts the normal oauth flow to create an user-level  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// bearer token *without* requiring that user to log in. This is useful when we  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// need to create a token for new users who haven't validated their email or logged in yet.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The ti parameter refers to an existing Application token that was used to make the upstream  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// request. This token needs to be validated and exist in database in order to create a new token.  
						 
					
						
							
								
									
										
										
										
											2021-10-04 15:24:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( s  * s )  GenerateUserAccessToken ( ctx  context . Context ,  ti  oauth2 . TokenInfo ,  clientSecret  string ,  userID  string )  ( oauth2 . TokenInfo ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									authToken ,  err  :=  s . server . Manager . GenerateAuthToken ( ctx ,  oauth2 . Code ,  & oauth2 . TokenGenerateRequest { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										ClientID :      ti . GetClientID ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ClientSecret :  clientSecret , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										UserID :        userID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RedirectURI :   ti . GetRedirectURI ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Scope :         ti . GetScope ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "error generating auth token: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  authToken  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "generated auth token was empty" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-17 12:02:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									log . Tracef ( ctx ,  "obtained auth token: %+v" ,  authToken ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-04 15:24:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									accessToken ,  err  :=  s . server . Manager . GenerateAccessToken ( ctx ,  oauth2 . AuthorizationCode ,  & oauth2 . TokenGenerateRequest { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										ClientID :      authToken . GetClientID ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ClientSecret :  clientSecret , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RedirectURI :   authToken . GetRedirectURI ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Scope :         authToken . GetScope ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Code :          authToken . GetCode ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "error generating user-level access token: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  accessToken  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "generated user-level access token was empty" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-17 12:02:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									log . Tracef ( ctx ,  "obtained user-level access token: %+v" ,  accessToken ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 20:46:45 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  accessToken ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( s  * s )  LoadAccessToken ( ctx  context . Context ,  access  string )  ( accessToken  oauth2 . TokenInfo ,  err  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  s . server . Manager . LoadAccessToken ( ctx ,  access ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}