From aad1fabe5af55d4eff911e04b7796c72bed9ece6 Mon Sep 17 00:00:00 2001 From: Jeremie Ben-Arros Date: Tue, 6 Aug 2024 17:06:31 -0400 Subject: [PATCH 1/3] allow P4V user client --- loginhook/ExtUtils.lua | 5 ++ loginhook/main.lua | 111 +++++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 49 deletions(-) diff --git a/loginhook/ExtUtils.lua b/loginhook/ExtUtils.lua index 4b296c4..ed4a9b8 100644 --- a/loginhook/ExtUtils.lua +++ b/loginhook/ExtUtils.lua @@ -208,6 +208,11 @@ function ExtUtils.verifyHost() return verify_host == "true" end +function ExtUtils.allowUserClientP4V() + local allow_user_client_p4v = ExtUtils.iCfgData[ "allow-user-client-p4v" ] + return allow_user_client_p4v == "true" +end + function ExtUtils.isClientUser( user ) -- users in the client-sso-users list are required to use P4LOGINSSO local required = ExtUtils.iCfgData[ "client-sso-users" ] diff --git a/loginhook/main.lua b/loginhook/main.lua index d0e8451..6a85dd4 100644 --- a/loginhook/main.lua +++ b/loginhook/main.lua @@ -40,7 +40,8 @@ function InstanceConfigFields() [ "client-name-identifier" ] = "... Field within JSON web token containing unique user identifier.", [ "user-identifier" ] = "... Trigger variable used as unique user identifier.", [ "name-identifier" ] = "... Field within IdP response containing unique user identifier.", - [ "enable-logging" ] = "... Extension will write debug messages to a log if 'true'." + [ "enable-logging" ] = "... Extension will write debug messages to a log if 'true'.", + [ "allow-user-client-p4v" ] = "... Extension will allow validation of JWT with user identifier." } end @@ -182,6 +183,56 @@ local function validateOAuthResponse( token ) return false, code, err end +local function webFlow() + -- Get a request id from the service, save it in requestId; do this every time + -- for every user, in case the same user logs in from multiple systems. We + -- will use this request identifier to get the status of the user later. + local userid = utils.userIdentifier( false ) + local easy = curl.easy() + local safe_id = easy:escape( userid ) + local ok, url, sdata = getData( utils.requestUrl( safe_id ) ) + if ok then + requestId = sdata[ "request" ] + -- Save the instanceId used in rule-based routing so that all subsequent + -- requests are routed to the appropriate instance of the service. + instanceId = sdata[ "instanceId" ] + else + utils.debug( { + [ "AuthPreSSO" ] = "error: failed to get request identifier", + [ "http-code" ] = url, + [ "http-error" ] = tostring( sdata ) + } ) + utils.debug( { + [ "AuthPreSSO" ] = "info: ensure Service-URL is valid", + [ "Service-URL" ] = utils.gCfgData[ "Service-URL" ] + } ) + -- At this point we know this user should be using SSO but there was a + -- problem, so try to inform them of what went wrong. + errorMessage = "error connecting to service, check extension logs" + return true, "unused", utils.serviceDownUrl(), false + end + local url = utils.loginUrl( sdata ) + -- Return the login URL as a property named `data` for P4PHP clients. + -- + -- N.B. Swarm uses a clientprog value of "P4PHP" when performing user login, + -- but the login will be handled differently in that case regardless. + local clientprog = Helix.Core.Server.GetVar( "clientprog" ) + if string.find( clientprog, "P4PHP" ) then + utils.debug( { [ "AuthPreSSO" ] = "info: loginURL via 'data' for P4PHP client" } ) + return true, url + end + -- Return the login URL as a property named `data` for Helix TeamHub. + if string.find( clientprog, "PilsnerHTHAdapter" ) then + utils.debug( { [ "AuthPreSSO" ] = "info: loginURL via 'data' for PilsnerHTHAdapter" } ) + return true, url + end + utils.debug( { + [ "AuthPreSSO" ] = "info: invoking URL " .. url, + [ "user" ] = user + } ) + return true, "unused", url, false +end + -- return -> (ret: bool, data: str, invokeURL: str, skipSSO: bool) -- required: 'ret' if false indicates error -- optional: 'data' has multiple meanings that depend on the use case @@ -209,6 +260,14 @@ function AuthPreSSO() return false end if hasClientUsers and isClientUser then + local currentClientProg = Helix.Core.Server.GetVar( "clientprog" ) + if currentClientProg:match( "^Helix P4V" ) ~= nil then + utils.debug( { + [ "AuthPreSSO" ] = "jump to ForceInteractiveSSO", + [ "user" ] = user + } ) + return webFlow() + end -- This user must authenticate via a P4LOGINSSO program that returns -- some form of "access token" (JWT) that the service will validate. utils.debug( { @@ -266,53 +325,7 @@ function AuthPreSSO() return true, "unused", "skipping", true end end - -- Get a request id from the service, save it in requestId; do this every time - -- for every user, in case the same user logs in from multiple systems. We - -- will use this request identifier to get the status of the user later. - local userid = utils.userIdentifier( false ) - local easy = curl.easy() - local safe_id = easy:escape( userid ) - local ok, url, sdata = getData( utils.requestUrl( safe_id ) ) - if ok then - requestId = sdata[ "request" ] - -- Save the instanceId used in rule-based routing so that all subsequent - -- requests are routed to the appropriate instance of the service. - instanceId = sdata[ "instanceId" ] - else - utils.debug( { - [ "AuthPreSSO" ] = "error: failed to get request identifier", - [ "http-code" ] = url, - [ "http-error" ] = tostring( sdata ) - } ) - utils.debug( { - [ "AuthPreSSO" ] = "info: ensure Service-URL is valid", - [ "Service-URL" ] = utils.gCfgData[ "Service-URL" ] - } ) - -- At this point we know this user should be using SSO but there was a - -- problem, so try to inform them of what went wrong. - errorMessage = "error connecting to service, check extension logs" - return true, "unused", utils.serviceDownUrl(), false - end - local url = utils.loginUrl( sdata ) - -- Return the login URL as a property named `data` for P4PHP clients. - -- - -- N.B. Swarm uses a clientprog value of "P4PHP" when performing user login, - -- but the login will be handled differently in that case regardless. - local clientprog = Helix.Core.Server.GetVar( "clientprog" ) - if string.find( clientprog, "P4PHP" ) then - utils.debug( { [ "AuthPreSSO" ] = "info: loginURL via 'data' for P4PHP client" } ) - return true, url - end - -- Return the login URL as a property named `data` for Helix TeamHub. - if string.find( clientprog, "PilsnerHTHAdapter" ) then - utils.debug( { [ "AuthPreSSO" ] = "info: loginURL via 'data' for PilsnerHTHAdapter" } ) - return true, url - end - utils.debug( { - [ "AuthPreSSO" ] = "info: invoking URL " .. url, - [ "user" ] = user - } ) - return true, "unused", url, false + return webFlow() end local function validateResponse( response ) @@ -491,4 +504,4 @@ function RunCommand( args ) Helix.Core.Server.ClientOutputText( "unsupported command: " .. cmd .. "\n" ) end return true -end +end \ No newline at end of file From 29a1318334d23294aca5bdb6c8c617a618e94de3 Mon Sep 17 00:00:00 2001 From: Jeremie Ben-Arros Date: Wed, 7 Aug 2024 09:05:41 -0400 Subject: [PATCH 2/3] correcting doc --- loginhook/main.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loginhook/main.lua b/loginhook/main.lua index 6a85dd4..b4bebcd 100644 --- a/loginhook/main.lua +++ b/loginhook/main.lua @@ -41,7 +41,7 @@ function InstanceConfigFields() [ "user-identifier" ] = "... Trigger variable used as unique user identifier.", [ "name-identifier" ] = "... Field within IdP response containing unique user identifier.", [ "enable-logging" ] = "... Extension will write debug messages to a log if 'true'.", - [ "allow-user-client-p4v" ] = "... Extension will allow validation of JWT with user identifier." + [ "allow-user-client-p4v" ] = "... Extension will allow P4V falling back to use SSO rather than using P4LOGINSSO." } end @@ -261,9 +261,9 @@ function AuthPreSSO() end if hasClientUsers and isClientUser then local currentClientProg = Helix.Core.Server.GetVar( "clientprog" ) - if currentClientProg:match( "^Helix P4V" ) ~= nil then + if utils.allowUserClientP4V() and currentClientProg:match( "^Helix P4V" ) ~= nil then utils.debug( { - [ "AuthPreSSO" ] = "jump to ForceInteractiveSSO", + [ "AuthPreSSO" ] = "info: P4V detected, will fallback to SSO", [ "user" ] = user } ) return webFlow() From c3e81f356c2d88e4a1ef90f741afd936b0f24200 Mon Sep 17 00:00:00 2001 From: Jeremie Ben-Arros Date: Wed, 7 Aug 2024 09:43:31 -0400 Subject: [PATCH 3/3] change wording --- loginhook/ExtUtils.lua | 2 +- loginhook/main.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loginhook/ExtUtils.lua b/loginhook/ExtUtils.lua index ed4a9b8..5ea9582 100644 --- a/loginhook/ExtUtils.lua +++ b/loginhook/ExtUtils.lua @@ -209,7 +209,7 @@ function ExtUtils.verifyHost() end function ExtUtils.allowUserClientP4V() - local allow_user_client_p4v = ExtUtils.iCfgData[ "allow-user-client-p4v" ] + local allow_user_client_p4v = ExtUtils.iCfgData[ "allow-user-client-p4v-to-sso" ] return allow_user_client_p4v == "true" end diff --git a/loginhook/main.lua b/loginhook/main.lua index b4bebcd..1a6da96 100644 --- a/loginhook/main.lua +++ b/loginhook/main.lua @@ -41,7 +41,7 @@ function InstanceConfigFields() [ "user-identifier" ] = "... Trigger variable used as unique user identifier.", [ "name-identifier" ] = "... Field within IdP response containing unique user identifier.", [ "enable-logging" ] = "... Extension will write debug messages to a log if 'true'.", - [ "allow-user-client-p4v" ] = "... Extension will allow P4V falling back to use SSO rather than using P4LOGINSSO." + [ "allow-user-client-p4v-to-sso" ] = "... Extension will fall back to SSO for P4V client rather than P4LOGINSSO if 'true'." } end