12Knocksinna / Office365itpros

Office 365 for IT Pros PowerShell examples

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

(401) Unauthorized - TeamsGroupsActivityReportV5

antondreyer opened this issue · comments

Good day, and thanks for the script.
I think I am running into an issue where the Token isn't refreshing a second time - it's on a tenant with 50k+ teams

After about an hour I can see it saying it refreshed the token, and then after another hour it starts returning "The remote server returned an error: (401) Unauthorized."

By limiting the number of groups it loops through to 10 I did get a successful run, so i don't think its graph permissions

Does the script handle multiple refreshes of the token in all the loops that take a long time?

There's a loop in the script to get a refreshed token after 59 minutes.

Check if token is older than 50 minutes and request a refresh token

    $TimeRightNow = (Get-date)
    if($TimeRightNow  -ge $TokenExpiredDate){
        $body = @{
            client_id     = $AppId
            scope         = "https://graph.microsoft.com/.default"
            client_secret = $AppSecret
            grant_type    = "client_credentials"
        }
        
        $Params = @{
            'Uri' = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
            'Method' = 'Post'
            'Body' = $Body
            'ContentType' = 'application/x-www-form-urlencoded'
        }
        
    # Get OAuth 2.0 Token
    try{
        $Refreshtoken = Invoke-RestMethod @Params
    }
    catch{
        Write-Host "An error occurred:"
        Write-Host $_ -ForegroundColor Red
        Write-ErrorLog 'An error occurred: {Error}' -PropertyValues $_
    }
    # Unpack Access Token
    
    if ($null -ne $Refreshtoken) {
        $Token = $Refreshtoken.access_token
        Write-Host "Token Refreshed at $TimeRightNow" -ForegroundColor Red
    }
    else {Write-Host "Not refreshed, Token is empty" -ForegroundColor Red}
    $TokenExpiredDate = (Get-date).AddMinutes($TimeToRefreshToken) 
    }
#### END of Check if token is older than 50 minutes and request a refresh token #######

Looking at the code, it seems like it works for once through the refresh loop but maybe fails after that. Perhaps if you chance the unpack access token code to that shown below it will work for multiple loops.

    # Unpack Access Token
    
    if ($null -ne $Refreshtoken) {
        $Token = $Refreshtoken.access_token
        Write-Host "Token Refreshed at $TimeRightNow" -ForegroundColor Red
        $TokenCreationDate = (Get-Date)
        $TokenExpiredDate = (Get-Date).AddMinutes($TimeToRefreshToken) 

Unfortunately still the same result

# Unpack Access Token

if ($null -ne $Refreshtoken) {

should $Refreshtoken not perhaps be set to null somewhere so it can evaluate true on the next run?

Also not sure if "$TokenCreationDate = (Get-Date)" serves any purpose? Doesnt seem to be used anywhere

It's no excuse, but another contributor added that piece of code. I will get to testing and refining it some time. Finding 40K teams to test it against might be a challenge...

I did some testing...

I moved the code to get an access token into a function

`function GetAccessToken {

function to return an Oauth access token

Define the values applicable for the application used to connect to the Graph

$AppId = "828e1143-88e3-492b-bf82-24c4a47ada63"
$TenantId = "b662313f-14fc-43a2-9a7a-d2e27f4f3478"
$AppSecret = 'sK78Q~EYQVuAU5EURRtTZhl4uH-e-WAinDEfqaMW'

Construct URI and body needed for authentication

$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body = @{
client_id = $AppId
scope = "https://graph.microsoft.com/.default"
client_secret = $AppSecret
grant_type = "client_credentials"
}

Get OAuth 2.0 Token

$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing

Unpack Access Token

$Token = ($tokenRequest.Content | ConvertFrom-Json).access_token

Return $Token
}
`

and then replaced all the code that's currently in place to check for token renewal with:

Check if token needs to be refreshed. If it does, request a new token

    $TimeNow = (Get-Date)
    if($TimeNow -ge $TokenExpiredDate){
       $Token = GetAccessToken
       $TokenExpiredDate = (Get-date).AddMinutes($TimeToRefreshToken) 
       Write-Host "Requested new access token - expiration at" $TokenExpiredDate 
    }
        
#### END of Check if token is older than 50 minutes and request a refresh token #######

I changed the token renewal check to 3 minutes and the script ran as expected with renewal happening on schedule. You can apply the change to your script and try it out or wait until I get done with another change that I want to make (sometime soon).

I've updated the script to V5.5. This version includes the changes to improve token handling.