diff --git a/Project/Sources/Classes/OAuth2Authorization.4dm b/Project/Sources/Classes/OAuth2Authorization.4dm new file mode 100644 index 0000000..f9e7b6d --- /dev/null +++ b/Project/Sources/Classes/OAuth2Authorization.4dm @@ -0,0 +1,22 @@ +shared singleton Class constructor() + +Function getResponse($request : 4D.IncomingMessage) : 4D.OutgoingMessage + + var $response:=4D.OutgoingMessage.new() + var $body : Blob + var $state : Text:=cs.Tools.me.getURLParameterValue($request.url; "state") + var $options : Object:={state: $state} + $options.redirectURI:=$request.urlPath + $options.result:=$request.getJSON() + + If (_authorize($options; ->$body)) + + $response.setStatus(200) + $response.setHeader("Content-Type"; "text/html") + $response.setBody($body) + Else + + $response.setStatus(404) + End if + + return $response diff --git a/Project/Sources/Classes/OAuth2Provider.4dm b/Project/Sources/Classes/OAuth2Provider.4dm index 8aa56bf..6da73dd 100644 --- a/Project/Sources/Classes/OAuth2Provider.4dm +++ b/Project/Sources/Classes/OAuth2Provider.4dm @@ -30,7 +30,7 @@ property _grantType : Text property _codeVerifier : Text property _state : Text -property enableDebugLog : Boolean // Enable HTTP Server debug log for Debug purposes only +property enableDebugLog : Boolean // Enable HTTP Server debug log for Debug purposes only Class constructor($inParams : Object) @@ -496,7 +496,17 @@ Function _getToken_SignedIn($bUseRefreshToken : Boolean) : Object End if End if - If (cs.Tools.me.startWebServer($options)) + var $bUseHostDatabaseServer : Boolean:=False + var $hostDatabaseServer : Object:=WEB Server(Web server host database) + If (($hostDatabaseServer#Null)&& $hostDatabaseServer.isRunning) + If ($options.useTLS) + $bUseHostDatabaseServer:=($hostDatabaseServer.HTTPSEnabled && ($hostDatabaseServer.HTTPSPort=$options.port)) + Else + $bUseHostDatabaseServer:=($hostDatabaseServer.HTTPEnabled && ($hostDatabaseServer.HTTPPort=$options.port)) + End if + End if + + If ($bUseHostDatabaseServer || cs.Tools.me.startWebServer($options)) var $authorizationCode : Text:=This._getAuthorizationCode() diff --git a/Project/Sources/Classes/Tools.4dm b/Project/Sources/Classes/Tools.4dm index d027d2e..148eab2 100644 --- a/Project/Sources/Classes/Tools.4dm +++ b/Project/Sources/Classes/Tools.4dm @@ -236,6 +236,28 @@ Function getJMAPAttribute($inKey : Text) : Text // ---------------------------------------------------- +Function getDomainFromURL($URL : Text) : Text + + ARRAY LONGINT($pos; 0) + ARRAY LONGINT($len; 0) + + var $result : Text + var $pattern : Text:="(?mi-s)^(https?|wss?)://(.*)(:\\d*)(/?.*)" + + If (Match regex($pattern; $URL; 1; $pos; $len)) + + If (Size of array($pos)>2) + $result:=Substring($URL; $pos{3}+1; $len{3}-1) + End if + + End if + + return $result + + + // ---------------------------------------------------- + + Function getPathFromURL($URL : Text) : Text ARRAY LONGINT($pos; 0) @@ -341,6 +363,35 @@ Function isEmailAddressHeader($inKey : Text) : Boolean // ---------------------------------------------------- +Function isLocalIP($inIPAddress : Text) : Boolean + + If (Length($inIPAddress)=0) + return False + End if + If (($inIPAddress="127.0.0.1") || ($inIPAddress="::1") || ($inIPAddress="localhost")) + return True + End if + + var $sysInfo : Object:=System info + var $networkInterfaces : Collection:=$sysInfo.networkInterfaces + var $networkInterface : Object + + For each ($networkInterface; $networkInterfaces) + var $ipAddresses : Collection:=$networkInterface.ipAddresses + var $ipAddress : Object + For each ($ipAddress; $ipAddresses) + If ($ipAddress.ip=$inIPAddress) + return True + End if + End for each + End for each + + return False + + + // ---------------------------------------------------- + + Function isValidEmail($inEmail : Text) : Boolean var $pattern : Text:="(?i)^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$" @@ -350,23 +401,23 @@ Function isValidEmail($inEmail : Text) : Boolean // ---------------------------------------------------- -Function quoteString($inString : text) : text +Function quoteString($inString : Text) : Text var $result : Text:=$inString var $length : Integer:=Length($result) - - if($length>0) - if ($result[[1]]#"\"") + + If ($length>0) + If ($result[[1]]#"\"") $result:="\""+$result - End if + End if If ($result[[$length]]#"\"") $result+="\"" - End if - End if - + End if + End if + return $result - - + + // ---------------------------------------------------- @@ -545,6 +596,6 @@ Function urlEncode($value : Text) : Text Function localizedString($inValue : Text) : Text - - /* Temp to avoid compilation issues due to command renaming */ - return Localized string:C991($inValue) + +/* Temp to avoid compilation issues due to command renaming */ + return Localized string:C991($inValue) \ No newline at end of file diff --git a/Project/Sources/Methods/_authorize.4dm b/Project/Sources/Methods/_authorize.4dm new file mode 100644 index 0000000..3c7c9a6 --- /dev/null +++ b/Project/Sources/Methods/_authorize.4dm @@ -0,0 +1,76 @@ +//%attributes = {"invisible":true} +#DECLARE($inOptions : Object; $outResponseBodyPtr : Pointer) : Boolean + +var $redirectURI : Text +var $URL : Text:=$inOptions.redirectURI +var $customResponseFile; $customErrorFile : 4D.File +var $state : Text:=String($inOptions.state) +var $responseFile : 4D.File:=Folder(fk resources folder).file("Response_Template.html") + +If (OB Is defined(Storage.requests; $state)) + $redirectURI:=String(Storage.requests[$state].redirectURI) + If (Length($redirectURI)>0) + $redirectURI:=cs.Tools.me.getPathFromURL($redirectURI)+"@" + End if + $customResponseFile:=(Value type(Storage.requests[$state].authenticationPage)#Is undefined) ? Storage.requests[$state].authenticationPage : Null + $customErrorFile:=(Value type(Storage.requests[$state].authenticationErrorPage)#Is undefined) ? Storage.requests[$state].authenticationErrorPage : Null +End if + +If ($URL=$redirectURI) + + var $pageTitle; $pageMessage; $pageDetails : Text + + If (OB Is defined(Storage.requests; $state)) + Use (Storage.requests[$state]) + Storage.requests[$state].token:=$inOptions.result + End use + End if + + If (($inOptions.result=Null) | (OB Is defined($inOptions.result; "error"))) + + $pageTitle:=cs.Tools.me.localizedString("OAuth2_Response_Title") + $pageMessage:=cs.Tools.me.localizedString("OAuth2_Error_Message") + + If (OB Is defined($inOptions.result; "error")) + $pageMessage+=("

