How to retrieve all Okta groups including their members using Powershell

Okta exposes a very useful API, with which I’ve been working for a while to ensure business fit for certain scenario’s that Okta and/or Office 365/Azure don’t fully support yet.

One of those scenario’s requires information about certain groups and their members. I’m narrowing the selection down to just pure Okta groups, but any groups (e.g. AD Synced) can be returned with below code by adjusting the filter in the retrieveAllOktaGroups function.

  1. First, you will need an Okta token to use with Powershell’s REST functions, this is the easiest part.
  2. Okta’s API’s are customer specific, so your $OktaAPIBaseURL parameter should be something like “https://companyname.okta.com”
  3. Run the retrieveAllOktaGroupsAndMembers function below with the token as a parameter
  4. Remember that Okta tokens expire if not used for a while

function Invoke-PagedMethod {
    Param(
        $url,
        $authHeader
    )
    try{
        $response = Invoke-WebRequest $url -Method GET -Headers $authHeader -ErrorAction Stop
        $links = @{}
        if ($response.Headers.Link) {
            foreach ($header in $response.Headers.Link.split(",")) {
                if ($header -match '<(.*)>; rel="(.*)"') {
                    $links[$matches[2]] = $matches[1]
                }
            }
        }
        @{objects = ConvertFrom-Json $response.content; nextUrl = $links.next}
    }catch{
        Throw $_
    }
}

function buildOktaAuthHeader{
    Param(
        [Parameter(Mandatory=$true)]$oktaToken
    )    
    $authHeader = @{
    'Content-Type'='application/json'
    'Accept'='application/json'
    'Authorization'= 'SSWS '+$oktaToken
    }
    return $authHeader
}

function retrieveAllOktaGroups{
    Param(
        [Parameter(Mandatory=$true)]$oktaToken,
        [Parameter(Mandatory=$true)]$oktaAPIBaseURL
    )  
    $authHeader = buildOktaAuthHeader -oktaToken $oktaToken  
    $groups = @()
    $res = @{"nextURL"="$oktaAPIBaseURL/api/v1/groups?limit=200&filter=type eq `"OKTA_GROUP`""}
    while($true){
        try{
            if($res.nextURL -eq $Null){
                write-verbose "finished retireveAllOktaUsers function"
                break;
            }
            $res = Invoke-PagedMethod –Url $res.nextURL -authHeader $authHeader -Method GET
            if($res.objects){
                $groups += $res.objects
            }
            write-verbose "retrieved $($groups.Count) groups..."
        }catch{
            Throw "failed to retrieve groups from Okta: $_"
        }
    }    
    return $groups  
}

function retrieveOktaGroupMembers{
    Param(
        $oktaToken,
        $groupHref
    )
    $authHeader = buildOktaAuthHeader -oktaToken $oktaToken
    $members = @()
    $res = @{"nextURL"="$($groupHref)?limit=200"}
    while($true){
        try{
            if($res.nextURL -eq $Null){
                write-verbose "finished paged function"
                break;
            }
            $res = Invoke-PagedMethod –Url $res.nextURL -authHeader $authHeader -Method GET
            if($res.objects){
                $members += $res.objects
            }
            write-verbose "retrieved $($members.Count) members..."
        }catch{
            Throw "failed to retrieve members from Okta: $_"
        }
    }    
    return $members  
}

function retrieveAllOktaGroupsAndMembers{
    Param(
        $oktaToken,
        $oktaAPIBaseURL
    )
    $groupsAndMembers = @()
    foreach($group in (retrieveAllOktaGroups -oktaToken $oktaToken -oktaAPIBaseURL $oktaAPIBaseURL)){
        $groupMembers = retrieveOktaGroupMembers -oktaToken $oktaToken -groupHref $group._links.users.href
        if($groupMembers){
            Write-Verbose "Adding $($groupMembers.Count) members to group"
            $group | Add-Member -MemberType NoteProperty -Name "Members" -Value $groupMembers
        }
        $groupsAndMembers+=$group
    }
    return $groupsAndMembers
}
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

7 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
josh
josh
1 year ago

this was a really good script. I would love to see an example on how you pass the parameter and how the values return. overall a quality share

harry
harry
6 years ago

Hi Jos, how can we edit the script to look for single group. Can you please help me there

trackback

[…] To use this script, you’ll need an Okta token […]