Functions/Authentication/New-PASSession.ps1

# .ExternalHelp psPAS-help.xml
function New-PASSession {
    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Gen2')]
    param(
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ParameterSetName = 'Gen1'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-Subdomain-IdentityUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-IdentityUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-Subdomain-ServiceUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-ServiceUser'
        )]
        [ValidateNotNullOrEmpty()]
        [PSCredential]$Credential,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-Subdomain-IdentityUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-Subdomain-ServiceUser'
        )]
        [string]$TenantSubdomain,

        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1SAML'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2SAML'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'shared'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'integrated'
        )]
        [string]$BaseURI,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-IdentityUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-ServiceUser'
        )]
        [string]$IdentityTenantURL,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-IdentityUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-ServiceUser'
        )]
        [string]$PrivilegeCloudURL,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-Subdomain-IdentityUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-IdentityUser'
        )]
        [switch]$IdentityUser,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-Subdomain-ServiceUser'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'ISPSS-URL-ServiceUser'
        )]
        [switch]$ServiceUser,

        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1'
        )]
        [parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1SAML'
        )]
        [Alias('UseClassicAPI')]
        [switch]$UseGen1API,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1'
        )]
        [SecureString]$newPassword,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2SAML'
        )]
        [switch]$SAMLAuth,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2SAML'
        )]
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1SAML'
        )]
        [Alias('SAMLToken')]
        [String]$SAMLResponse,

        [Parameter(
            Mandatory = $True,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'shared'
        )]
        [switch]$UseSharedAuthentication,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [bool]$useRadiusAuthentication,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [ValidateSet('CyberArk', 'LDAP', 'Windows', 'RADIUS', 'PKI', 'PKIPN')]
        [string]$type = 'CyberArk',

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [string]$OTP,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [ValidateSet('Append', 'Challenge')]
        [string]$OTPMode,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [AllowEmptyString()]
        [string]$OTPDelimiter,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [ValidateSet('Password', 'OTP')]
        [string]$RadiusChallenge,

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'integrated'
        )]
        [switch]$UseDefaultCredentials,

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2'
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2Radius'
        )]
        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'integrated'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen2SAML'
        )]
        [Boolean]$concurrentSession,

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1'
        )]
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true,
            ParameterSetName = 'Gen1Radius'
        )]
        [ValidateRange(1, 100)]
        [int]$connectionNumber,

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [string]$PVWAAppName = 'PasswordVault',

        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $false
        )]
        [switch]$SkipVersionCheck,

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $false
        )]
        [X509Certificate]$Certificate,

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $false
        )]
        [string]$CertificateThumbprint,

        [parameter(
            Mandatory = $false,
            ValueFromPipeline = $false,
            ValueFromPipelinebyPropertyName = $true
        )]
        [switch]$SkipCertificateCheck

    )

    BEGIN {

        if ($baseURI) {

            #Ensure URL is in expected format
            #Remove trailing space and PasswordVault if provided in BaseUri
            $baseURI = $baseURI -replace '/$', ''
            $baseURI = $baseURI -replace '/PasswordVault$', ''
            #Build URL
            $Uri = "$baseURI/$PVWAAppName"

        }

        #Hashtable to hold Logon Request
        $LogonRequest = @{ }

        #Define Logon Request Parameters
        $LogonRequest['Method'] = 'POST'
        $LogonRequest['SessionVariable'] = 'PASSession'
        $LogonRequest['UseDefaultCredentials'] = $UseDefaultCredentials.IsPresent
        $LogonRequest['SkipCertificateCheck'] = $SkipCertificateCheck.IsPresent

        If ($PSBoundParameters['type'] -eq 'Windows') {

            $LogonRequest['Credential'] = $Credential

        }

        If ($CertificateThumbprint) {

            $LogonRequest['CertificateThumbprint'] = $CertificateThumbprint

        }

        If ($Certificate) {

            $LogonRequest['Certificate'] = $Certificate

        }

    }#begin

    PROCESS {

        Switch ($PSCmdlet.ParameterSetName) {

            ( { $PSItem -match '^ISPSS-URL' } ) {

                #Ensure URLs are in expected format
                #Remove trailing space and PasswordVault (if provided in PrivilegeCloudURL)
                $IdentityTenantURL = $IdentityTenantURL -replace '/$', ''
                $PrivilegeCloudURL = $PrivilegeCloudURL -replace '/$', ''
                $PrivilegeCloudURL = $PrivilegeCloudURL -replace '/PasswordVault$', ''

            }

            ( { $PSItem -match '^ISPSS-SubDomain' } ) {

                $SharedServicesURLs = Find-SharedServicesURL -subdomain $TenantSubdomain

                $IdentityTenantURL = $SharedServicesURLs | Select-Object -ExpandProperty identity_user_portal | Select-Object -ExpandProperty api
                $PrivilegeCloudURL = $SharedServicesURLs | Select-Object -ExpandProperty pcloud | Select-Object -ExpandProperty api

            }

            ( { $PSItem -match '^ISPSS-.*-.*User$' } ) {

                #IdentityUser/ServiceUser LogonRequest for New-IDSession/New-IDPlatformToken
                $LogonRequest['Uri'] = $IdentityTenantURL
                $LogonRequest['Credential'] = $Credential

                #URL for P Cloud API Operations
                $Uri = "${PrivilegeCloudURL}/$PVWAAppName"

                break
            }

            'integrated' {

                $LogonRequest['Uri'] = "$Uri/api/Auth/Windows/Logon"  #hardcode Windows for integrated auth

                #Construct Request Body
                #The only expected parameter should be concurrentSessions
                $LogonRequest['Body'] = $PSBoundParameters | Get-PASParameter -ParametersToKeep concurrentSession | ConvertTo-Json

                break

            }

            'shared' {

                Assert-VersionRequirement -SelfHosted

                $LogonRequest['Uri'] = "$Uri/WebServices/auth/Shared/RestfulAuthenticationService.svc/Logon"
                break

            }

            'Gen1SAML' {

                $LogonRequest['Uri'] = "$Uri/WebServices/auth/SAML/SAMLAuthenticationService.svc/Logon"

                #add token to header
                $LogonRequest['Headers'] = @{'Authorization' = $SAMLResponse }
                break

            }

            'Gen2SAML' {

                #*For SAML auth
                #The only expected parameter should be concurrentSession & SAMLResponse
                $boundParameters = $PSBoundParameters | Get-PASParameter -ParametersToKeep concurrentSession, SAMLResponse

                #add required parameters
                $boundParameters.Add('apiUse', $true)

                If ( -not ($PSBoundParameters.ContainsKey('SAMLResponse'))) {

                    #If no SAMLResponse provided
                    #Get SAML Response from IdP
                    #*https://gist.github.com/infamousjoeg/b44faa299ec3de65bdd1d3b8474b0649
                    $SAMLResponse = Get-PASSAMLResponse -URL $Uri

                    #add SAMLResponse to boundParameters
                    $boundParameters.Add('SAMLResponse', $SAMLResponse)

                }

                $LogonRequest['Body'] = $boundParameters
                $LogonRequest['ContentType'] = 'application/x-www-form-urlencoded'
                $LogonRequest['Uri'] = "$Uri/api/auth/SAML/Logon"
                break

            }

            ( { $PSItem -match '^Gen2' } ) {

                $LogonRequest['Uri'] = "$Uri/api/Auth/$type/Logon"

            }

            ( { $PSItem -match '^Gen1' } ) {

                $LogonRequest['Uri'] = "$Uri/WebServices/auth/Cyberark/CyberArkAuthenticationService.svc/Logon"

            }

            ( { $PSItem -match '^Gen' } ) {


                #Get request parameters
                $boundParameters = $PSBoundParameters | Get-PASParameter -ParametersToRemove Credential, SkipVersionCheck, SkipCertificateCheck,
                UseDefaultCredentials, CertificateThumbprint, BaseURI, PVWAAppName, OTP, type, OTPMode, OTPDelimiter, RadiusChallenge, Certificate

                #deal with newPassword SecureString
                If ($PSBoundParameters.ContainsKey('newPassword')) {

                    #Include decoded password in request
                    $boundParameters['newPassword'] = $(ConvertTo-InsecureString -SecureString $newPassword)

                }

                if ($type -ne 'PKIPN') {

                    if ($PSBoundParameters.Keys.Contains('Credential')) {
                        #Add user name from credential object
                        $boundParameters['username'] = $($Credential.UserName)
                        #Add decoded password value from credential object
                        $boundParameters['password'] = $($Credential.GetNetworkCredential().Password)
                    }

                } Else {
                    #PKIPN Auth
                    $boundParameters['secureMode'] = $true
                    $boundParameters['type'] = 'pkipn'
                }

                #RADIUS Auth
                If ($PSCmdlet.ParameterSetName -match 'Radius$') {

                    #OTP in Append Mode
                    If (($PSBoundParameters.ContainsKey('OTP')) -and ($PSBoundParameters['OTPMode'] -eq 'Append')) {

                        If ($PSBoundParameters.ContainsKey('OTPDelimiter')) {

                            #Use specified delimiter to append OTP
                            $Delimiter = $OTPDelimiter

                        } Else {

                            #delimit with comma by default
                            $Delimiter = ','

                        }

                        #Append OTP to password
                        $boundParameters['password'] = "$($boundParameters['password'])$Delimiter$OTP"

                    }

                    #RADIUS Challenge Mode
                    ElseIf (($PSBoundParameters.ContainsKey('OTP')) -and ($PSBoundParameters['OTPMode'] -eq 'Challenge')) {

                        If ($RadiusChallenge -eq 'Password') {

                            #Send OTP first + then Password
                            $boundParameters['password'] = $OTP
                            $($Credential.GetNetworkCredential().Password) | Set-Variable -Name OTP

                        }

                    }

                }

                #Construct Request Body
                $LogonRequest['Body'] = $boundParameters | ConvertTo-Json

                break

            }

        }

        if ($PSCmdlet.ShouldProcess($LogonRequest['Uri'], 'Logon')) {

            try {

                switch ($PSCmdlet.ParameterSetName) {
                    ( { $PSItem -match '^ISPSS' } ) {
                        #Check IdentityCommand module available
                        if (-not (Get-Module IdentityCommand)) {
                            try { Import-Module IdentityCommand -ErrorAction Stop }
                            catch { throw 'Failed to import IdentityCommand: Install the IdentityCommand Module and try again.' }
                        }
                    }
                    ( { $PSItem -match '^ISPSS-.*-IdentityUser$' } ) {
                        #Perform Identity User Authentication using IdentityCommand module
                        $PASSession = New-IDSession -tenant_url $LogonRequest['Uri'] -Credential $LogonRequest['Credential']
                        break
                    }
                    ( { $PSItem -match '^ISPSS-.*-ServiceUser$' } ) {
                        #Perform Identity User Authentication using IdentityCommand module
                        $PASSession = New-IDPlatformToken -tenant_url $LogonRequest['Uri'] -Credential $LogonRequest['Credential']
                        break
                    }
                    default {
                        #Send Logon Request
                        $PASSession = Invoke-PASRestMethod @LogonRequest
                        break
                    }
                }

                If ($null -ne $PASSession.UserName) {

                    #*$PASSession is expected to be a string value
                    #*For IIS Windows/PKI auth:
                    #*An object with a username property will be returned if a secondary authentication is required

                    #Use WebSession from initial request
                    $LogonRequest.Remove('SessionVariable')
                    $LogonRequest['WebSession'] = $psPASSession.WebSession

                    #Prepare auth request
                    switch ( $true ) {

                        ($PSCmdlet.ParameterSetName -match 'Radius$') {

                            #RADIUS Secondary auth
                            $LogonRequest['Uri'] = "$Uri/api/Auth/RADIUS/Logon"
                            break
                        }

                        ($type -eq 'PKI') {

                            #LDAP Secondary auth
                            $LogonRequest['Uri'] = "$Uri/api/Auth/LDAP/Logon"
                            break

                        }

                    }

                    #Submit secondary auth request
                    $PASSession = Invoke-PASRestMethod @LogonRequest

                }

            } catch {

                if ($PSItem.FullyQualifiedErrorId -notmatch 'ITATS542I') {

                    #Throw all errors not related to ITATS542I
                    throw $PSItem

                } Else {

                    #ITATS542I is expected for RADIUS Challenge

                    #Use WebSession from initial request
                    $LogonRequest.Remove('SessionVariable')
                    $LogonRequest['WebSession'] = $psPASSession.WebSession

                    #Collect values required to respond to the challenge
                    $RADIUSResponse = @{}
                    $RADIUSResponse['LogonRequest'] = $LogonRequest
                    $RADIUSResponse['Message'] = $($PSItem.Exception.Message)

                    #Include any OTP value provided in the RADIUS Response
                    If ($PSBoundParameters.ContainsKey('OTP')) {

                        #!If $RadiusChallenge = Password, $OTP will be password value
                        $RADIUSResponse['OTP'] = $OTP

                    }

                    #Respond to RADIUS challenge
                    $PASSession = Send-RADIUSResponse @RADIUSResponse

                }

            } finally {

                #If Logon Result
                If ($PASSession) {

                    switch ($PASSession) {

                        ( { $null -ne $PSItem.UserName } ) {

                            throw "No Session Token for user $($PASSession.UserName)"

                        }

                        ( { $null -ne $PSItem.access_token } ) {

                            #Shared Service access_token.
                            $CyberArkLogonResult = "$($PASSession.token_type) $($PASSession.access_token)"

                            #Make the IdentityCommand WebSession available in the psPAS module scope
                            $psPASSession.WebSession = $($PSItem.GetWebSession())

                        }

                        ( { $null -ne $PSItem.Token } ) {

                            #Shared Services Identity User Bearer Token
                            $CyberArkLogonResult = "Bearer $($PASSession.Token)"

                            #Make the IdentityCommand WebSession available in the psPAS module scope
                            $psPASSession.WebSession = $($PSItem.GetWebSession())

                        }

                        ( { $null -ne $PSItem.LogonResult } ) {

                            #Shared Auth LogonResult.
                            $CyberArkLogonResult = $PASSession.LogonResult

                        }

                        ( { $null -ne $PSItem.CyberArkLogonResult } ) {

                            #Classic CyberArkLogonResult
                            $CyberArkLogonResult = $PASSession.CyberArkLogonResult

                        }

                        default {

                            If ($PASSession.length -ge 180) {

                                #V10 Auth Token.
                                $CyberArkLogonResult = $PASSession

                            }

                        }

                    }

                    #Record Session Start Time
                    $psPASSession.StartTime = Get-Date

                    #BaseURI set in Module Scope
                    $psPASSession.BaseURI = $Uri

                    #API URL for non PasswordVault operations
                    $psPASSession.ApiURI = $PrivilegeCloudURL

                    #Auth token added to WebSession
                    $psPASSession.WebSession.Headers['Authorization'] = [string]$CyberArkLogonResult

                    #Initial Value for Version variable
                    [System.Version]$Version = '0.0'

                    if ( -not ($SkipVersionCheck)) {

                        Try {

                            #Get CyberArk ExternalVersion number.
                            [System.Version]$Version = Get-PASServer -ErrorAction Stop |
                                Select-Object -ExpandProperty ExternalVersion

                        } Catch { [System.Version]$Version = '0.0' }

                    }

                    #Version information available in module scope.
                    $psPASSession.ExternalVersion = $Version

                    Try {

                        #Get Authenticated User.
                        $User = Get-PASLoggedOnUser -ErrorAction Stop

                    } Catch {

                        if ($PSBoundParameters.ContainsKey('Credential')) {
                            $User = $Credential
                        } else {
                            $User = $null
                        }

                    } Finally {

                        if ($null -ne $User) {
                            $Username = $User | Select-Object -ExpandProperty UserName
                        } else { $Username = $User }

                        $psPASSession.User = $Username

                    }

                }

            }

        }

    }#process

    END { }#end

}