Public/Authentication/Connect-FloRecruit.ps1
|
function Connect-FloRecruit { <# .SYNOPSIS Authenticates to the FloRecruit API and creates a session. .DESCRIPTION Authenticates using email and password (with optional MFA) to the FloRecruit API. Creates a session object that is used for all subsequent API calls. The session includes the authentication token and credentials for automatic re-authentication. .PARAMETER OrganizationName The FloRecruit organization name (used in the URL). .PARAMETER Email The email address for authentication. .PARAMETER Password The password as a SecureString (recommended). .PARAMETER PasswordPlainText The password as plain text (use only when necessary). .PARAMETER MFASecret The MFA secret as a SecureString (if MFA is enabled). .PARAMETER BaseUrl Override the base API URL (for testing/staging environments). .EXAMPLE $password = Read-Host -AsSecureString -Prompt "Enter Password" Connect-FloRecruit -OrganizationName "myorg" -Email "admin@myorg.com" -Password $password .EXAMPLE $password = Read-Host -AsSecureString -Prompt "Enter Password" $mfa = Read-Host -AsSecureString -Prompt "Enter MFA Secret" Connect-FloRecruit -OrganizationName "myorg" -Email "admin@myorg.com" -Password $password -MFASecret $mfa #> [CmdletBinding(DefaultParameterSetName = 'SecurePassword')] param( [Parameter(Mandatory)] [string]$OrganizationName, [Parameter(Mandatory)] [string]$Email, [Parameter(Mandatory, ParameterSetName = 'SecurePassword')] [System.Security.SecureString]$Password, [Parameter(Mandatory, ParameterSetName = 'PlainTextPassword')] [string]$PasswordPlainText, [Parameter(ParameterSetName = 'SecurePassword')] [Parameter(ParameterSetName = 'PlainTextPassword')] [System.Security.SecureString]$MFASecret, [Parameter()] [string]$BaseUrl ) # Convert plain text password to SecureString if using that parameter set if ($PSCmdlet.ParameterSetName -eq 'PlainTextPassword') { $Password = ConvertTo-SecureString -String $PasswordPlainText -AsPlainText -Force } # Build URLs if ($BaseUrl) { $authEndpoint = "$BaseUrl/admin/auth/" $apiBase = "$BaseUrl/api" } else { $authEndpoint = "https://florecruit.com/app/$OrganizationName/admin/auth/" $apiBase = "https://florecruit.com/app/$OrganizationName/api" } Write-Verbose "Authenticating to: $authEndpoint" try { # Convert SecureString password to plain text for authentication $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password) $plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) # Build authentication body $authBody = @{ email = $Email password = $plainPassword } # Add MFA if provided if ($MFASecret) { $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($MFASecret) $plainMFA = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR) $authBody['mfa_secret'] = $plainMFA } # Make authentication request $response = Invoke-WebRequest -Uri $authEndpoint -Method POST -Body ($authBody | ConvertTo-Json) -ContentType 'application/json' -SessionVariable webSession -ErrorAction Stop Write-Verbose "Authentication response status: $($response.StatusCode)" # Extract authentication token from cookies # FloRecruit returns 200 OK always - check for cookie presence to verify success $authCookie = $null $cookieString = $null # Try to get cookie from web session first if ($webSession -and $webSession.Cookies) { $authCookie = $webSession.Cookies.GetCookies($authEndpoint) | Where-Object { $_.Name -match 'auth|token|session' } | Select-Object -First 1 } if ($authCookie) { $cookieString = "$($authCookie.Name)=$($authCookie.Value)" } else { # Fallback: Try to extract from Set-Cookie header if ($response.Headers['Set-Cookie']) { $setCookieHeader = $response.Headers['Set-Cookie'] if ($setCookieHeader -match '([^=]+)=([^;]+)') { $cookieName = $Matches[1] $cookieValue = $Matches[2] $cookieString = "$cookieName=$cookieValue" } else { throw "Authentication failed: No valid authentication cookie found in response" } } else { throw "Authentication failed: No authentication cookie found in response" } } # Create session object $Script:FloRecruitSession = [PSCustomObject]@{ PSTypeName = 'FloRecruit.Session' OrganizationName = $OrganizationName Email = $Email Password = $Password MFASecret = $MFASecret BaseUrl = $apiBase AuthEndpoint = $authEndpoint AuthToken = $cookieString TokenExpiry = (Get-Date).AddMinutes(30) # Conservative estimate ConnectedAt = Get-Date RequestCount = 0 RateLimitWindowStart = Get-Date } Write-Host "Successfully connected to FloRecruit as $Email" -ForegroundColor Green # Return session info (without credentials) return [PSCustomObject]@{ PSTypeName = 'FloRecruit.SessionInfo' OrganizationName = $OrganizationName Email = $Email BaseUrl = $apiBase ConnectedAt = $Script:FloRecruitSession.ConnectedAt } } catch { Write-Error "Failed to connect to FloRecruit: $_" throw } finally { # Clear sensitive data from memory if ($plainPassword) { Clear-Variable -Name plainPassword -ErrorAction SilentlyContinue } if ($plainMFA) { Clear-Variable -Name plainMFA -ErrorAction SilentlyContinue } } } |