"+String($inOptions.result.error)) + End if + If (OB Is defined($inOptions.result; "error_subtype")) + $pageMessage+=("

"+String($inOptions.result.error_subtype)) + End if + If (OB Is defined($inOptions.result; "error_description")) + $pageMessage+=("

"+String($inOptions.result.error_description)) + End if + If (OB Is defined($inOptions.result; "error_uri")) + $pageMessage+=("

"+String($inOptions.result.error_uri)) + End if + $pageDetails:=cs.Tools.me.localizedString("OAuth2_Response_Details") + + $responseFile:=($customErrorFile#Null) ? $customErrorFile : $responseFile + Else + + $pageTitle:=cs.Tools.me.localizedString("OAuth2_Response_Title") + $pageMessage:=cs.Tools.me.localizedString("OAuth2_Response_Message") + $pageDetails:=cs.Tools.me.localizedString("OAuth2_Response_Details") + + $responseFile:=($customResponseFile#Null) ? $customResponseFile : $responseFile + End if + + var $responseFileContent : Text:=$responseFile.getText() + var $outResponseBody : Text:="" + + PROCESS 4D TAGS($responseFileContent; $outResponseBody; $pageTitle; $pageMessage; $pageDetails) + + If (Type($outResponseBodyPtr)=Is pointer) + Case of + : (Type($outResponseBodyPtr->)=Is text) + $outResponseBodyPtr->:=$outResponseBody + : (Type($outResponseBodyPtr->)=Is BLOB) + CONVERT FROM TEXT($outResponseBody; "UTF-8"; $outResponseBodyPtr->) + End case + End if + + return True + +End if + +return False diff --git a/Project/Sources/Methods/_onWebConnection.4dm b/Project/Sources/Methods/_onWebConnection.4dm index 15dfde4..f77649b 100644 --- a/Project/Sources/Methods/_onWebConnection.4dm +++ b/Project/Sources/Methods/_onWebConnection.4dm @@ -2,24 +2,19 @@ #DECLARE($URL : Text; $header : Text; $peerIP : Text; $localIP : Text; $username : Text; $password : Text) var $redirectURI : Text -var $customResponseFile; $customErrorFile : 4D.File var $state : Text:=cs.Tools.me.getURLParameterValue($1; "state") -var $responseFile : 4D.File:=Folder(fk resources folder).file("Response_Template.html") If (OB Is defined(Storage.requests; $state)) $redirectURI:=String(Storage.requests[$state].redirectURI) If (Length($redirectURI)>0) $redirectURI:=cs.Tools.me.getPathFromURL($redirectURI)+"@" End if - $customResponseFile:=(Value type(Storage.requests[$state].authenticationPage)#Is undefined) ? Storage.requests[$state].authenticationPage : Null - $customErrorFile:=(Value type(Storage.requests[$state].authenticationErrorPage)#Is undefined) ? Storage.requests[$state].authenticationErrorPage : Null End if If ($URL=$redirectURI) - var $result : Object - var WSTITLE; WSMESSAGE; WSDETAILS : Text - + var $options : Object:={redirectURI: $redirectURI; state: $state} + ARRAY TEXT($names; 0) ARRAY TEXT($values; 0) WEB GET VARIABLES($names; $values) @@ -27,54 +22,23 @@ If ($URL=$redirectURI) If (Size of array($names)>0) var $i : Integer - $result:=New shared object + var $result : Object:=New shared object Use ($result) For ($i; 1; Size of array($names)) $result[$names{$i}]:=$values{$i} End for End use - + $options.result:=$result End if - If (OB Is defined(Storage.requests; $state)) - Use (Storage.requests[$state]) - Storage.requests[$state].token:=$result - End use - End if - - If (($result=Null) | (OB Is defined($result; "error"))) - - WSTITLE:=cs.Tools.me.localizedString("OAuth2_Response_Title") - WSMESSAGE:=cs.Tools.me.localizedString("OAuth2_Error_Message") + var $responseBody : Blob + If (_authorize($options; ->$responseBody)) - If (OB Is defined($result; "error")) - WSMESSAGE:=WSMESSAGE+"

