public/Get-OktaJwt.ps1
Set-StrictMode -Version Latest function Get-OktaJwt { [CmdletBinding()] [OutputType([string])] param ( [string] $ClientId = $env:OKTA_CLIENT_ID, [string] $Issuer = $env:OKTA_ISSUER, [Parameter(ParameterSetName="User")] [string] $RedirectUri = $env:OKTA_REDIRECT_URI, [Parameter(ParameterSetName="User")] [string] $Username = $env:OKTA_USERNAME, [Alias("Pw")] [string] $ClientSecret = $env:OKTA_CLIENT_SECRET, [Alias("Password")] [securestring] $SecureClientSecret, [Parameter(ParameterSetName="User")] [switch] $IdToken, [Parameter(Mandatory)] [string[]] $Scopes, [Parameter(Mandatory)] [ValidateSet("authorization_code", "password", "refresh_token", "client_credentials", "implicit")] [string] $GrantType ) $ErrorActionPreference = "Stop" if ((!$ClientSecret -and !$SecureClientSecret) -or !$Issuer -or !$ClientId -or ($Username -and !$RedirectUri)) { throw "Missing required parameter. See help." } if ($SecureClientSecret) { # (from VSTeam) # Convert the securestring to a normal string # this was the one technique that worked on Mac, Linux and Windows $credential = New-Object System.Management.Automation.PSCredential $account, $SecurePersonalAccessToken $secret = $credential.GetNetworkCredential().Password } else { $secret = $ClientSecret } if ($Username) { # Code derived from https://devforum.okta.com/t/unit-testing-and-implicit-flow/1210/4 $body = @{ username = $Username password = $secret options = @{ multiOptionalFactorEnroll = $true warnBeforePasswordExpired = $true } } $uri = New-Object 'System.Uri' -ArgumentList $Issuer $baseUri = New-Object 'System.Uri' -ArgumentList $uri.GetLeftPart("Authority") $sessionUri = New-Object 'System.Uri' -ArgumentList $baseUri, "api/v1/authn" try { $trans = Invoke-WebRequest -Uri $sessionUri -Method Post ` -Headers @{ 'Accept' = 'application/json' 'Content-Type' = 'application/json' } ` -Body (ConvertTo-Json $body) ` -MaximumRedirection 0 $parms = @{} if ($PSVersionTable.PSVersion.Major -ge 7) { $parms['Depth'] = 10 } $session = $trans.Content | ConvertFrom-Json @parms } catch { $e = $_ try { if ($_.Exception.Response.StatusCode -eq 'Unauthorized') { Write-Warning "Unauthorzied response. Proabably base userName or password" return } else { throw $e } } catch { throw $e } } if (!$session) { Write-Warning "Didn't get session" return } try { $tokenUri = New-Object 'System.Uri' -ArgumentList $uri,($uri.PathAndQuery+"/v1/authorize?" + "response_type=$(ternary $IdToken 'id_token' 'token')&" + "scope=$($scopes -join '%20')&" + 'state=TEST&' + 'nonce=TEST&' + "client_id=$ClientId&" + "redirect_uri=$redirectUri&" + "sessionToken=$($session.sessionToken)") Write-Verbose "Token uri is $tokenUri" $null = Invoke-WebRequest $tokenUri -MaximumRedirection 0 } catch { # expect 302 response Write-Verbose "$_`n$($_.ScriptStackTrace)" $e = $_ if ($e.Exception.Response.StatusCode -eq "Redirect") { #302 Write-Verbose $e.Exception.Response.Headers.Location $q = [System.Web.HttpUtility]::ParseQueryString($e.Exception.Response.Headers.Location) Write-Verbose "Headers are: $($e.Exception.Response.Headers)" Write-Verbose "Headers.Location is: $($e.Exception.Response.Headers.Location)" Write-Verbose "Keys:" Write-Verbose ($q.AllKeys | Out-String) if ($IdToken) { $token = $q["$redirectUri#id_token"] } else { $token = $q["$redirectUri#access_token"] } if (!$token) { Write-Warning "Didn't get token" } $token } else { Write-Warning "Didn't get redirect for JWT" Write-Warning $_ } } } else { $clientCreds = [System.Text.Encoding]::UTF8.GetBytes("${ClientId}:$secret"); $oktaHeader = @{ Authorization = "Basic $([System.Convert]::ToBase64String($clientCreds))" Accept = "application/json" } $body = "grant_type=$GrantType&scope=$($Scopes -join '%20')" # space-separated scopes $parms = @{} if ($PSVersionTable.PSVersion.Major -ge 7) { $parms['SkipHttpErrorCheck'] = $true } $jwt = "" Write-Verbose $body $result = Invoke-WebRequest $Issuer -Method Post -Body $body -ContentType "application/x-www-form-urlencoded" -Headers $oktaHeader @parms if ($result.StatusCode -ne 200) { Write-Warning "Couldn't get JWT" Write-Warning $result } else { $parms = @{} if ($PSVersionTable.PSVersion.Major -ge 7) { $parms['Depth'] = 5 } $jwt = (ConvertFrom-Json $result.Content @parms).access_token } $jwt } } |