2023-03-12 16:00:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GoToSocial  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Copyright (C) GoToSocial Authors admin@gotosocial.org  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SPDX-License-Identifier: AGPL-3.0-or-later  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// 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/>.  
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								package  auth  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"net" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/gin-contrib/sessions" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/gin-gonic/gin" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/google/uuid" 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-02 13:10:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									apiutil  "github.com/superseriousbusiness/gotosocial/internal/api/util" 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/config" 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/db" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtserror" 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/oauth" 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/oidc" 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-01 18:29:25 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/validate" 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// extraInfo wraps a form-submitted username and transmitted name  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  extraInfo  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Username  string  ` form:"username" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Name      string  ` form:"name" `  // note that this is only used for re-rendering the page in case of an error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// CallbackGETHandler parses a token from an external auth provider.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Module )  CallbackGETHandler ( c  * gin . Context )  {  
						 
					
						
							
								
									
										
										
										
											2023-01-02 13:10:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! config . GetOIDCEnabled ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  errors . New ( "oidc is not enabled for this server" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorNotFound ( err ,  err . Error ( ) ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-02 13:10:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									s  :=  sessions . Default ( c ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// check the query vs session state parameter to mitigate csrf 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// https://auth0.com/docs/secure/attack-protection/state-parameters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									returnedInternalState  :=  c . Query ( callbackStateParam ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  returnedInternalState  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "%s parameter not found on callback query" ,  callbackStateParam ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  err . Error ( ) ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									savedInternalStateI  :=  s . Get ( sessionInternalState ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									savedInternalState ,  ok  :=  savedInternalStateI . ( string ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "key %s was not found in session" ,  sessionInternalState ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  err . Error ( ) ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  returnedInternalState  !=  savedInternalState  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-28 16:43:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  errors . New ( "mismatch between callback state and saved state" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorUnauthorized ( err ,  err . Error ( ) ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// retrieve stored claims using code 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									code  :=  c . Query ( callbackCodeParam ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  code  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "%s parameter not found on callback query" ,  callbackCodeParam ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  err . Error ( ) ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									claims ,  errWithCode  :=  m . idp . HandleCallback ( c . Request . Context ( ) ,  code ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// We can use the client_id on the session to retrieve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// info about the app associated with the client_id 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									clientID ,  ok  :=  s . Get ( sessionClientID ) . ( string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  ||  clientID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "key %s was not found in session" ,  sessionClientID ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  oauth . HelpfulAdvice ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 19:56:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									app  :=  & gtsmodel . Application { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  m . db . GetWhere ( c . Request . Context ( ) ,  [ ] db . Where { { Key :  sessionClientID ,  Value :  clientID } } ,  app ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										safe  :=  fmt . Sprintf ( "application for %s %s could not be retrieved" ,  sessionClientID ,  clientID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  errWithCode  gtserror . WithCode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  ==  db . ErrNoEntries  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											errWithCode  =  gtserror . NewErrorBadRequest ( err ,  safe ,  oauth . HelpfulAdvice ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-08 13:49:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											errWithCode  =  gtserror . NewErrorInternalError ( err ,  safe ,  oauth . HelpfulAdvice ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									user ,  errWithCode  :=  m . fetchUserForClaims ( c . Request . Context ( ) ,  claims ,  net . IP ( c . ClientIP ( ) ) ,  app . ID ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  user  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// no user exists yet - let's ask them for their preferred username 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										instance ,  errWithCode  :=  m . processor . InstanceGetV1 ( c . Request . Context ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											apiutil . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// store the claims in the session - that way we know the user is authenticated when processing the form later 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s . Set ( sessionClaims ,  claims ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s . Set ( sessionAppID ,  app . ID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  s . Save ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											apiutil . ErrorHandler ( c ,  gtserror . NewErrorInternalError ( err ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . HTML ( http . StatusOK ,  "finalize.tmpl" ,  gin . H { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"instance" :           instance , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"name" :               claims . Name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"preferredUsername" :  claims . PreferredUsername , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									s . Set ( sessionUserID ,  user . ID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  s . Save ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorInternalError ( err ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-02 13:10:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									c . Redirect ( http . StatusFound ,  "/oauth" + OauthAuthorizePath ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// FinalizePOSTHandler registers the user after additional data has been provided  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( m  * Module )  FinalizePOSTHandler ( c  * gin . Context )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s  :=  sessions . Default ( c ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									form  :=  & extraInfo { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  c . ShouldBind ( form ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  oauth . HelpfulAdvice ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// since we have multiple possible validation error, `validationError` is a shorthand for rendering them 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									validationError  :=  func ( err  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										instance ,  errWithCode  :=  m . processor . InstanceGetV1 ( c . Request . Context ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											apiutil . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . HTML ( http . StatusOK ,  "finalize.tmpl" ,  gin . H { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"instance" :           instance , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"name" :               form . Name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"preferredUsername" :  form . Username , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											"error" :              err , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check if the username conforms to the spec 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  validate . Username ( form . Username ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										validationError ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// see if the username is still available 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usernameAvailable ,  err  :=  m . db . IsUsernameAvailable ( c . Request . Context ( ) ,  form . Username ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  oauth . HelpfulAdvice ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! usernameAvailable  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										validationError ( fmt . Errorf ( "Username %s is already taken" ,  form . Username ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// retrieve the information previously set by the oidc logic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									appID ,  ok  :=  s . Get ( sessionAppID ) . ( string ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "key %s was not found in session" ,  sessionAppID ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  oauth . HelpfulAdvice ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// retrieve the claims returned by the IDP. Having this present means that we previously already verified these claims 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									claims ,  ok  :=  s . Get ( sessionClaims ) . ( * oidc . Claims ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "key %s was not found in session" ,  sessionClaims ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  oauth . HelpfulAdvice ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we're now ready to actually create the user 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									user ,  errWithCode  :=  m . createUserFromOIDC ( c . Request . Context ( ) ,  claims ,  form ,  net . IP ( c . ClientIP ( ) ) ,  appID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s . Delete ( sessionClaims ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s . Delete ( sessionAppID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s . Set ( sessionUserID ,  user . ID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  s . Save ( ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										m . clearSession ( s ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-02 14:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										apiutil . ErrorHandler ( c ,  gtserror . NewErrorInternalError ( err ) ,  m . processor . InstanceGetV1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-02 13:10:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									c . Redirect ( http . StatusFound ,  "/oauth" + OauthAuthorizePath ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * Module )  fetchUserForClaims ( ctx  context . Context ,  claims  * oidc . Claims ,  ip  net . IP ,  appID  string )  ( * gtsmodel . User ,  gtserror . WithCode )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  claims . Sub  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  errors . New ( "no sub claim found - is your provider OIDC compliant?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorBadRequest ( err ,  err . Error ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									user ,  err  :=  m . db . GetUserByExternalID ( ctx ,  claims . Sub ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  user ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-20 12:26:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  !=  db . ErrNoEntries  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "error checking database for externalID %s: %s" ,  claims . Sub ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorInternalError ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! config . GetOIDCLinkExisting ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// fallback to email if we want to link existing users 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									user ,  err  =  m . db . GetUserByEmailAddress ( ctx ,  claims . Email ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  ==  db . ErrNoEntries  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "error checking database for email %s: %s" ,  claims . Email ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorInternalError ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// at this point we have found a matching user but still need to link the newly received external ID 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									user . ExternalID  =  claims . Sub 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  =  m . db . UpdateUser ( ctx ,  user ,  "external_id" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "error linking existing user %s: %s" ,  claims . Email ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorInternalError ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  user ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 14:15:56 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( m  * Module )  createUserFromOIDC ( ctx  context . Context ,  claims  * oidc . Claims ,  extraInfo  * extraInfo ,  ip  net . IP ,  appID  string )  ( * gtsmodel . User ,  gtserror . WithCode )  {  
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Check if the claimed email address is available for use. 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 15:34:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									emailAvailable ,  err  :=  m . db . IsEmailAvailable ( ctx ,  claims . Email ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  gtserror . Newf ( "db error checking email availability: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorInternalError ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ! emailAvailable  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  help  =  "The email address given to us by your authentication provider already exists in our records and the server administrator has not enabled account migration" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  :=  gtserror . Newf ( "email address %s is not available" ,  claims . Email ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorConflict ( err ,  help ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// We still need to set something as a password, even 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// if it's not a password the user will end up using. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// We'll just set two uuids on top of each other, which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// should be long + random enough to baffle any attempts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// to crack, and which is also, conveniently, 72 bytes, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// which is the maximum length that bcrypt can handle. 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If the user ever wants to log in using a password 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// rather than oidc flow, they'll have to request a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// password reset, which is fine. 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									password  :=  uuid . NewString ( )  +  uuid . NewString ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// Since this user is created via OIDC, we can assume 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// that the account should be preapproved, and the email 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// address should be considered as verified already, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// since the OIDC login was successful. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-31 16:03:47 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// If we don't assume this, we end up in a situation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// where the admin first adds a user to OIDC, then has 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// to approve them again in GoToSocial when they log in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// there for the first time, which doesn't make sense. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-31 16:03:47 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// In other words, if a user logs in via OIDC, they 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// should be able to use their account straight away. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										preApproved    =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										emailVerified  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If one of the claimed groups corresponds to one of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// the configured admin OIDC groups, create this user 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// as an admin. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									admin  :=  adminGroup ( claims . Groups ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Create the user! This will also create an account and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// store it in the database, so we don't need to do that. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									user ,  err  :=  m . db . NewSignup ( ctx ,  gtsmodel . NewSignup { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Username :       extraInfo . Username , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Email :          claims . Email , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Password :       password , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SignUpIP :       ip , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AppID :          appID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ExternalID :     claims . Sub , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PreApproved :    preApproved , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										EmailVerified :  emailVerified , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Admin :          admin , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  gtserror . Newf ( "db error doing new signup: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  gtserror . NewErrorInternalError ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 10:36:28 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  user ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2023-07-23 12:33:17 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// adminGroup returns true if one of the given OIDC  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// groups is equal to at least one admin OIDC group.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  adminGroup ( groups  [ ] string )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  ag  :=  range  config . GetOIDCAdminGroups ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  g  :=  range  groups  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  strings . EqualFold ( ag ,  g )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// This is an admin group, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// ∴ user is an admin. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// User is in no admin groups, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// ∴ user is not an admin. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}