"+$result.error - End if - If (OB Is defined($result; "error_subtype")) - WSMESSAGE:=WSMESSAGE+"

"+$result.error_subtype - End if - If (OB Is defined($result; "error_description")) - WSMESSAGE:=WSMESSAGE+"

"+$result.error_description - End if - If (OB Is defined($result; "error_uri")) - WSMESSAGE:=WSMESSAGE+"

"+$result.error_uri - End if - WSDETAILS:=cs.Tools.me.localizedString("OAuth2_Response_Details") - - $responseFile:=($customErrorFile#Null) ? $customErrorFile : $responseFile - Else - - WSTITLE:=cs.Tools.me.localizedString("OAuth2_Response_Title") - WSMESSAGE:=cs.Tools.me.localizedString("OAuth2_Response_Message") - WSDETAILS:=cs.Tools.me.localizedString("OAuth2_Response_Details") - - $responseFile:=($customResponseFile#Null) ? $customResponseFile : $responseFile + var $contentType : Text:="Content-Type: text/html" + WEB SET HTTP HEADER($contentType) + WEB SEND RAW DATA($responseBody) End if - WEB SEND FILE($responseFile.platformPath) - -Else - - // Nothing to do... 404 will be automatically sent - End if + +// Nothing to do... 404 will be automatically sent diff --git a/Resources/Response_Template.html b/Resources/Response_Template.html index 92a47b1..4090003 100644 --- a/Resources/Response_Template.html +++ b/Resources/Response_Template.html @@ -14,7 +14,7 @@ -<!--#4DTEXT WSTITLE-->  +<!--#4DTEXT $1-->  -

-

-

+

+

+